Skip to content

feat(util): add ConcurrentHashtable with lock-free D1/D2 composite-key tables#11675

Draft
dougqh wants to merge 3 commits into
masterfrom
feat/concurrent-hashtable
Draft

feat(util): add ConcurrentHashtable with lock-free D1/D2 composite-key tables#11675
dougqh wants to merge 3 commits into
masterfrom
feat/concurrent-hashtable

Conversation

@dougqh

@dougqh dougqh commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds ConcurrentHashtable with D1 (single-key) and D2 (composite-key) inner classes, mirroring the Hashtable API with concurrent access guarantees
  • Lock-free get / getOrCreate fast path via AtomicReferenceArray volatile bucket reads; synchronized only on miss with double-checked re-read under lock
  • Shared mechanics (bucketIndex, forEach) extracted into ConcurrentHashtable.Support, following the Hashtable.Support pattern
  • D2.get(K1, K2) and D2.getOrCreate(K1, K2, creator) accept key parts directly — no composite key object allocated for the lookup, unlike ConcurrentHashMap<Pair<K1,K2>, V> where EA must conservatively treat the key as escaping even on hits (ownership-transfer contract)
  • Adds ConcurrentHashtableD1Test and ConcurrentHashtableD2Test (JUnit 5), including a concurrency correctness test verifying exactly one entry is created under 16 racing threads
  • Adds ConcurrentHashtableD2Benchmark comparing get and getOrCreate throughput against ConcurrentHashMap and ConcurrentSkipListMap with shared Scope.Benchmark state (all threads hitting the same table)

Test plan

  • ./gradlew :internal-api:test --tests "datadog.trace.util.ConcurrentHashtable*" — all tests pass
  • ./gradlew :internal-api:jmhCompileGeneratedClasses — benchmark compiles clean
  • Run ConcurrentHashtableD2Benchmark locally to validate get/getOrCreate throughput advantage over CHM and CSLM

🤖 Generated with Claude Code

dougqh and others added 2 commits June 18, 2026 11:44
…y tables

Mirrors Hashtable's D1/D2 API with concurrent access guarantees: lock-free
get via AtomicReferenceArray volatile reads, synchronized getOrCreate with
double-checked re-read on miss. Eliminates composite key object allocation
on hot read paths — the same structural advantage Hashtable.D2 has over
HashMap<Pair<K1,K2>,V>, but thread-safe.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t class; add D2 benchmark

Extract bucketIndex and forEach into ConcurrentHashtable.Support, mirroring the
Hashtable.Support pattern. Add ConcurrentHashtableD2Benchmark comparing get and
getOrCreate throughput against ConcurrentHashMap and ConcurrentSkipListMap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 6 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-java | spotless   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-java | test_inst_latest: [21, 1/6]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-java | java-startup-parallel-check-slo-breaches   View in Datadog   GitLab

View all 6 failed jobs.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f415b3b | Docs | Datadog PR Page | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.02 s 13.99 s [-0.6%; +1.0%] (no difference)
startup:insecure-bank:tracing:Agent 12.98 s 13.05 s [-1.4%; +0.4%] (no difference)
startup:petclinic:appsec:Agent 16.93 s 16.67 s [+0.6%; +2.4%] (maybe worse)
startup:petclinic:iast:Agent 16.82 s 17.01 s [-1.9%; -0.3%] (maybe better)
startup:petclinic:profiling:Agent 16.18 s 16.88 s [-8.3%; -0.1%] (maybe better)
startup:petclinic:sca:Agent 16.86 s 16.60 s [+0.8%; +2.5%] (maybe worse)
startup:petclinic:tracing:Agent 15.67 s 15.95 s [-6.1%; +2.6%] (no difference)

Commit: f415b3b0 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

… ConcurrentHashtable

Two gaps filled per-dimension (D1 and D2):
- Chain collision: force multiple entries into the same bucket (CollidingKey
  with fixed hashCode for D1; pigeonhole via 2-bucket table for D2) and verify
  all entries are reachable after concurrent inserts.
- Concurrent distinct keys: 16 threads each insert a unique key simultaneously,
  verifying final size and that every key is retrievable — exercises concurrent
  inserts to different buckets, which the single-shared-key test does not cover.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant