Skip to content

Commit c23cc9a

Browse files
committed
Various memory-measuring improvements
1 parent 0d3f561 commit c23cc9a

16 files changed

Lines changed: 170 additions & 42 deletions

Builds/VisualStudio/stellar-core.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ exit /b 0
908908
<ClCompile Include="..\..\src\util\test\Uint128Tests.cpp" />
909909
<ClCompile Include="..\..\src\util\test\XDRStreamTests.cpp" />
910910
<ClCompile Include="..\..\src\util\TarjanSCCCalculator.cpp" />
911+
<ClCompile Include="..\..\src\util\TcmallocConfig.cpp" />
911912
<ClCompile Include="..\..\src\util\Thread.cpp" />
912913
<ClCompile Include="..\..\src\util\TmpDir.cpp" />
913914
<ClCompile Include="..\..\src\util\Timer.cpp" />
@@ -1280,6 +1281,7 @@ exit /b 0
12801281
<ClInclude Include="..\..\src\util\SociNoWarnings.h" />
12811282
<ClInclude Include="..\..\src\util\StatusManager.h" />
12821283
<ClInclude Include="..\..\src\util\TarjanSCCCalculator.h" />
1284+
<ClInclude Include="..\..\src\util\TcmallocConfig.h" />
12831285
<ClInclude Include="..\..\src\util\Thread.h" />
12841286
<ClInclude Include="..\..\src\util\TmpDir.h" />
12851287
<ClInclude Include="..\..\src\util\Timer.h" />

Builds/VisualStudio/stellar-core.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,9 @@
489489
<ClCompile Include="..\..\src\util\TarjanSCCCalculator.cpp">
490490
<Filter>util</Filter>
491491
</ClCompile>
492+
<ClCompile Include="..\..\src\util\TcmallocConfig.cpp">
493+
<Filter>util</Filter>
494+
</ClCompile>
492495
<ClCompile Include="..\..\src\util\Thread.cpp">
493496
<Filter>util</Filter>
494497
</ClCompile>
@@ -1737,6 +1740,9 @@
17371740
<ClInclude Include="..\..\src\util\TarjanSCCCalculator.h">
17381741
<Filter>util</Filter>
17391742
</ClInclude>
1743+
<ClInclude Include="..\..\src\util\TcmallocConfig.h">
1744+
<Filter>util</Filter>
1745+
</ClInclude>
17401746
<ClInclude Include="..\..\src\util\Thread.h">
17411747
<Filter>util</Filter>
17421748
</ClInclude>

INSTALL.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,15 @@ The GUI depends on the `capstone`, `freetype` and `glfw` libraries and their hea
268268

269269
# On MacOS
270270
$ brew install capstone freetype2 glfw
271+
272+
On Windows, follow the [build and install instructions](https://github.com/wolfpld/tracy) from the main Tracy site.
273+
274+
At a high level you need to install the required prerequisites to build clients, run in a shell:
275+
276+
vcpkg.exe integrate install
277+
vcpkg.exe install --triplet x64-windows-static capstone freetype glfw3
278+
279+
Then build one of the servers. Solutions for servers compatible with the version of stellar-core can be found under:
280+
281+
* lib/tracy/profiler/build/win32 (GUI)
282+
* lib/tracy/capture/build/win32

common.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ if USE_TRACY
3131
AM_CPPFLAGS += -DUSE_TRACY $(tracy_CFLAGS)
3232
endif # USE_TRACY
3333

34+
if USE_TRACY_MEMORY_TRACKING
35+
AM_CPPFLAGS += -DUSE_TRACY_MEMORY_TRACKING
36+
endif # USE_TRACY_MEMORY_TRACKING
37+
3438
if BUILD_TESTS
3539
AM_CPPFLAGS += -DBUILD_TESTS=1
3640
endif # BUILD_TESTS

configure.ac

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,12 @@ AC_ARG_ENABLE(tracy-memory-tracking,
534534
AS_HELP_STRING([--enable-tracy-memory-tracking],
535535
[Enable 'tracy' profiler/tracer memory tracking code (slow)]))
536536
AM_CONDITIONAL(USE_TRACY_MEMORY_TRACKING, [test x$enable_tracy_memory_tracking = xyes])
537-
537+
if test x"$enable_tracy_memory_tracking" = xyes -a x"$have_tcmalloc" = x1; then
538+
AC_MSG_ERROR([--enable-tracy-memory-tracking requires --disable-tcmalloc])
539+
fi
540+
if test x"$enable_tracy_memory_tracking" = xyes -a x"$enable_tracy" != xyes; then
541+
AC_MSG_ERROR([--enable-tracy-memory-tracking requires --enable-tracy])
542+
fi
538543
if test x"$enable_tracy" = xyes -a x"$enable_asan" = xyes; then
539544
AC_MSG_ERROR([--enable-asan is not compatible with --enable-tracy])
540545
fi

docs/metrics.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ soroban.config.bucket-list-target-size-byte | counter | soroban config settin
284284
soroban.module-cache.num-entries | counter | current number of entries in module cache
285285
soroban.module-cache.compilation-time | timer | times each contract compilation when adding to module cache
286286
soroban.module-cache.rebuild-time | timer | times each rebuild of module cache (including all compilations)
287-
soroban.module-cache.rebuild-bytes | counter | bytes of WASM bytecode compiled in last rebuild of module cache
287+
soroban.module-cache.rebuild-wasm-bytes | counter | bytes of WASM bytecode compiled in last rebuild of module cache
288+
soroban.module-cache.rebuild-heap-bytes | counter | bytes of heap memory allocated in last rebuild of module cache
288289
soroban.in-memory-state.contract-code-size | counter | size in bytes of non-evicted ContractCode entries according to memory cost model
289290
soroban.in-memory-state.contract-data-size | counter | size in bytes of ContractData entries in memory
290291
soroban.in-memory-state.contract-code-entries | counter | number of ContractCode entries in memory

performance-eval/performance-eval.md

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,28 +294,84 @@ solution is, as root to run
294294

295295
Stellar-core has built-in support for Tracy traces.
296296

297-
To install the visualizer, follow the [build and install instructions](https://github.com/wolfpld/tracy) from the main Tracy site.
297+
To install the visualizer, follow the directions in [INSTALL.md](../INSTALL.md).
298298

299-
At a high level you need to
299+
### General Visual Studio profiler
300300

301-
install the required pre-requesites to build clients, run in a shell:
301+
The main page for the profiler built into Visual Studio Community Edition is located there: https://docs.microsoft.com/en-us/visualstudio/profiling/index
302302

303-
vcpkg.exe integrate install
304-
vcpkg.exe install --triplet x64-windows-static capstone freetype glfw3
303+
## All platforms
305304

306-
Then build one of the servers.
305+
Intel V-Tune (free, unlimited license 90 days renewal) https://software.intel.com/en-us/system-studio/choose-download
307306

308-
Solutions for servers compatible with the version of stellar-core can be found under:
307+
# Memory-use profiling
309308

310-
* lib/tracy/profiler/build/win32 (GUI)
311-
* lib/tracy/capture/build/win32
309+
Tools for memory use profiling are less well-developed than CPU profiling, but there are some options available.
312310

313-
Note: when connecting, use `localhost` instead of `127.0.0.1` as Tracy binds by default to IPV6 addresses.
311+
## Tracy
314312

315-
### General Visual Studio profiler
313+
Tracy has some built-in support for memory profiling, but turning it on will
314+
slow down core significantly and will use memory in the tracy client _very
315+
quickly_, easily overwhelming your workstation if you're not careful. So you can
316+
usually only turn it on for a brief period of time.
316317

317-
The main page for the profiler built into Visual Studio Community Edition is located there: https://docs.microsoft.com/en-us/visualstudio/profiling/index
318+
It is most useful for examining a small part of the code for a short period of
319+
time, where you already have a fairly good idea of there being memory allocation
320+
issues that you want to see a precise accounting of. Allocations get linked to
321+
zones (as a list in each zone detail view) and are available for inspection in
322+
the "memory" window, along with a total map of memory and a list of all
323+
allocations.
318324

319-
## All platforms
325+
Stellar-core has support for this mode separate from normal tracy tracing,
326+
because it is so performance intensive and memory hungry. You need to configure
327+
with --enable-tracy-memory-tracking and --disable-tcmalloc.
328+
329+
## Heaptrack
330+
331+
A better option for a high level "profile" of memory is the "heaptrack" tool,
332+
which is available on Linux.
333+
334+
$ sudo apt install heaptrack heaptrack-gui
335+
336+
To use it you will also need to configure with --disable-tcmalloc, because it
337+
works by intercepting malloc/free calls underlying the default operator
338+
new/delete, and tcmalloc's operator new and delete will bypass that
339+
interception.
340+
341+
Heaptrack should also be run only for a moderate amount of time, otherwise the
342+
recording will be huge. But it at least writes its recording to disk, and the
343+
recording is much more compact than tracy's in-memory structure, so it can run
344+
much longer than tracy in memory-recording mode without issue.
345+
346+
Heaptrack can run a program as a subprocess or attach remotely. The remote
347+
attach mode allows you to avoid starting it until the program is close to the
348+
period you want to measure, so is recommended. You will need to enable ptrace
349+
permissions.
350+
351+
Heaptrack's default recording mode is very slow as it symbolicates all the
352+
stacks while it runs. A better way is to record a _raw_ profile and then
353+
symbolicate the data after the fact.
354+
355+
Combining these facts, the best execution we've found is like the following:
356+
357+
# in one terminal...
358+
$ stellar-core ...
359+
360+
# in another terminal...
361+
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
362+
$ heaptrack --raw $(pidof stellar-core)
363+
364+
# switch back core and stop it with Ctrl-C when done
365+
366+
# heaptrack will exit and write a file like
367+
# heaptrack.stellar-core.12345.raw.zst along with, hopefully, instructions
368+
# to run something like this to post-process the raw file into a more
369+
# compact and symbolicated form. This will run a long time:
370+
371+
$ zstd -dc < ".../heaptrack.stellar-core.12345.raw.zst" \
372+
| /usr/lib/heaptrack/libexec/heaptrack_interpret \
373+
| zstd -c > ".../heaptrack.stellar-core.12345.zst"
374+
375+
# finally load the profile into the visualization tool
376+
$ heaptrack_gui ".../heaptrack.stellar-core.12345.zst"
320377

321-
Intel V-Tune (free, unlimited license 90 days renewal) https://software.intel.com/en-us/system-studio/choose-download

src/ledger/LedgerManagerImpl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,8 +1028,10 @@ LedgerManagerImpl::ApplyState::finishPendingCompilation()
10281028
releaseAssert(mPhase == Phase::SETTING_UP_STATE);
10291029
releaseAssert(mCompiler);
10301030
auto newCache = mCompiler->wait();
1031-
getMetrics().mSorobanMetrics.mModuleCacheRebuildBytes.set_count(
1031+
getMetrics().mSorobanMetrics.mModuleCacheRebuildWasmBytes.set_count(
10321032
(int64)mCompiler->getBytesCompiled());
1033+
getMetrics().mSorobanMetrics.mModuleCacheRebuildHeapBytes.set_count(
1034+
mCompiler->getBytesAllocatedDuringCompilation());
10331035
getMetrics().mSorobanMetrics.mModuleCacheNumEntries.set_count(
10341036
(int64)mCompiler->getContractsCompiled());
10351037
getMetrics().mSorobanMetrics.mModuleCacheRebuildTime.Update(
@@ -1175,7 +1177,7 @@ LedgerManagerImpl::ApplyState::maybeRebuildModuleCache(
11751177
// contract-set in the live BL as an event that warrants a rebuild.
11761178

11771179
int64_t lastCompiledWasmBytesCount =
1178-
getMetrics().mSorobanMetrics.mModuleCacheRebuildBytes.count();
1180+
getMetrics().mSorobanMetrics.mModuleCacheRebuildWasmBytes.count();
11791181
uint64_t lastCompiledWasmBytes =
11801182
lastCompiledWasmBytesCount < 0
11811183
? 0

src/ledger/SharedModuleCacheCompiler.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,12 @@ SharedModuleCacheCompiler::popAndCompileWasm(size_t thread,
135135
return true;
136136
}
137137

138-
static size_t heap_at_compile_start = 0;
139-
140138
void
141139
SharedModuleCacheCompiler::start()
142140
{
143141
mStarted = std::chrono::steady_clock::now();
144142

145-
heap_at_compile_start = getMallocBytesInUse();
143+
mHeapSizeAtStart = getMallocBytesInUse();
146144

147145
LOG_INFO(DEFAULT_LOG,
148146
"Launching 1 loading and {} compiling background threads",
@@ -209,17 +207,20 @@ SharedModuleCacheCompiler::wait()
209207
auto end = std::chrono::steady_clock::now();
210208
LOG_INFO(
211209
DEFAULT_LOG,
212-
"Compiled {} contracts ({} bytes of Wasm) in {}ms real time, {}ms "
210+
"Compiled {} contracts ({} of Wasm) in {}ms real time, {}ms "
213211
"CPU time",
214-
mContractsCompiled, mBytesCompiled,
212+
mContractsCompiled, formatSize(mBytesCompiled),
215213
std::chrono::duration_cast<std::chrono::milliseconds>(end - mStarted)
216214
.count(),
217215
std::chrono::duration_cast<std::chrono::milliseconds>(mTotalCompileTime)
218216
.count());
219-
auto heap_at_compile_end = getMallocBytesInUse();
220-
LOG_INFO(DEFAULT_LOG, "Heap grew from {} to {} bytes during ompilation, difference is {} bytes",
221-
heap_at_compile_start, heap_at_compile_end, heap_at_compile_end - heap_at_compile_start);
222-
217+
mHeapSizeAtEnd = getMallocBytesInUse();
218+
int64_t heapDiff = static_cast<int64_t>(mHeapSizeAtEnd) -
219+
static_cast<int64_t>(mHeapSizeAtStart);
220+
LOG_INFO(DEFAULT_LOG,
221+
"Heap changed from {} to {} during compilation ({} difference)",
222+
formatSize(mHeapSizeAtStart), formatSize(mHeapSizeAtEnd),
223+
formatSize(heapDiff));
223224
return mModuleCache->shallow_clone();
224225
}
225226

@@ -230,6 +231,14 @@ SharedModuleCacheCompiler::getBytesCompiled()
230231
return mBytesCompiled * mLedgerVersions.size();
231232
}
232233

234+
int64_t
235+
SharedModuleCacheCompiler::getBytesAllocatedDuringCompilation()
236+
{
237+
std::unique_lock lock(mMutex);
238+
return static_cast<int64_t>(mHeapSizeAtEnd) -
239+
static_cast<int64_t>(mHeapSizeAtStart);
240+
}
241+
233242
std::chrono::nanoseconds
234243
SharedModuleCacheCompiler::getCompileTime()
235244
{

src/ledger/SharedModuleCacheCompiler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class SharedModuleCacheCompiler : NonMovableOrCopyable
4444
std::condition_variable mHaveContracts;
4545

4646
std::chrono::steady_clock::time_point mStarted;
47+
size_t mHeapSizeAtStart{0};
48+
size_t mHeapSizeAtEnd{0};
4749
std::chrono::nanoseconds mTotalCompileTime{0};
4850

4951
void setFinishedLoading(size_t nContracts);
@@ -61,6 +63,7 @@ class SharedModuleCacheCompiler : NonMovableOrCopyable
6163
void start();
6264
::rust::Box<stellar::rust_bridge::SorobanModuleCache> wait();
6365
size_t getBytesCompiled();
66+
int64_t getBytesAllocatedDuringCompilation();
6467
std::chrono::nanoseconds getCompileTime();
6568
size_t getContractsCompiled();
6669
};

0 commit comments

Comments
 (0)