kaist-cp / smr-benchmark

SMR Benchmark: A Microbenchmark Suite for Concurrent Safe Memory Reclamation Schemes
http://cp.kaist.ac.kr/gc
MIT License
36 stars 5 forks source link

SMR Benchmark: A Microbenchmark Suite for Concurrent Safe Memory Reclamation Schemes

CI Docs

This is the artifact for:

Summary

On Ubuntu 22.04,

sudo apt install build-essential python3-pip clang
# Install the Rust compiler and register its executable path.
curl https://sh.rustup.rs -sSf | bash -s -- -y
pip3 install --user pandas plotnine

cargo build --release

# To run a single map data structure benchmark (see later sections for details),
./target/release/<reclamation-scheme> -d <data-structure> -t <threads> -g <get-rate> -r <key-range> -i <time-interval-to-run-seconds>

# For dedicated experiment scripts (e.g., `experiment.sh`),
# see subdirectories in `bench-scripts`.

To add your own implementation of SMR and data structures, please refer to this guide.

Getting Started Guide

We recommend the following environment:

Project Structure

For the implementation of EBR and PEBR, please refer to our dedicated repository kaist-cp/crossbeam.

Setting up the Environment

The benchmark requires Rust (for building the implementation of reclamation schemes and data structures), Python (for generating the figures), and other essential build tools.

Install Rust and Build Tools

Install build tools by simply running:

# `clang` is necessary to compile NBR and HP-BRCU.
sudo apt install build-essential clang
# Install the Rust compiler and register its executable path.
curl https://sh.rustup.rs -sSf | bash -s -- -y

Install Python Packages

Some Python packages are necessary to execute end-to-end experiment scripts and generate plots. To install them locally, simply run:

sudo apt install python3-pip
pip3 install --user pandas plotnine

However, in some cases, you might encounter an issue due to the conflicts on the versions of Python packages. If this is the case, We suggest using pyenv to set up the Python environment to minimize potential conflicts with the pre-installed system Python environment.

# Install the system Python3 and all dependencies for `pyenv`.
sudo apt update && sudo apt install -y \
  build-essential python3 python3-pip curl \
  libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl \
  libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

# Install `pyenv`. If you already have `pyenv` in your system,
# skip this lines and set up `bench-venv`.
curl https://pyenv.run | bash
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
source ~/.bashrc

# Set up the `bench-venv` environment to generate figures.
pyenv install 3.10.12
pyenv virtualenv 3.10.12 bench-venv
pyenv local bench-venv
pip3 install -r requirements.txt

# Install the Rust compiler and register its executable path.
curl https://sh.rustup.rs -sSf | bash -s -- -y

Build Binaries

After installing the necessary dependencies properly, build the benchmark binaries with the following command:

cargo build --release

Basic Testing

cargo test --release -- --test-threads=1

After successful testing, outputs like the following appear, printing ok for each test.

$ cargo test --release -- --test-threads=1
    Finished release [optimized] target(s) in 0.05s
     Running unittests src/lib.rs (target/release/deps/smr_benchmark-c42d60ebe9d214bd)

running 72 tests
test ds_impl::cdrc::bonsai_tree::tests::smoke_bonsai_tree_ebr ... ok
test ds_impl::cdrc::bonsai_tree::tests::smoke_bonsai_tree_hp ... ok
test ds_impl::cdrc::double_link::test::simple_all ... ok
test ds_impl::cdrc::double_link::test::smoke_all ... ok
... (omitted) ...

test result: ok. 72 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 25.24s
... (omitted) ...

   Doc-tests smr-benchmark

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Running a Single Benchmark

Even with the small configuration, the end-to-end benchmark scripts in bench-scripts would take several hours. You can run a single benchmark by directly executing the benchmark binaries.

Map Data Structures

To run a single map data structure benchmark,

./target/release/<reclamation-scheme> -d <data-structure> -t <threads> -g <get-rate> -r <key-range> -i <time-interval-to-run-seconds>

where

It runs a single map data structure benchmark with the given configuration, and measures the throughput (operations per second) and memory usage (bytes).

$ ./target/release/circ-ebr -d nm-tree -t 64 -g 2 -r 10000 -i 10
nm-tree: 64 threads, n0, c1, E2, small bag
prefilling with 64 threads... prefilled... end
ops/s: 163839786, peak mem: 28.316 MiB, avg_mem: 4.970 MiB, peak garb: 99524, avg garb: 3589

For detailed usage information,

./target/release/<reclamation-scheme> -h

DoubleLink Queue

To run a single DoubleLink queue benchmark,

./target/release/double-link -t <threads> -m <reclamation-scheme> -i <time-interval-to-run-seconds>

where

It runs a single DoubleLink queue benchmark with the given configuration, and measures the throughput (operations per second) and memory usage (bytes).

$ ./target/release/double-link -t 64 -m circ-ebr -i 10          
circ-ebr: 64 threads
end
ops/s: 732030, peak mem: 219205664, avg_mem: 110476847

For detailed usage information,

./target/release/double-link -h

Running the Entire Benchmark

To run the entire benchmark, execute experiment.sh script in bench-scripts. This takes several hours and creates raw CSV data and figures under ./results/.

Debug

We used AddressSanitizer to debug our implementation. For example, a line below runs the benchmark with LLVM address sanitizer for Rust and uses parameters that impose high stress on SMR by triggering more frequent retirements.

RUST_BACKTRACE=1 RUSTFLAGS="-Z sanitizer=address" cargo run --bin <Reclamation scheme> --target x86_64-unknown-linux-gnu --features sanitize -- -d<Data structure> -i3 -t64 -r10 -g1

Note that sanitizer may report memory leaks when used against CIRC EBR. This is because we used high bits of pointers for epoch tagging purposes, but the AddressSanitizer does not recognize those tagged pointers.

References