# HBalloc Artifact

This artifact contains HBalloc, a persistent-memory allocator, together with a
NUMA-aware extension used to evaluate allocation scalability on multi-socket
persistent-memory systems. The artifact provides source code, build scripts,
benchmark drivers, and configuration files for reproducing the allocator
experiments reported in the paper.

The repository contains two allocator implementations:

- `src/`: original HBalloc implementation.
- `src_numa/`: NUMA-aware HBalloc extension.

The NUMA-aware version keeps HBalloc's original tcache/chunk allocation
pipeline, but partitions heap files and allocator metadata by NUMA node.

## Platform

We evaluate HBalloc on a Linux server (Ubuntu 18.04) equipped with 6 × 128GB Intel Optane DC PMM 100 Series and 12 × 16GB DDR4 DRAM. We connect the Optane DC PMMs to the same CPU socket and configure them in the interleaved and App Direct Modes.

## Repository Layout

- `src/`: original HBalloc implementation and public headers.
- `src_numa/`: NUMA-aware HBalloc extension. It keeps the original tcache/chunk allocation pipeline, but adds per-NUMA heap files, per-node tcache/log/region metadata, node-aware persistent-pointer translation, and local-first region allocation.
- `test/`: benchmark source files and legacy run scripts.
- `scripts/`: recommended artifact-evaluation helper scripts.
- `configs/`: quick, full, and single-socket benchmark configurations.
- `README.md`: artifact overview and reproduction guide.
- `REQUIREMENTS`: hardware and software requirements.
- `INSTALL`: installation and basic usage instructions.
- `STATUS`: requested artifact badges and justification.
- `LICENSE`: distribution terms.

## Requirements

Software:

- Linux
- `gcc`
- `make`
- POSIX threads
- `findmnt`
- `taskset`
- `numactl` and `libnuma-dev` for the single-socket benchmark

Hardware/filesystem:

- Persistent memory exposed through a DAX-mounted filesystem.
- A writable benchmark directory on that filesystem.

The scripts use these defaults:

```sh
PMEM_MOUNT=/mnt/pmem
HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
```

If your persistent-memory filesystem is mounted elsewhere, set both variables
before running the artifact:

```sh
export PMEM_MOUNT=/path/to/pmem
export HBALLOC_PMEM_DIR=/path/to/pmem/HBalloc
```

For the NUMA-aware version, `HBALLOC_PMEM_DIR` is used as the node-0
persistent heap directory. Set `HBALLOC_PMEM_DIR_NODE1` to place the node-1
heap and log files on another PMEM mount:

```sh
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export HBALLOC_PMEM_DIR_NODE1=/mnt/pmem1/HBalloc
```

Create the benchmark directory once:

```sh
sudo mkdir -p /mnt/pmem/HBalloc
sudo chown "$(id -u):$(id -g)" /mnt/pmem/HBalloc
```

If the NUMA-aware version uses a second PMEM mount, create that directory as
well:

```sh
sudo mkdir -p /mnt/pmem1/HBalloc
sudo chown "$(id -u):$(id -g)" /mnt/pmem1/HBalloc
```

## Install and Build

From the repository root:

```sh
make
```

This creates:

- `build/thread_test`: portable threaded allocation/free benchmark.
- `build/thread_test_single_socket`: NUMA-aware single-socket benchmark.

If `libnuma` is unavailable, build only the portable benchmark:

```sh
make thread-test
```

To build the NUMA-aware HBalloc extension from `src_numa/`:

```sh
make thread-test-numa
make single-socket-test-numa
```

This creates:

- `build/thread_test_numa`: threaded allocation/free benchmark linked with
  the NUMA-aware HBalloc implementation.
- `build/thread_test_single_socket_numa`: single-socket benchmark linked with
  the NUMA-aware HBalloc implementation.

## Small Example

First check the environment:

```sh
make check-env
```

Then run a small benchmark:

```sh
make quick
```

This uses `configs/quick.env`:

```sh
SIZE=64
NOBJ=10000
ITR=5
THREAD_COUNTS="1 2 4"
```

A successful run prints verified allocation/free counts and positive
throughput, for example:

```text
===== threads=1 =====
Verified operations = 50000 allocations + 50000 frees
Allocation throughput = ... Mops/s
Malloc+free throughput = ... Mops/s
```

By default, new benchmark logs are written outside the source tree under
`/tmp/hballoc-results`. Override this with `RESULTS_DIR=/path/to/output`.

## Reproducing the Paper Experiments

The main experiments use 64-byte objects and the thread counts:

```sh
1 2 4 8 16 32 64 128
```

The default full configuration is stored in `configs/full.env`:

```sh
SIZE=64
NOBJ=1000000
ITR=100
THREAD_COUNTS="1 2 4 8 16 32 64 128"
```

To reproduce the original HBalloc thread-scaling result:

```sh
export PMEM_MOUNT=/mnt/pmem
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export RESULTS_DIR=/tmp/hballoc-results-original
make bench
```

To reproduce the NUMA-aware HBalloc thread-scaling result with two PMEM
mounts:

```sh
export PMEM_MOUNT=/mnt/pmem
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export HBALLOC_PMEM_DIR_NODE1=/mnt/pmem1/HBalloc
export RESULTS_DIR=/tmp/hballoc-results-numa
make bench-numa
```

To reproduce the single-socket isolation experiment:

```sh
export PMEM_MOUNT=/mnt/pmem
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export RESULTS_DIR=/tmp/hballoc-results-single-socket
make bench-single-socket
```

For the NUMA-aware allocator under the same single-socket restriction:

```sh
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export HBALLOC_PMEM_DIR_NODE1=/mnt/pmem1/HBalloc
export RESULTS_DIR=/tmp/hballoc-results-single-socket-numa
make bench-single-socket-numa
```

Benchmark logs include the thread count, verified allocation/free counts,
execution time, allocation throughput, and malloc+free throughput. 

## NUMA-Aware HBalloc

The NUMA-aware implementation is intentionally kept separate from the original
allocator source tree. The default targets continue to build `src/`, while the
`*-numa` targets build `src_numa/`. This makes it possible to compare original
HBalloc and NUMA-aware HBalloc in the same repository.

Run the full two-socket benchmark with the NUMA-aware allocator:

```sh
export HBALLOC_PMEM_DIR=/mnt/pmem/HBalloc
export HBALLOC_PMEM_DIR_NODE1=/mnt/pmem1/HBalloc
make bench-numa
```

Run the single-socket benchmark with the NUMA-aware allocator:

```sh
make bench-single-socket-numa
```

The NUMA-aware allocator creates separate heap and log files for the two NUMA
nodes:

```text
$HBALLOC_PMEM_DIR/hballoc_heap_node0
$HBALLOC_PMEM_DIR/hballoc_log_node0
$HBALLOC_PMEM_DIR_NODE1/hballoc_heap_node1
$HBALLOC_PMEM_DIR_NODE1/hballoc_log_node1
```

If `HBALLOC_PMEM_DIR_NODE1` is not set, both node-local heaps are placed under
`HBALLOC_PMEM_DIR`. This is useful for functional testing, but it does not
evaluate true dual-PMEM-node placement.

