rc-hashmap 0.1.0

A HashMap with reference-counted key-value entries.
Documentation
name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: default (wyhash)
            flags: ""
          - name: random-state-hash
            flags: "--no-default-features --features random-state-hash"
          - name: xxh3-hash
            flags: "--no-default-features --features xxh3-hash"
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: build-${{ matrix.name }}

      - name: Tests (${{ matrix.name }})
        run: cargo test ${{ matrix.flags }} --verbose

      - name: Clippy (${{ matrix.name }})
        run: cargo clippy --all-targets ${{ matrix.flags }} -- -D warnings

  benches-compile:
    name: Benches - compile
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo (benches)
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: benches

      - name: Install cargo-criterion (prime cache)
        run: cargo install cargo-criterion --debug

      - name: Compile benches (default features)
        run: cargo bench --no-run --benches --verbose

      - name: Compile rc bench (random-state-hash)
        run: cargo bench --no-run --bench rc_hashmap_bench --no-default-features --features random-state-hash --verbose

      - name: Compile rc bench (xxh3-hash)
        run: cargo bench --no-run --bench rc_hashmap_bench --no-default-features --features xxh3-hash --verbose

  benches-run:
    name: Benches - run (${{ matrix.row.name }} / ${{ matrix.ds.name }})
    runs-on: ubuntu-latest
    needs: benches-compile
    strategy:
      fail-fast: false
      matrix:
        row:
          - { name: 'insert fresh', filter: 'insert/fresh_100k$' }
          - { name: 'insert warm', filter: 'insert/warm_100k$' }
          - { name: 'remove random', filter: 'remove/random_10k_of_110k$' }
          - { name: 'query hit', filter: 'query/hit_10k_on_100k$' }
          - { name: 'query miss', filter: 'query/miss_10k_on_100k$' }
          - { name: 'access random increment', filter: 'access/random_increment_100k$' }
          - { name: 'access iter all', filter: 'access/iter_all_100k$' }
          - { name: 'access iter_mut increment all', filter: 'access/iter_mut_increment_all_100k$' }
        ds:
          - { name: 'HandleHashMap', bench: 'handle_hashmap_bench', flags: '' }
          - { name: 'CountedHashMap', bench: 'counted_hashmap_bench', flags: '' }
          - { name: 'RcHashMap', bench: 'rc_hashmap_bench', flags: '' }
          - { name: 'RcHashMap (random-state-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features random-state-hash' }
          - { name: 'RcHashMap (xxh3-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features xxh3-hash' }
        exclude:
          # Access benchmarks are not hash-dependent; skip for alt hash configs
          - row: { name: 'access random increment', filter: 'access/random_increment_100k$' }
            ds: { name: 'RcHashMap (random-state-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features random-state-hash' }
          - row: { name: 'access iter all', filter: 'access/iter_all_100k$' }
            ds: { name: 'RcHashMap (random-state-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features random-state-hash' }
          - row: { name: 'access iter_mut increment all', filter: 'access/iter_mut_increment_all_100k$' }
            ds: { name: 'RcHashMap (random-state-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features random-state-hash' }
          - row: { name: 'access random increment', filter: 'access/random_increment_100k$' }
            ds: { name: 'RcHashMap (xxh3-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features xxh3-hash' }
          - row: { name: 'access iter all', filter: 'access/iter_all_100k$' }
            ds: { name: 'RcHashMap (xxh3-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features xxh3-hash' }
          - row: { name: 'access iter_mut increment all', filter: 'access/iter_mut_increment_all_100k$' }
            ds: { name: 'RcHashMap (xxh3-hash)', bench: 'rc_hashmap_bench', flags: '--no-default-features --features xxh3-hash' }
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo (benches)
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: benches

      - name: Install cargo-criterion
        run: cargo install cargo-criterion --debug

      - name: Run criterion matrix cell
        run: |
          set -euo pipefail
          fn="bench-${{ matrix.row.name }}-${{ matrix.ds.name }}.jsonl"
          cargo criterion ${{ matrix.ds.flags }} --bench ${{ matrix.ds.bench }} \
            --message-format=json -- ${{ matrix.row.filter }} > "$fn"
          ls -l "$fn"

      - name: Upload JSONL artifact
        uses: actions/upload-artifact@v4
        with:
          name: bench-json-${{ matrix.row.name }}-${{ matrix.ds.name }}
          path: bench-${{ matrix.row.name }}-${{ matrix.ds.name }}.jsonl

  benches-aggregate:
    name: Benches - aggregate and summarize
    runs-on: ubuntu-latest
    needs: benches-run
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Download bench artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: bench-json-*
          merge-multiple: true

      - name: Merge JSONL
        run: |
          shopt -s nullglob
          cat bench-*.jsonl > combined.jsonl || true
          echo "Combined lines:" $(wc -l < combined.jsonl || echo 0)
          ls -l combined.jsonl || true

      - name: Render table
        run: |
          python3 benches/bench_to_table.py combined.jsonl > bench-table.md
          echo '## Benchmark Throughput (M elems/sec)' >> "$GITHUB_STEP_SUMMARY"
          echo 'Note: GitHub actions runners are shared, might run on old hardware, and are considered noisy. Take results with a grain of salt.' >> "$GITHUB_STEP_SUMMARY"
          cat bench-table.md >> "$GITHUB_STEP_SUMMARY"
          echo "\n\n" >> "$GITHUB_STEP_SUMMARY"
          echo '"access" benchmarks are not dependent on hash, so are not re-run with different hashes. These cells contain "-".' >> "$GITHUB_STEP_SUMMARY"