diff --git a/rippled-example.cfg b/rippled-example.cfg index 8bd553b9c..6eb7172bf 100644 --- a/rippled-example.cfg +++ b/rippled-example.cfg @@ -211,6 +211,11 @@ # Examples: RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE # shfArahZT9Q9ckTf3s1psJ7C7qzVN # +# [node_size]: +# Tunes the servers based on the expected load and available memory. Legal +# sizes are "tiny", "small", "medium", "large", and "huge". +# The default is "tiny". +# # [cluster_nodes]: # To extend full trust to other nodes, place their node public keys here. # Generally, you should only do this for nodes under common administration. diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index 58b75e8b4..09e37a2e4 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -50,7 +50,7 @@ Application::Application() : getRand(mNonce256.begin(), mNonce256.size()); getRand(reinterpret_cast(&mNonceST), sizeof(mNonceST)); mJobQueue.setThreadCount(); - mSweepTimer.expires_from_now(boost::posix_time::seconds(60)); + mSweepTimer.expires_from_now(boost::posix_time::seconds(20)); mSweepTimer.async_wait(boost::bind(&Application::sweep, this)); } @@ -159,6 +159,9 @@ void Application::setup() if (!theConfig.RUN_STANDALONE) getUNL().nodeBootstrap(); + mValidations.tune(theConfig.getSize(siValidationsSize), theConfig.getSize(siValidationsAge)); + mHashedObjectStore.tune(theConfig.getSize(siNodeCacheSize), theConfig.getSize(siNodeCacheAge)); + mLedgerMaster.tune(theConfig.getSize(siLedgerSize), theConfig.getSize(siLedgerAge)); // // Allow peer connections. @@ -294,7 +297,7 @@ void Application::sweep() mTempNodeCache.sweep(); mValidations.sweep(); getMasterLedgerAcquire().sweep(); - mSweepTimer.expires_from_now(boost::posix_time::seconds(60)); + mSweepTimer.expires_from_now(boost::posix_time::seconds(theConfig.getSize(siSweepInterval))); mSweepTimer.async_wait(boost::bind(&Application::sweep, this)); } diff --git a/src/cpp/ripple/Config.cpp b/src/cpp/ripple/Config.cpp index d45d35d65..f26e7ff8b 100644 --- a/src/cpp/ripple/Config.cpp +++ b/src/cpp/ripple/Config.cpp @@ -27,6 +27,7 @@ #define SECTION_IPS "ips" #define SECTION_NETWORK_QUORUM "network_quorum" #define SECTION_NODE_SEED "node_seed" +#define SECTION_NODE_SIZE "node_size" #define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water" #define SECTION_PEER_IP "peer_ip" #define SECTION_PEER_PORT "peer_port" @@ -81,8 +82,9 @@ void Config::setup(const std::string& strConf, bool bTestNet, bool bQuiet) // that with "db" as the data directory. // - TESTNET = bTestNet; - QUIET = bQuiet; + TESTNET = bTestNet; + QUIET = bQuiet; + NODE_SIZE = 0; // TESTNET forces a "testnet-" prefix on the conf file and db directory. strDbPath = TESTNET ? "testnet-db" : "db"; @@ -329,6 +331,28 @@ void Config::load() if (sectionSingleB(secConfig, SECTION_RPC_ALLOW_REMOTE, strTemp)) RPC_ALLOW_REMOTE = boost::lexical_cast(strTemp); + if (sectionSingleB(secConfig, SECTION_NODE_SIZE, strTemp)) + { + if (strTemp == "tiny") + NODE_SIZE = 0; + else if (strTemp == "small") + NODE_SIZE = 1; + else if (strTemp == "medium") + NODE_SIZE = 2; + else if (strTemp == "large") + NODE_SIZE = 3; + else if (strTemp == "huge") + NODE_SIZE = 4; + else + { + NODE_SIZE = boost::lexical_cast(strTemp); + if (NODE_SIZE < 0) + NODE_SIZE = 0; + else if (NODE_SIZE > 4) + NODE_SIZE = 4; + } + } + (void) sectionSingleB(secConfig, SECTION_WEBSOCKET_IP, WEBSOCKET_IP); if (sectionSingleB(secConfig, SECTION_WEBSOCKET_PORT, strTemp)) @@ -427,4 +451,27 @@ void Config::load() } } +int Config::getSize(SizedItemName item) +{ + SizedItem sizeTable[] = { + { siSweepInterval, { 10, 30, 60, 90, 90 } }, + { siLedgerFetch, { 2, 4, 10, 10, 10 } }, + { siValidationsSize, { 256, 256, 512, 1024, 1024 } }, + { siValidationsAge, { 500, 500, 500, 500, 500 } }, + { siNodeCacheSize, { 8192, 32768, 131072, 1048576, 0 } }, + { siNodeCacheAge, { 30, 60, 90, 300, 600 } }, + { siLedgerSize, { 32, 64, 128, 1024, 0 } }, + { siLedgerAge, { 30, 60, 120, 300, 600 } }, + }; + + for (int i = 0; i < (sizeof(sizeTable) / sizeof(SizedItem)); ++i) + { + if (sizeTable[i].item == item) + return sizeTable[i].sizes[NODE_SIZE]; + } + assert(false); + return -1; +} + + // vim:ts=4 diff --git a/src/cpp/ripple/Config.h b/src/cpp/ripple/Config.h index 6fe20fcc4..904f12ca9 100644 --- a/src/cpp/ripple/Config.h +++ b/src/cpp/ripple/Config.h @@ -48,6 +48,24 @@ const int SYSTEM_WEBSOCKET_PUBLIC_PORT = 6563; // XXX Going away. // Might connect with fewer for testing. #define DEFAULT_PEER_CONNECT_LOW_WATER 4 +enum SizedItemName +{ + siSweepInterval, + siValidationsSize, + siValidationsAge, + siNodeCacheSize, + siNodeCacheAge, + siLedgerSize, + siLedgerAge, + siLedgerFetch, +}; + +struct SizedItem +{ + SizedItemName item; + int sizes[5]; +}; + class Config { public: @@ -139,6 +157,7 @@ public: // Node storage configuration uint32 LEDGER_HISTORY; + int NODE_SIZE; // Client behavior int ACCOUNT_PROBE_MAX; // How far to scan for accounts. @@ -150,6 +169,7 @@ public: Config(); + int getSize(SizedItemName); void setup(const std::string& strConf, bool bTestNet, bool bQuiet); void load(); }; diff --git a/src/cpp/ripple/HashedObject.cpp b/src/cpp/ripple/HashedObject.cpp index d5e248f2e..9cc0636c6 100644 --- a/src/cpp/ripple/HashedObject.cpp +++ b/src/cpp/ripple/HashedObject.cpp @@ -20,6 +20,12 @@ HashedObjectStore::HashedObjectStore(int cacheSize, int cacheAge) : mWriteSet.reserve(128); } +void HashedObjectStore::tune(int size, int age) +{ + mCache.setTargetSize(size); + mCache.setTargetAge(age); +} + bool HashedObjectStore::store(HashedObjectType type, uint32 index, const std::vector& data, const uint256& hash) diff --git a/src/cpp/ripple/HashedObject.h b/src/cpp/ripple/HashedObject.h index d96101370..74fc7a142 100644 --- a/src/cpp/ripple/HashedObject.h +++ b/src/cpp/ripple/HashedObject.h @@ -67,6 +67,7 @@ public: void bulkWrite(); void waitWrite(); + void tune(int size, int age); void sweep() { mCache.sweep(); mNegativeCache.sweep(); } int import(const std::string&); diff --git a/src/cpp/ripple/LedgerHistory.cpp b/src/cpp/ripple/LedgerHistory.cpp index dc30e87e3..39aab0a04 100644 --- a/src/cpp/ripple/LedgerHistory.cpp +++ b/src/cpp/ripple/LedgerHistory.cpp @@ -115,4 +115,10 @@ Ledger::pointer LedgerHistory::canonicalizeLedger(Ledger::pointer ledger, bool s return ledger; } +void LedgerHistory::tune(int size, int age) +{ + mLedgersByHash.setTargetSize(size); + mLedgersByHash.setTargetAge(age); +} + // vim:ts=4 diff --git a/src/cpp/ripple/LedgerHistory.h b/src/cpp/ripple/LedgerHistory.h index 965ac492a..9ee0ed9e8 100644 --- a/src/cpp/ripple/LedgerHistory.h +++ b/src/cpp/ripple/LedgerHistory.h @@ -19,6 +19,7 @@ public: Ledger::pointer getLedgerBySeq(uint32 index); Ledger::pointer getLedgerByHash(const uint256& hash); Ledger::pointer canonicalizeLedger(Ledger::pointer, bool cache); + void tune(int size, int age); void sweep() { mLedgersByHash.sweep(); } }; diff --git a/src/cpp/ripple/LedgerMaster.cpp b/src/cpp/ripple/LedgerMaster.cpp index e27c35007..2f52d9cfd 100644 --- a/src/cpp/ripple/LedgerMaster.cpp +++ b/src/cpp/ripple/LedgerMaster.cpp @@ -195,7 +195,8 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l theApp->getIOService().post(boost::bind(&LedgerMaster::missingAcquireComplete, this, mMissingLedger)); } - if (theApp->getMasterLedgerAcquire().getFetchCount() < 4) + int fetch = theConfig.getSize(siLedgerFetch); + if (theApp->getMasterLedgerAcquire().getFetchCount() < fetch) { int count = 0; typedef std::pair u_pair; @@ -203,7 +204,7 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l std::vector vec = origLedger->getLedgerHashes(); BOOST_REVERSE_FOREACH(const u_pair& it, vec) { - if ((count < 3) && (it.first < ledgerSeq) && + if ((count < fetch) && (it.first < ledgerSeq) && !mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second)) { ++count; diff --git a/src/cpp/ripple/LedgerMaster.h b/src/cpp/ripple/LedgerMaster.h index dac64c862..dfcf8ef2e 100644 --- a/src/cpp/ripple/LedgerMaster.h +++ b/src/cpp/ripple/LedgerMaster.h @@ -129,6 +129,7 @@ public: void resumeAcquiring(); + void tune(int size, int age) { mLedgerHistory.tune(size, age); } void sweep(void) { mLedgerHistory.sweep(); } void addValidateCallback(callback& c) { mOnValidate.push_back(c); } diff --git a/src/cpp/ripple/ValidationCollection.cpp b/src/cpp/ripple/ValidationCollection.cpp index 8101d5f51..5d34e59ec 100644 --- a/src/cpp/ripple/ValidationCollection.cpp +++ b/src/cpp/ripple/ValidationCollection.cpp @@ -12,6 +12,12 @@ SETUP_LOG(); typedef std::map::value_type u160_val_pair; typedef boost::shared_ptr VSpointer; +void ValidationCollection::tune(int size, int age) +{ + mValidations.setTargetSize(size); + mValidations.setTargetAge(age); +} + VSpointer ValidationCollection::findCreateSet(const uint256& ledgerHash) { VSpointer j = mValidations.fetch(ledgerHash); diff --git a/src/cpp/ripple/ValidationCollection.h b/src/cpp/ripple/ValidationCollection.h index b65559f79..7bba8bad4 100644 --- a/src/cpp/ripple/ValidationCollection.h +++ b/src/cpp/ripple/ValidationCollection.h @@ -48,6 +48,7 @@ public: boost::unordered_map getCurrentValidations(uint256 currentLedger); std::list getCurrentTrustedValidations(); + void tune(int size, int age); void flush(); void sweep() { mValidations.sweep(); } };