@@ -173,6 +173,14 @@ class provider_allocator : public allocator_interface {
173173 return argPos;
174174 }
175175
176+ void preBench (::benchmark::State &state) override {
177+ provider.preBench (state);
178+ }
179+
180+ void postBench (::benchmark::State &state) override {
181+ provider.postBench (state);
182+ }
183+
176184 void TearDown (::benchmark::State &state) override {
177185 provider.TearDown (state);
178186 }
@@ -204,13 +212,18 @@ template <typename Pool> class pool_allocator : public allocator_interface {
204212 return argPos;
205213 }
206214
215+ void preBench (::benchmark::State &state) override { pool.preBench (state); }
216+ void postBench (::benchmark::State &state) override {
217+ pool.postBench (state);
218+ }
219+
207220 void TearDown (::benchmark::State &state) override { pool.TearDown (state); }
208221
209- virtual void *benchAlloc (size_t size) override {
222+ void *benchAlloc (size_t size) override {
210223 return umfPoolMalloc (pool.pool , size);
211224 }
212225
213- virtual void benchFree (void *ptr, [[maybe_unused]] size_t size) override {
226+ void benchFree (void *ptr, [[maybe_unused]] size_t size) override {
214227 umfPoolFree (pool.pool , ptr);
215228 }
216229
@@ -241,7 +254,7 @@ struct benchmark_interface : public benchmark::Fixture {
241254 allocator.TearDown (state);
242255 }
243256
244- virtual void bench (::benchmark::State &state) = 0 ;
257+ void bench ([[maybe_unused]] ::benchmark::State &state){} ;
245258
246259 virtual std::vector<std::string> argsName () {
247260 auto s = Size::argsName ();
@@ -260,6 +273,9 @@ struct benchmark_interface : public benchmark::Fixture {
260273 benchmark->ArgNames (bench->argsName ())->Name (bench->name ());
261274 }
262275
276+ void custom_counters (::benchmark::State &state) {
277+ allocator.custom_counters (state);
278+ }
263279 std::vector<Size> alloc_sizes;
264280 Allocator allocator;
265281};
@@ -282,7 +298,8 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
282298
283299 vector2d<alloc_data> allocations;
284300 std::vector<unsigned > iters;
285-
301+ std::vector<size_t > memused;
302+ std::vector<size_t > peakmemory;
286303 vector2d<next_alloc_data> next;
287304 std::vector<std::vector<next_alloc_data>::const_iterator> next_iter;
288305 int64_t iterations;
@@ -302,6 +319,12 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
302319 allocations.resize (state.threads ());
303320 next.resize (state.threads ());
304321 next_iter.resize (state.threads ());
322+ memused.resize (state.threads ());
323+ peakmemory.resize (state.threads ());
324+ for (int i = 0 ; i < state.threads (); i++) {
325+ memused[i] = 0 ;
326+ peakmemory[i] = 0 ;
327+ }
305328
306329#ifndef WIN32
307330 // Ensure that system malloc does not have memory pooled on the heap
@@ -323,13 +346,49 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
323346 waitForAllThreads (state);
324347 // prepare workload for actual benchmark.
325348 freeAllocs (state);
349+ // reset peak memory before real benchmark
350+ for (auto &i : peakmemory) {
351+ i = 0 ;
352+ }
353+
326354 prealloc (state);
327355 prepareWorkload (state);
356+ waitForAllThreads (state);
357+ base::allocator.preBench (state);
328358 }
329359
330360 void TearDown (::benchmark::State &state) override {
361+ base::allocator.postBench (state);
331362 auto tid = state.thread_index ();
363+ if (tid == 0 ) {
364+ size_t current_memory_allocated = 0 ;
365+ for (int i = 0 ; i < state.threads (); i++) {
366+ current_memory_allocated += memused[i];
367+ }
368+ size_t peak_memory_allocated =
369+ *std::max_element (peakmemory.begin (), peakmemory.end ());
370+
371+ size_t peak_memory_used = state.counters [" peak_memory_use" ];
372+ size_t current_memory_used = state.counters [" current_memory_use" ];
373+
374+ if (peak_memory_used != 0 ) {
375+ state.counters [" peak_memory_fragmentation" ] =
376+ 100.0 * (peak_memory_used - peak_memory_allocated) /
377+ peak_memory_used;
378+ }
379+
380+ if (current_memory_used != 0 ) {
381+ state.counters [" current_memory_fragmentation" ] =
382+ 100.0 * (current_memory_used - current_memory_allocated) /
383+ current_memory_used;
384+ }
385+
386+ state.counters [" current_memory_allocated" ] =
387+ current_memory_allocated;
388+ state.counters [" peak_memory_allocated" ] = peak_memory_allocated;
389+ }
332390
391+ waitForAllThreads (state);
333392 freeAllocs (state);
334393 waitForAllThreads (state);
335394 if (tid == 0 ) {
@@ -342,20 +401,24 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
342401 base::TearDown (state);
343402 }
344403
345- void bench (benchmark::State &state) override {
404+ void bench (benchmark::State &state) {
346405 auto tid = state.thread_index ();
347406 auto &allocation = allocations[tid];
407+ auto &memuse = memused[tid];
408+ auto &peak = peakmemory[tid];
348409 for (int i = 0 ; i < allocsPerIterations; i++) {
349410 auto &n = *next_iter[tid]++;
350411 auto &alloc = allocation[n.offset ];
351412 base::allocator.benchFree (alloc.ptr , alloc.size );
352-
413+ memuse -= alloc. size ;
353414 alloc.size = n.size ;
354415 alloc.ptr = base::allocator.benchAlloc (alloc.size );
355416
356417 if (alloc.ptr == NULL ) {
357418 state.SkipWithError (" allocation failed" );
358419 }
420+ memuse += alloc.size ;
421+ peak = std::max (peak, memuse);
359422 }
360423 }
361424
@@ -376,7 +439,10 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
376439 auto tid = state.thread_index ();
377440 auto &i = allocations[tid];
378441 i.resize (max_allocs);
442+ auto &memuse = memused[tid];
443+ auto &peak = peakmemory[tid];
379444 auto sizeGenerator = base::alloc_sizes[tid];
445+
380446 for (size_t j = 0 ; j < max_allocs; j++) {
381447 auto size = sizeGenerator.nextSize ();
382448 i[j].ptr = base::allocator.benchAlloc (size);
@@ -385,6 +451,8 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
385451 return ;
386452 }
387453 i[j].size = size;
454+ memuse += size;
455+ peak = std::max (peak, memuse);
388456 }
389457 }
390458
@@ -394,6 +462,7 @@ class multiple_malloc_free_benchmark : public benchmark_interface<Size, Alloc> {
394462 for (auto &j : i) {
395463 if (j.ptr != NULL ) {
396464 base::allocator.benchFree (j.ptr , j.size );
465+ memused[tid] -= j.size ;
397466 j.ptr = NULL ;
398467 j.size = 0 ;
399468 }
0 commit comments