Skip to content

Commit dd5b7eb

Browse files
committed
Support reusable module cache with multithreaded pre-compilation
1 parent d7136b5 commit dd5b7eb

16 files changed

+794
-18
lines changed

src/catchup/AssumeStateWork.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "crypto/Hex.h"
1010
#include "history/HistoryArchive.h"
1111
#include "invariant/InvariantManager.h"
12+
#include "ledger/LedgerManager.h"
1213
#include "work/WorkSequence.h"
1314
#include "work/WorkWithCallback.h"
1415

@@ -78,6 +79,10 @@ AssumeStateWork::doWork()
7879
// now referenced by BucketList
7980
buckets.clear();
8081

82+
// Compile all live BL entries once we assume a new state.
83+
app.getLedgerManager().compileAllContractsInLedger(
84+
maxProtocolVersion);
85+
8186
// Check invariants after state has been assumed
8287
app.getInvariantManager().checkAfterAssumeState(has.currentLedger);
8388

src/ledger/LedgerManager.h

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "catchup/LedgerApplyManager.h"
88
#include "history/HistoryManager.h"
99
#include "ledger/NetworkConfig.h"
10+
#include "rust/RustBridge.h"
1011
#include <memory>
1112

1213
namespace stellar
@@ -200,6 +201,12 @@ class LedgerManager
200201
virtual void manuallyAdvanceLedgerHeader(LedgerHeader const& header) = 0;
201202

202203
virtual SorobanMetrics& getSorobanMetrics() = 0;
204+
virtual rust_bridge::SorobanModuleCache& getModuleCache() = 0;
205+
206+
// Compiles all contracts in the current ledger, for ledger protocols
207+
// starting at minLedgerVersion and running through to
208+
// Config::CURRENT_LEDGER_PROTOCOL_VERSION (to enable upgrades).
209+
virtual void compileAllContractsInLedger(uint32_t minLedgerVersion) = 0;
203210

204211
virtual ~LedgerManager()
205212
{

src/ledger/LedgerManagerImpl.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
#include "history/HistoryManager.h"
2121
#include "ledger/FlushAndRotateMetaDebugWork.h"
2222
#include "ledger/LedgerHeaderUtils.h"
23+
#include "ledger/LedgerManager.h"
2324
#include "ledger/LedgerTxn.h"
2425
#include "ledger/LedgerTxnEntry.h"
2526
#include "ledger/LedgerTxnHeader.h"
27+
#include "ledger/SharedModuleCacheCompiler.h"
2628
#include "main/Application.h"
2729
#include "main/Config.h"
2830
#include "main/ErrorMessages.h"
31+
#include "rust/RustBridge.h"
2932
#include "transactions/MutableTransactionResult.h"
3033
#include "transactions/OperationFrame.h"
3134
#include "transactions/TransactionFrameBase.h"
@@ -41,8 +44,10 @@
4144
#include "util/XDRCereal.h"
4245
#include "util/XDRStream.h"
4346
#include "work/WorkScheduler.h"
47+
#include "xdr/Stellar-ledger-entries.h"
4448
#include "xdrpp/printer.h"
4549

50+
#include <cstdint>
4651
#include <fmt/format.h>
4752

4853
#include "xdr/Stellar-ledger-entries.h"
@@ -125,6 +130,27 @@ LedgerManager::ledgerAbbrev(LedgerHeaderHistoryEntry const& he)
125130
return ledgerAbbrev(he.header, he.hash);
126131
}
127132

133+
static std::vector<uint32_t>
134+
getModuleCacheProtocols()
135+
{
136+
std::vector<uint32_t> ledgerVersions;
137+
for (uint32_t i = (uint32_t)REUSABLE_SOROBAN_MODULE_CACHE_PROTOCOL_VERSION;
138+
i <= Config::CURRENT_LEDGER_PROTOCOL_VERSION; i++)
139+
{
140+
ledgerVersions.push_back(i);
141+
}
142+
auto extra = getenv("SOROBAN_TEST_EXTRA_PROTOCOL");
143+
if (extra)
144+
{
145+
uint32_t proto = static_cast<uint32_t>(atoi(extra));
146+
if (proto > 0)
147+
{
148+
ledgerVersions.push_back(proto);
149+
}
150+
}
151+
return ledgerVersions;
152+
}
153+
128154
LedgerManagerImpl::LedgerManagerImpl(Application& app)
129155
: mApp(app)
130156
, mSorobanMetrics(app.getMetrics())
@@ -157,6 +183,8 @@ LedgerManagerImpl::LedgerManagerImpl(Application& app)
157183
, mCatchupDuration(
158184
app.getMetrics().NewTimer({"ledger", "catchup", "duration"}))
159185
, mState(LM_BOOTING_STATE)
186+
, mModuleCache(::rust_bridge::new_module_cache())
187+
, mModuleCacheProtocols(getModuleCacheProtocols())
160188

161189
{
162190
setupLedgerCloseMetaStream();
@@ -405,6 +433,9 @@ LedgerManagerImpl::loadLastKnownLedger(bool restoreBucketlist)
405433
updateNetworkConfig(ltx);
406434
mSorobanNetworkConfigReadOnly = mSorobanNetworkConfigForApply;
407435
}
436+
437+
// Prime module cache with ledger content.
438+
compileAllContractsInLedger(latestLedgerHeader->ledgerVersion);
408439
}
409440

410441
Database&
@@ -568,6 +599,30 @@ LedgerManagerImpl::getSorobanMetrics()
568599
return mSorobanMetrics;
569600
}
570601

602+
rust_bridge::SorobanModuleCache&
603+
LedgerManagerImpl::getModuleCache()
604+
{
605+
return *mModuleCache;
606+
}
607+
608+
void
609+
LedgerManagerImpl::compileAllContractsInLedger(uint32_t minLedgerVersion)
610+
{
611+
auto& moduleCache = getModuleCache();
612+
moduleCache.clear();
613+
std::vector<uint32_t> versions;
614+
for (auto const& v : mModuleCacheProtocols)
615+
{
616+
if (v >= minLedgerVersion)
617+
{
618+
versions.push_back(v);
619+
}
620+
}
621+
auto compiler = std::make_shared<SharedModuleCacheCompiler>(
622+
mApp, moduleCache, versions);
623+
compiler->run();
624+
}
625+
571626
void
572627
LedgerManagerImpl::publishSorobanMetrics()
573628
{
@@ -1812,6 +1867,8 @@ LedgerManagerImpl::transferLedgerEntriesToBucketList(
18121867
ledgerCloseMeta->populateEvictedEntries(evictedState);
18131868
}
18141869

1870+
evictFromModuleCache(lh.ledgerVersion, evictedState);
1871+
18151872
ltxEvictions.commit();
18161873
}
18171874

@@ -1822,6 +1879,8 @@ LedgerManagerImpl::transferLedgerEntriesToBucketList(
18221879
ltx.getAllEntries(initEntries, liveEntries, deadEntries);
18231880
if (blEnabled)
18241881
{
1882+
addAnyContractsToModuleCache(lh.ledgerVersion, initEntries);
1883+
addAnyContractsToModuleCache(lh.ledgerVersion, liveEntries);
18251884
mApp.getBucketManager().addLiveBatch(mApp, lh, initEntries, liveEntries,
18261885
deadEntries);
18271886
}
@@ -1882,4 +1941,43 @@ LedgerManagerImpl::ledgerClosed(
18821941

18831942
return res;
18841943
}
1944+
1945+
void
1946+
LedgerManagerImpl::evictFromModuleCache(uint32_t ledgerVersion,
1947+
EvictedStateVectors const& evictedState)
1948+
{
1949+
::rust::Vec<CxxBuf> contractCodeKeys;
1950+
for (auto const& entry : evictedState.archivedEntries)
1951+
{
1952+
if (entry.data.type() == CONTRACT_CODE)
1953+
{
1954+
Hash const& hash = entry.data.contractCode().hash;
1955+
::rust::Slice<uint8_t const> slice{hash.data(), hash.size()};
1956+
mModuleCache->evict_contract_code(slice);
1957+
}
1958+
}
1959+
}
1960+
1961+
void
1962+
LedgerManagerImpl::addAnyContractsToModuleCache(
1963+
uint32_t ledgerVersion, std::vector<LedgerEntry> const& le)
1964+
{
1965+
for (auto const& e : le)
1966+
{
1967+
if (e.data.type() == CONTRACT_CODE)
1968+
{
1969+
for (auto const& v : mModuleCacheProtocols)
1970+
{
1971+
if (v >= ledgerVersion)
1972+
{
1973+
auto const& wasm = e.data.contractCode().code;
1974+
auto slice =
1975+
rust::Slice<const uint8_t>(wasm.data(), wasm.size());
1976+
mModuleCache->compile(ledgerVersion, slice);
1977+
}
1978+
}
1979+
}
1980+
}
1981+
}
1982+
18851983
}

src/ledger/LedgerManagerImpl.h

+14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "ledger/NetworkConfig.h"
1212
#include "ledger/SorobanMetrics.h"
1313
#include "main/PersistentState.h"
14+
#include "rust/RustBridge.h"
1415
#include "transactions/TransactionFrame.h"
1516
#include "util/XDRStream.h"
1617
#include "xdr/Stellar-ledger.h"
@@ -152,6 +153,12 @@ class LedgerManagerImpl : public LedgerManager
152153
// Update cached ledger state values managed by this class.
153154
void advanceLedgerPointers(CloseLedgerOutput const& output);
154155

156+
// The reusable / inter-ledger soroban module cache.
157+
::rust::Box<rust_bridge::SorobanModuleCache> mModuleCache;
158+
159+
// Protocol versions to compile each contract for in the module cache.
160+
std::vector<uint32_t> mModuleCacheProtocols;
161+
155162
protected:
156163
// initialLedgerVers must be the ledger version at the start of the ledger
157164
// and currLedgerVers is the ledger version in the current ltx header. These
@@ -175,6 +182,11 @@ class LedgerManagerImpl : public LedgerManager
175182
void logTxApplyMetrics(AbstractLedgerTxn& ltx, size_t numTxs,
176183
size_t numOps);
177184

185+
void evictFromModuleCache(uint32_t ledgerVersion,
186+
EvictedStateVectors const& evictedState);
187+
void addAnyContractsToModuleCache(uint32_t ledgerVersion,
188+
std::vector<LedgerEntry> const& le);
189+
178190
public:
179191
LedgerManagerImpl(Application& app);
180192

@@ -251,5 +263,7 @@ class LedgerManagerImpl : public LedgerManager
251263
{
252264
return mCurrentlyApplyingLedger;
253265
}
266+
rust_bridge::SorobanModuleCache& getModuleCache() override;
267+
void compileAllContractsInLedger(uint32_t minLedgerVersion) override;
254268
};
255269
}

0 commit comments

Comments
 (0)