Skip to content

Commit 97af12e

Browse files
authored
Merge pull request #31 from rafaelkallis/copilot/add-benchmark-space-mem-used
Add memory benchmarking with valgrind massif
2 parents 3ee24a2 + 4302416 commit 97af12e

File tree

4 files changed

+125
-1
lines changed

4 files changed

+125
-1
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,9 @@ add_executable(bench
7474
"${PROJECT_SOURCE_DIR}/bench/query_sparse_zipf.cpp"
7575
)
7676
target_link_libraries(bench art picobench zipf)
77+
78+
# bench-mem executable (for memory profiling with valgrind)
79+
add_executable(bench-mem
80+
"${PROJECT_SOURCE_DIR}/bench/memory.cpp"
81+
)
82+
target_link_libraries(bench-mem art zipf)

Makefile

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,25 @@ test:
1616
bench:
1717
@if [ -f ./$(BUILD_DIR)/bench ]; then ./$(BUILD_DIR)/bench; else echo "Please run 'make' or 'make release' first" && exit 1; fi
1818

19+
bench-mem:
20+
@if [ ! -f ./$(BUILD_DIR)/bench-mem ]; then echo "Please run 'make' or 'make release' first" && exit 1; fi
21+
@echo "Running memory benchmark with uniform distribution..."
22+
@valgrind --tool=massif --massif-out-file=./$(BUILD_DIR)/massif.out.uniform ./$(BUILD_DIR)/bench-mem uniform
23+
@ms_print ./$(BUILD_DIR)/massif.out.uniform | head -50
24+
@echo ""
25+
@echo "Running memory benchmark with Zipfian distribution..."
26+
@valgrind --tool=massif --massif-out-file=./$(BUILD_DIR)/massif.out.zipf ./$(BUILD_DIR)/bench-mem zipf
27+
@ms_print ./$(BUILD_DIR)/massif.out.zipf | head -50
28+
@echo ""
29+
@echo "Full reports saved to:"
30+
@echo " - ./$(BUILD_DIR)/massif.out.uniform"
31+
@echo " - ./$(BUILD_DIR)/massif.out.zipf"
32+
@echo ""
33+
@echo "To view full reports, run:"
34+
@echo " ms_print ./$(BUILD_DIR)/massif.out.uniform"
35+
@echo " ms_print ./$(BUILD_DIR)/massif.out.zipf"
36+
1937
clean:
2038
rm -rf ./$(BUILD_DIR)
2139

22-
.PHONY: test bench
40+
.PHONY: test bench bench-mem

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ make test
4444

4545
# run benchmarks
4646
make bench
47+
48+
# run memory benchmarks (requires valgrind)
49+
make bench-mem
4750
```
4851
4952
## Benchmark results
@@ -101,6 +104,31 @@ query sparse zipf:
101104
102105
You can replicate using `make release && make bench`
103106
107+
## Memory Benchmark
108+
109+
The `make bench-mem` command runs memory profiling using [Valgrind Massif](https://valgrind.org/docs/manual/ms-manual.html) to measure the memory footprint of the ART data structure. The benchmark tests two scenarios:
110+
111+
1. **Uniform distribution**: Keys are uniformly distributed
112+
2. **Zipfian distribution**: Keys follow a Zipfian distribution (realistic workload with hot keys)
113+
114+
Both benchmarks insert 1,000,000 elements with `nullptr` values to measure only the data structure overhead.
115+
116+
Example usage:
117+
```bash
118+
# Build and run memory benchmarks
119+
make release && make bench-mem
120+
```
121+
122+
The command will output a summary of memory usage for both distributions and save detailed reports to:
123+
- `build/massif.out.uniform` - Full report for uniform distribution
124+
- `build/massif.out.zipf` - Full report for Zipfian distribution
125+
126+
To view the full reports:
127+
```bash
128+
ms_print build/massif.out.uniform
129+
ms_print build/massif.out.zipf
130+
```
131+
104132

105133
## References
106134

bench/memory.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* @file memory usage benchmarks
3+
* @author Rafael Kallis <rk@rafaelkallis.com>
4+
*/
5+
6+
#include "art.hpp"
7+
#include "zipf.hpp"
8+
#include <cstdint>
9+
#include <functional>
10+
#include <iostream>
11+
#include <string>
12+
13+
using std::string;
14+
using std::to_string;
15+
using std::hash;
16+
17+
// Number of elements to insert for memory benchmarks
18+
const uint32_t NUM_ELEMENTS = 1000000;
19+
20+
/**
21+
* Memory benchmark with uniformly distributed keys
22+
* Uses nullptr values to measure only data structure overhead
23+
*/
24+
static void memory_uniform() {
25+
art::art<int*> m;
26+
hash<uint32_t> h;
27+
28+
// Fill tree with nullptr values
29+
for (uint32_t i = 0; i < NUM_ELEMENTS; i++) {
30+
m.set(to_string(h(i)).c_str(), nullptr);
31+
}
32+
33+
std::cout << "Inserted " << NUM_ELEMENTS << " elements (uniform distribution)" << std::endl;
34+
}
35+
36+
/**
37+
* Memory benchmark with Zipfian distributed keys
38+
* Uses nullptr values to measure only data structure overhead
39+
*/
40+
static void memory_zipf() {
41+
art::art<int*> m;
42+
hash<uint32_t> h;
43+
fast_zipf rng(NUM_ELEMENTS);
44+
45+
// Fill tree with nullptr values
46+
for (uint32_t i = 0; i < NUM_ELEMENTS; i++) {
47+
m.set(to_string(h(rng())).c_str(), nullptr);
48+
}
49+
50+
std::cout << "Inserted " << NUM_ELEMENTS << " elements (zipfian distribution)" << std::endl;
51+
}
52+
53+
int main(int argc, char *argv[]) {
54+
if (argc < 2) {
55+
std::cerr << "Usage: " << argv[0] << " <uniform|zipf>" << std::endl;
56+
return 1;
57+
}
58+
59+
std::string mode(argv[1]);
60+
61+
if (mode == "uniform") {
62+
memory_uniform();
63+
} else if (mode == "zipf") {
64+
memory_zipf();
65+
} else {
66+
std::cerr << "Unknown mode: " << mode << std::endl;
67+
std::cerr << "Valid modes: uniform, zipf" << std::endl;
68+
return 1;
69+
}
70+
71+
return 0;
72+
}

0 commit comments

Comments
 (0)