mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-26 21:47:06 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e221267af |
No files matched your search
@@ -304,6 +304,7 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
|
|||||||
| ---------------- | ------------- | ----------------------------------------------------------------------------- |
|
| ---------------- | ------------- | ----------------------------------------------------------------------------- |
|
||||||
| `assert` | OFF | Force enabling assertions. |
|
| `assert` | OFF | Force enabling assertions. |
|
||||||
| `coverage` | OFF | Prepare the coverage report. |
|
| `coverage` | OFF | Prepare the coverage report. |
|
||||||
|
| `jemalloc` | ON | Use jemalloc instead of the system allocator; disables glibc malloc trimming. |
|
||||||
| `rust` | OFF | Build the Rust crates and the C++ code that depends on them. |
|
| `rust` | OFF | Build the Rust crates and the C++ code that depends on them. |
|
||||||
| `tests` | OFF | Build tests. |
|
| `tests` | OFF | Build tests. |
|
||||||
| `unity` | OFF | Configure a unity build. |
|
| `unity` | OFF | Configure a unity build. |
|
||||||
@@ -317,6 +318,26 @@ memory) since they concatenate sources into fewer translation units. Non-unity
|
|||||||
builds may be faster for incremental builds, and can be helpful for detecting
|
builds may be faster for incremental builds, and can be helpful for detecting
|
||||||
`#include` omissions.
|
`#include` omissions.
|
||||||
|
|
||||||
|
### Memory allocator
|
||||||
|
|
||||||
|
Conan and CMake use jemalloc by default. In jemalloc builds, `mallocTrim` does
|
||||||
|
not call glibc's `malloc_trim` or collect trim metrics; jemalloc manages its own
|
||||||
|
arenas and memory reclamation.
|
||||||
|
|
||||||
|
To use the system allocator instead (GNU/glibc malloc with the existing
|
||||||
|
`malloc_trim(0)` behavior on Linux/glibc), add `--options '&:jemalloc=False'`
|
||||||
|
to each `conan install` command and `-Djemalloc=OFF` to the CMake configure
|
||||||
|
command. Keep the Conan and CMake options consistent. To switch an existing
|
||||||
|
system-allocator build to jemalloc, rerun Conan with
|
||||||
|
`--options '&:jemalloc=True'` and configure CMake with `-Djemalloc=ON`, since
|
||||||
|
existing build directories may cache the old option value.
|
||||||
|
|
||||||
|
The `sanitizers` Conan profile disables jemalloc when sanitizer instrumentation
|
||||||
|
is enabled so that sanitizers can intercept the system allocator. CMake also
|
||||||
|
defaults to the system allocator when `SANITIZERS` is set; use `-Djemalloc=OFF`
|
||||||
|
if reusing a build directory previously configured with jemalloc. Platforms
|
||||||
|
other than Linux/glibc do not support malloc trimming, regardless of this option.
|
||||||
|
|
||||||
### Rust crates
|
### Rust crates
|
||||||
|
|
||||||
The Rust crates in `crates/` are only part of the build when `rust` is ON. With
|
The Rust crates in `crates/` are only part of the build when `rust` is ON. With
|
||||||
|
|||||||
@@ -131,7 +131,17 @@ else()
|
|||||||
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
# Sanitizers need to intercept the system allocator.
|
||||||
|
if(SANITIZERS_ENABLED)
|
||||||
|
set(JEMALLOC_DEFAULT OFF)
|
||||||
|
else()
|
||||||
|
set(JEMALLOC_DEFAULT ON)
|
||||||
|
endif()
|
||||||
|
option(
|
||||||
|
jemalloc
|
||||||
|
"Use jemalloc instead of the system allocator"
|
||||||
|
${JEMALLOC_DEFAULT}
|
||||||
|
)
|
||||||
option(werr "treat warnings as errors" OFF)
|
option(werr "treat warnings as errors" OFF)
|
||||||
option(
|
option(
|
||||||
local_protobuf
|
local_protobuf
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags"
|
|||||||
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{ sanitizers }}", "SANITIZERS_COMPILER_FLAGS": "{{ sanitizer_compiler_flags | join(' ') }}", "SANITIZERS_LINKER_FLAGS": "{{ sanitizer_linker_flags | join(' ') }}"}
|
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{ sanitizers }}", "SANITIZERS_COMPILER_FLAGS": "{{ sanitizer_compiler_flags | join(' ') }}", "SANITIZERS_LINKER_FLAGS": "{{ sanitizer_linker_flags | join(' ') }}"}
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
|
# Let sanitizers intercept the system allocator rather than jemalloc.
|
||||||
|
&:jemalloc=False
|
||||||
{% if enable_asan %}
|
{% if enable_asan %}
|
||||||
# Build Boost.Context with ucontext backend (not fcontext) so that
|
# Build Boost.Context with ucontext backend (not fcontext) so that
|
||||||
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
||||||
|
|||||||
+3
-1
@@ -52,7 +52,7 @@ class Xrpl(ConanFile):
|
|||||||
"benchmark": True,
|
"benchmark": True,
|
||||||
"coverage": False,
|
"coverage": False,
|
||||||
"fPIC": True,
|
"fPIC": True,
|
||||||
"jemalloc": False,
|
"jemalloc": True,
|
||||||
"rocksdb": True,
|
"rocksdb": True,
|
||||||
"shared": False,
|
"shared": False,
|
||||||
"static": True,
|
"static": True,
|
||||||
@@ -228,5 +228,7 @@ class Xrpl(ConanFile):
|
|||||||
"xxhash::xxhash",
|
"xxhash::xxhash",
|
||||||
"zlib::zlib",
|
"zlib::zlib",
|
||||||
]
|
]
|
||||||
|
if self.options.jemalloc:
|
||||||
|
libxrpl.requires.append("jemalloc::jemalloc")
|
||||||
if self.options.rocksdb:
|
if self.options.rocksdb:
|
||||||
libxrpl.requires.append("rocksdb::librocksdb")
|
libxrpl.requires.append("rocksdb::librocksdb")
|
||||||
@@ -13,11 +13,11 @@ namespace xrpl {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Allocator interaction note:
|
// Allocator interaction note:
|
||||||
// - This facility invokes glibc's malloc_trim(0) on Linux/glibc to request that
|
// - This facility invokes glibc's malloc_trim(0) on Linux/glibc to request that
|
||||||
// ptmalloc return free heap pages to the OS.
|
// ptmalloc return free heap pages to the OS, unless built with jemalloc.
|
||||||
// - If an alternative allocator (e.g. jemalloc or tcmalloc) is linked or
|
// - Builds with jemalloc disable trimming and its instrumentation entirely.
|
||||||
// preloaded (LD_PRELOAD), calling glibc's malloc_trim typically has no effect
|
// - Other linked or preloaded allocators (LD_PRELOAD) are not detected. Calling
|
||||||
// on the *active* heap. The call is harmless but may not reclaim memory
|
// glibc's malloc_trim typically has no effect on their heaps because those
|
||||||
// because those allocators manage their own arenas.
|
// allocators manage their own arenas.
|
||||||
// - Only glibc sbrk/arena space is eligible for trimming; large mmap-backed
|
// - Only glibc sbrk/arena space is eligible for trimming; large mmap-backed
|
||||||
// allocations are usually returned to the OS on free regardless of trimming.
|
// allocations are usually returned to the OS on free regardless of trimming.
|
||||||
// - Call at known reclamation points (e.g., after cache sweeps / online delete)
|
// - Call at known reclamation points (e.g., after cache sweeps / online delete)
|
||||||
@@ -47,18 +47,16 @@ struct MallocTrimReport
|
|||||||
* @brief Attempt to return freed memory to the operating system.
|
* @brief Attempt to return freed memory to the operating system.
|
||||||
*
|
*
|
||||||
* On Linux with glibc malloc, this issues ::malloc_trim(0), which may release
|
* On Linux with glibc malloc, this issues ::malloc_trim(0), which may release
|
||||||
* free space from ptmalloc arenas back to the kernel. On other platforms, or if
|
* free space from ptmalloc arenas back to the kernel. On other platforms, or
|
||||||
* a different allocator is in use, this function is a no-op and the report will
|
* when built with jemalloc, this function performs no trimming or instrumentation
|
||||||
* indicate that trimming is unsupported or had no effect.
|
* and returns a default report with supported=false.
|
||||||
*
|
*
|
||||||
* @param tag Identifier for logging/debugging purposes.
|
* @param tag Identifier for logging/debugging purposes.
|
||||||
* @param journal Journal for diagnostic logging.
|
* @param journal Journal for diagnostic logging.
|
||||||
* @return Report containing before/after metrics and the trim result.
|
* @return Report containing before/after metrics and the trim result.
|
||||||
*
|
*
|
||||||
* @note If an alternative allocator (jemalloc/tcmalloc) is linked or preloaded,
|
* @note Other linked or preloaded allocators are not detected at runtime.
|
||||||
* calling glibc's malloc_trim may have no effect on the active heap. The
|
* Calling glibc's malloc_trim may have no effect on their heaps.
|
||||||
* call is harmless but typically does not reclaim memory under those
|
|
||||||
* allocators.
|
|
||||||
*
|
*
|
||||||
* @note Only memory served from glibc's sbrk/arena heaps is eligible for trim.
|
* @note Only memory served from glibc's sbrk/arena heaps is eligible for trim.
|
||||||
* Large allocations satisfied via mmap are usually returned on free
|
* Large allocations satisfied via mmap are usually returned on free
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
// jemalloc manages its own arenas; glibc trimming and metrics do not apply.
|
||||||
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@@ -43,7 +44,7 @@ namespace detail {
|
|||||||
|
|
||||||
// cSpell:ignore statm
|
// cSpell:ignore statm
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
mallocTrimWithPad(std::size_t padBytes)
|
mallocTrimWithPad(std::size_t padBytes)
|
||||||
@@ -69,7 +70,7 @@ parseStatmRSSkB(std::string const& statm)
|
|||||||
return (resident * pageSize) / 1024;
|
return (resident * pageSize) / 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __GLIBC__ && BOOST_OS_LINUX
|
#endif // __GLIBC__ && BOOST_OS_LINUX && !PROFILE_JEMALLOC
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@@ -80,8 +81,9 @@ mallocTrim(std::string_view tag, beast::Journal journal)
|
|||||||
|
|
||||||
MallocTrimReport report;
|
MallocTrimReport report;
|
||||||
|
|
||||||
#if !(defined(__GLIBC__) && BOOST_OS_LINUX)
|
#if !(defined(__GLIBC__) && BOOST_OS_LINUX) || defined(PROFILE_JEMALLOC)
|
||||||
JLOG(journal.debug()) << "malloc_trim not supported on this platform (tag=" << tag << ")";
|
JLOG(journal.debug()) << "malloc_trim not supported by this build's platform or allocator (tag="
|
||||||
|
<< tag << ")";
|
||||||
#else
|
#else
|
||||||
// Keep glibc malloc_trim padding at 0 (default): 12h Mainnet tests across 0/256KB/1MB/16MB
|
// Keep glibc malloc_trim padding at 0 (default): 12h Mainnet tests across 0/256KB/1MB/16MB
|
||||||
// showed no clear, consistent benefit from custom padding—0 provided the best overall balance
|
// showed no clear, consistent benefit from custom padding—0 provided the best overall balance
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using namespace xrpl;
|
|||||||
|
|
||||||
// cSpell:ignore statm
|
// cSpell:ignore statm
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
namespace xrpl::detail {
|
namespace xrpl::detail {
|
||||||
long
|
long
|
||||||
parseStatmRSSkB(std::string const& statm);
|
parseStatmRSSkB(std::string const& statm);
|
||||||
@@ -48,7 +48,7 @@ TEST(MallocTrimReport, structure)
|
|||||||
EXPECT_EQ(report.deltaKB(), 0);
|
EXPECT_EQ(report.deltaKB(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
TEST(ParseStatmRSSkB, standard_format)
|
TEST(ParseStatmRSSkB, standard_format)
|
||||||
{
|
{
|
||||||
using xrpl::detail::parseStatmRSSkB;
|
using xrpl::detail::parseStatmRSSkB;
|
||||||
@@ -127,7 +127,7 @@ TEST(MallocTrim, without_debug_logging)
|
|||||||
|
|
||||||
MallocTrimReport const report = mallocTrim("without_debug", journal);
|
MallocTrimReport const report = mallocTrim("without_debug", journal);
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
EXPECT_EQ(report.supported, true);
|
EXPECT_EQ(report.supported, true);
|
||||||
EXPECT_GE(report.trimResult, 0);
|
EXPECT_GE(report.trimResult, 0);
|
||||||
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
||||||
@@ -149,7 +149,7 @@ TEST(MallocTrim, empty_tag)
|
|||||||
beast::Journal const journal{beast::Journal::getNullSink()};
|
beast::Journal const journal{beast::Journal::getNullSink()};
|
||||||
MallocTrimReport const report = mallocTrim("", journal);
|
MallocTrimReport const report = mallocTrim("", journal);
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
EXPECT_EQ(report.supported, true);
|
EXPECT_EQ(report.supported, true);
|
||||||
EXPECT_GE(report.trimResult, 0);
|
EXPECT_GE(report.trimResult, 0);
|
||||||
#else
|
#else
|
||||||
@@ -179,7 +179,7 @@ TEST(MallocTrim, with_debug_logging)
|
|||||||
|
|
||||||
MallocTrimReport const report = mallocTrim("debug_test", journal);
|
MallocTrimReport const report = mallocTrim("debug_test", journal);
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
EXPECT_EQ(report.supported, true);
|
EXPECT_EQ(report.supported, true);
|
||||||
EXPECT_GE(report.trimResult, 0);
|
EXPECT_GE(report.trimResult, 0);
|
||||||
EXPECT_GE(report.durationUs.count(), 0);
|
EXPECT_GE(report.durationUs.count(), 0);
|
||||||
@@ -188,9 +188,12 @@ TEST(MallocTrim, with_debug_logging)
|
|||||||
#else
|
#else
|
||||||
EXPECT_EQ(report.supported, false);
|
EXPECT_EQ(report.supported, false);
|
||||||
EXPECT_EQ(report.trimResult, -1);
|
EXPECT_EQ(report.trimResult, -1);
|
||||||
|
EXPECT_EQ(report.rssBeforeKB, -1);
|
||||||
|
EXPECT_EQ(report.rssAfterKB, -1);
|
||||||
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
|
||||||
EXPECT_EQ(report.minfltDelta, -1);
|
EXPECT_EQ(report.minfltDelta, -1);
|
||||||
EXPECT_EQ(report.majfltDelta, -1);
|
EXPECT_EQ(report.majfltDelta, -1);
|
||||||
|
EXPECT_EQ(report.deltaKB(), 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +206,7 @@ TEST(MallocTrim, repeated_calls)
|
|||||||
{
|
{
|
||||||
MallocTrimReport const report = mallocTrim("iteration_" + std::to_string(i), journal);
|
MallocTrimReport const report = mallocTrim("iteration_" + std::to_string(i), journal);
|
||||||
|
|
||||||
#if defined(__GLIBC__) && BOOST_OS_LINUX
|
#if defined(__GLIBC__) && BOOST_OS_LINUX && !defined(PROFILE_JEMALLOC)
|
||||||
EXPECT_EQ(report.supported, true);
|
EXPECT_EQ(report.supported, true);
|
||||||
EXPECT_GE(report.trimResult, 0);
|
EXPECT_GE(report.trimResult, 0);
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in new issue
Block a user