Skip to content

Commit e7adaa6

Browse files
feat: switch memory profiling from peak RSS to live heap usage (#22266)
## Summary Replaces #22229 (which was accidentally merged into the wrong branch and reverted). Switches `--memory_profile_out` from peak RSS (getrusage, monotonically increasing) to live heap usage (mallinfo2, goes up and down). This matches what Tracy's memory view showed and reveals when memory is actually freed. - Uses `mallinfo2().uordblks` on Linux, returns 0 on WASM, falls back to peak RSS on other platforms - Renamed `RssCheckpoint` to `MemoryCheckpoint`, `rss_mb` to `heap_mb` - Renamed `add_rss_checkpoint` to `add_checkpoint` Refs: AztecProtocol/barretenberg#1641 ## Example output ``` 0 MultiCallEntrypoint:entrypoint after_alloc 76 MiB 0 MultiCallEntrypoint:entrypoint after_oink 60 MiB <-- freed during commitments 6 EcdsaRAccount:entrypoint after_trace 202 MiB <-- peak 6 EcdsaRAccount:entrypoint after_oink 157 MiB <-- 45 MiB freed 8 SponsoredFPC:sponsor after_alloc 42 MiB <-- small circuit ``` ## Test plan - [x] Builds cleanly (native + asan-fast locally) - [x] Tested with deploy_ecdsar1+sponsored_fpc: heap values go up and down as expected - [ ] CI build passes --------- Co-authored-by: AztecBot <tech@aztec-labs.com>
1 parent 5c2e6d9 commit e7adaa6

7 files changed

Lines changed: 40 additions & 24 deletions

File tree

barretenberg/cpp/scripts/extract_memory_benchmarks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
entries.append({
4545
"name": f"{name_path}/{label}",
4646
"unit": "MB",
47-
"value": cp["rss_mb"],
48-
"extra": f"stacked:{name_path}/rss_over_stages"
47+
"value": cp["heap_mb"],
48+
"extra": f"stacked:{name_path}/heap_over_stages"
4949
})
5050

5151
# Append to existing benchmarks file

barretenberg/cpp/src/barretenberg/chonk/chonk.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ void Chonk::accumulate_and_fold(ClientCircuit& circuit,
540540
}
541541

542542
if (detail::use_memory_profile) {
543-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_accumulate");
543+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_accumulate");
544544
detail::GLOBAL_MEMORY_PROFILE.next_circuit();
545545
}
546546

barretenberg/cpp/src/barretenberg/common/memory_profile.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,38 @@
66

77
#include "barretenberg/serialize/msgpack_impl.hpp"
88

9+
#if defined(__linux__)
10+
#include <malloc.h>
11+
#endif
12+
13+
namespace {
14+
15+
size_t heap_allocated_mb()
16+
{
17+
#if defined(__linux__)
18+
struct mallinfo2 info = mallinfo2();
19+
return info.uordblks / (1024ULL * 1024ULL);
20+
#elif defined(__wasm__)
21+
return 0;
22+
#else
23+
// mallinfo2 is Linux-specific; fall back to peak RSS on other platforms
24+
return peak_rss_bytes() / (1024ULL * 1024ULL);
25+
#endif
26+
}
27+
28+
} // namespace
29+
930
namespace bb::detail {
1031

1132
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
1233
bool use_memory_profile = false;
1334
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
1435
MemoryProfile GLOBAL_MEMORY_PROFILE;
1536

16-
void MemoryProfile::add_rss_checkpoint(const std::string& stage)
37+
void MemoryProfile::add_checkpoint(const std::string& stage)
1738
{
1839
std::lock_guard<std::mutex> lock(mutex);
19-
#ifdef __wasm__
20-
size_t rss_mb = 0;
21-
#else
22-
size_t rss_mb = static_cast<size_t>(peak_rss_bytes() / (1024ULL * 1024ULL));
23-
#endif
24-
rss_checkpoints.push_back(RssCheckpoint{ stage, current_circuit_index, current_circuit_name, rss_mb });
40+
checkpoints.push_back(MemoryCheckpoint{ stage, current_circuit_index, current_circuit_name, heap_allocated_mb() });
2541
}
2642

2743
void MemoryProfile::set_circuit_name(const std::string& name)
@@ -39,7 +55,7 @@ void MemoryProfile::next_circuit()
3955
void MemoryProfile::clear()
4056
{
4157
std::lock_guard<std::mutex> lock(mutex);
42-
rss_checkpoints.clear();
58+
checkpoints.clear();
4359
current_circuit_name.clear();
4460
current_circuit_index = 0;
4561
}
@@ -48,7 +64,7 @@ void MemoryProfile::serialize_json(std::ostream& os) const
4864
{
4965
// Use msgpack round-trip to produce JSON (same pattern as bb_bench.cpp)
5066
msgpack::sbuffer buffer;
51-
msgpack::pack(buffer, rss_checkpoints);
67+
msgpack::pack(buffer, checkpoints);
5268
msgpack::object_handle oh = msgpack::unpack(buffer.data(), buffer.size());
5369
os << oh.get() << std::endl;
5470
}

barretenberg/cpp/src/barretenberg/common/memory_profile.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ namespace bb::detail {
1313
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
1414
extern bool use_memory_profile;
1515

16-
struct RssCheckpoint {
16+
struct MemoryCheckpoint {
1717
std::string stage;
1818
size_t circuit_index;
1919
std::string circuit_name;
20-
size_t rss_mb;
20+
size_t heap_mb; // live heap allocations via mallinfo2 (Linux) or peak RSS (other platforms)
2121

22-
SERIALIZATION_FIELDS(stage, circuit_index, circuit_name, rss_mb);
22+
SERIALIZATION_FIELDS(stage, circuit_index, circuit_name, heap_mb);
2323
};
2424

2525
struct MemoryProfile {
2626
std::mutex mutex;
27-
std::vector<RssCheckpoint> rss_checkpoints;
27+
std::vector<MemoryCheckpoint> checkpoints;
2828
std::string current_circuit_name;
2929
size_t current_circuit_index = 0;
3030

31-
void add_rss_checkpoint(const std::string& stage);
31+
void add_checkpoint(const std::string& stage);
3232
void set_circuit_name(const std::string& name);
3333
void next_circuit();
3434
void serialize_json(std::ostream& os) const;

barretenberg/cpp/src/barretenberg/hypernova/hypernova_prover.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ HypernovaFoldingProver::Accumulator HypernovaFoldingProver::instance_to_accumula
120120
MegaOinkProver oink_prover{ instance, precomputed_vk, transcript };
121121
oink_prover.prove();
122122
if (detail::use_memory_profile) {
123-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_oink");
123+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_oink");
124124
}
125125

126126
instance->gate_challenges = transcript->template get_dyadic_powers_of_challenge<FF>(
@@ -136,7 +136,7 @@ HypernovaFoldingProver::Accumulator HypernovaFoldingProver::instance_to_accumula
136136
Flavor::VIRTUAL_LOG_N);
137137
auto sumcheck_output = sumcheck.prove();
138138
if (detail::use_memory_profile) {
139-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_sumcheck");
139+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_sumcheck");
140140
}
141141

142142
Accumulator accumulator = sumcheck_output_to_accumulator(sumcheck_output, instance, precomputed_vk);

barretenberg/cpp/src/barretenberg/ultra_honk/prover_instance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ template <typename Flavor> ProverInstance_<Flavor>::ProverInstance_(Circuit& cir
7373
}
7474

7575
if (detail::use_memory_profile) {
76-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_alloc");
76+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_alloc");
7777
}
7878

7979
// Construct and add to proving key the wire, selector and copy constraint polynomials
@@ -106,7 +106,7 @@ template <typename Flavor> ProverInstance_<Flavor>::ProverInstance_(Circuit& cir
106106
analyze_prover_polynomials(polynomials);
107107
}
108108
if (detail::use_memory_profile) {
109-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_trace");
109+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_trace");
110110
}
111111
}
112112

barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ template <typename Flavor> typename UltraProver_<Flavor>::Proof UltraProver_<Fla
8080
oink_prover.prove();
8181
vinfo("created oink proof");
8282
if (detail::use_memory_profile) {
83-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_oink");
83+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_oink");
8484
}
8585

8686
generate_gate_challenges();
@@ -89,13 +89,13 @@ template <typename Flavor> typename UltraProver_<Flavor>::Proof UltraProver_<Fla
8989
execute_sumcheck_iop();
9090
vinfo("finished relation check rounds");
9191
if (detail::use_memory_profile) {
92-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_sumcheck");
92+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_sumcheck");
9393
}
9494
// Execute Shplemini PCS
9595
execute_pcs();
9696
vinfo("finished PCS rounds");
9797
if (detail::use_memory_profile) {
98-
detail::GLOBAL_MEMORY_PROFILE.add_rss_checkpoint("after_pcs");
98+
detail::GLOBAL_MEMORY_PROFILE.add_checkpoint("after_pcs");
9999
}
100100

101101
return export_proof();

0 commit comments

Comments
 (0)