Skip to content

Commit 2a2c95a

Browse files
committed
fcmp++: set max arenas glibc will use
1 parent 28fdf98 commit 2a2c95a

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

src/cryptonote_core/cryptonote_core.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ namespace cryptonote
453453
{
454454
start_time = std::time(nullptr);
455455

456+
// Necessary for FCMP++ sync on Linux platforms, especially with limited memory
457+
rct::limitMaxMemArenas();
458+
456459
const bool regtest = command_line::get_arg(vm, arg_regtest_on);
457460
if (test_options != NULL || regtest)
458461
{

src/ringct/rctSigs.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#include "device/device.hpp"
4545
#include "serialization/crypto.h"
4646

47+
#if defined(__GLIBC__)
48+
#include <malloc.h>
49+
#endif
50+
4751
using namespace crypto;
4852
using namespace std;
4953

@@ -1747,4 +1751,26 @@ namespace rct {
17471751
}
17481752
return true;
17491753
}
1754+
1755+
void limitMaxMemArenas()
1756+
{
1757+
#ifdef M_ARENA_MAX
1758+
tools::threadpool &tpool = tools::threadpool::getInstanceForCompute();
1759+
const std::size_t n_threads = std::max<std::size_t>(1, tpool.get_max_concurrency());
1760+
1761+
// See mallopt and M_ARENA_MAX at: https://man7.org/linux/man-pages/man3/mallopt.3.html
1762+
int r = mallopt(M_ARENA_MAX, n_threads);
1763+
if (r == 1)
1764+
{
1765+
MDEBUG("Set max arenas to " << n_threads);
1766+
return;
1767+
}
1768+
1769+
MWARNING("Failed to set max arenas, the system may use more memory than expected during sync.");
1770+
#else
1771+
MDEBUG("System does not have mallopt and M_ARENA_MAX setting. This setting is crucial for some Linux platforms to"
1772+
<< " avoid OOM's when batch verifying FCMP++ txs. If we see OOM's in the future when batch verifying on a non-"
1773+
<< "Linux platform, then check the system allocator behavior and see if it has a setting similar to mallopt");
1774+
#endif
1775+
}
17501776
}

src/ringct/rctSigs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,17 @@ namespace rct {
147147

148148
// Split into batches and verify each batch in parallel
149149
bool batchVerifyFcmpPpProofs(std::vector<fcmp_pp::FcmpPpVerifyInput> &&fcmp_pp_verify_inputs);
150+
151+
// The default libc allocator on most Linux systems may cache allocated memory for reuse.
152+
// As a result, verifying many large batches of FCMP++ proofs in multithreaded contexts
153+
// can end up using a lot of memory that does not get released back to the OS, even
154+
// though memory is already freed.
155+
// This function uses the mallopt syscall to limit the max number of "arenas" the system
156+
// may use, setting it to the number of threads the system has. This way there won't
157+
// be more memory allocated and kept around than expected in a potentially unbounded
158+
// number of arenas.
159+
// More on this here: https://gotplt.org/posts/malloc-per-thread-arenas-in-glibc.html
160+
void limitMaxMemArenas();
150161
}
151162
#endif /* RCTSIGS_H */
152163

0 commit comments

Comments
 (0)