Skip to content

Unify Hashtable static API with ConcurrentHashtable; deprecate Support - #12101

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

Unify Hashtable static API with ConcurrentHashtable; deprecate Support#12101
dougqh wants to merge 3 commits into
masterfrom
feat/hashtable-api-unification

Conversation

@dougqh

@dougqh dougqh commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What Does This Do?

Unifies the Hashtable static API with ConcurrentHashtable's flat layout, ahead of treating the two as one family (see #11675).

  • Moves the static building blocks off the nested Support class onto Hashtable itselfsizeFor, bucketIndex, bucket, insertHeadEntry, clear, forEach, and the iterator factories (bucketIterator, mutatingBucketIterator, mutatingTableIterator) — mirroring ConcurrentHashtable's "static functions over a caller-owned array" shape.
  • Adds createFixedBuckets(Class<TEntry> entryClass, int capacity) factories on Hashtable, D1, and D2 for family symmetry with ConcurrentHashtable/FlatHashtable. On Hashtable it returns a concrete Hashtable.Entry[] (chain heads stored at the base type — the array is a heterogeneous Entry[], not a reflectively-allocated TEntry[], so entryClass anchors inference/call-shape but is not consumed to allocate). D1/D2.createFixedBuckets return a D1/D2 instance.
  • Adds D2.Entry.key1() / key2() accessors to match D1 and the concurrent variant.
  • Renames the context type parameter <T><C> on the context-passing forEach overloads (consistent with the naming applied in Add ConcurrentHashtable (perf toolbox) #11675).

Motivation

Hashtable and ConcurrentHashtable are meant to read as one family — same call shapes, same building-block spine — so a caller can move between single-threaded and concurrent variants without relearning the surface. Today the building blocks live on a nested Support class on Hashtable but flat on ConcurrentHashtable. This aligns them.

Support is deprecated, not removed

Support becomes a thin @Deprecated facade that delegates to the new statics, retaining the scaled create(int, float) factory and MAX_RATIO (which have no blessed equivalent — size for load-factor headroom explicitly at the call site instead). Client-side statistics (AggregateTable, AggregateEntry, CardinalityLimitReporter) keep compiling untouched — deprecation is warning-only, so this PR introduces zero churn there. Migrating those consumers off Support is a deliberate follow-up.

No behavior change

Pure API relocation + deprecation. Bodies are unchanged; Support members now delegate.

Test plan

  • ./gradlew :internal-api:compileJava :dd-trace-core:compileJava — client-side-stats consumers compile untouched (deprecation warnings only)
  • ./gradlew :internal-api:test --tests "datadog.trace.util.Hashtable*" — all pass
  • HashtableTest migrated to the blessed API (separate commit), with a small DeprecatedSupportTests group retaining coverage of the deprecated-only scaled create + MAX_RATIO

🤖 Generated with Claude Code

dougqh and others added 2 commits July 29, 2026 11:08
Move the static building blocks off the nested Support class onto Hashtable
itself, mirroring ConcurrentHashtable's flat layout, and add
createFixedBuckets(Class, int) factories on Hashtable/D1/D2 for family
symmetry. Support becomes a thin @deprecated facade delegating to the new
statics (retaining the scaled create(int, float)/MAX_RATIO helpers, which have
no blessed equivalent), so client-side-statistics callers keep compiling
untouched. Rename the context type parameter <T> -> <C> on the context-passing
forEach overloads, and add D2.Entry.key1()/key2() accessors to match D1/the
concurrent variant.

No behavior change; pure API relocation + deprecation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Point the tests at the relocated static building blocks on Hashtable
(createFixedBuckets, sizeFor, bucketIndex, clear, insertHeadEntry, and
the iterator factories) instead of the now-deprecated Support facade.

Keep a small DeprecatedSupportTests group covering the deprecated-only
scaled create(int, float) + MAX_RATIO, which have no blessed equivalent
and remain in use by client-side statistics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dougqh dougqh added comp: core Tracer core tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes type: refactoring labels Jul 29, 2026
@dougqh

dougqh commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@datadog-prod-us1-4

datadog-prod-us1-4 Bot commented Jul 29, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 75.58%
Overall Coverage: 57.34% (-0.48%)

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4643cba67

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

*/
@Deprecated
public static final class Support {
private Support() {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the deprecated Support constructor

Because Support was a public nested class with an implicit public no-arg constructor, making the constructor private breaks source and binary compatibility for any existing consumer that instantiated the facade, even if only as a namespace: recompilation now fails, and already-compiled bytecode can hit an access error when loading against this version. Since this change is explicitly keeping Support as a deprecated compatibility facade, leave a deprecated public no-op constructor (or omit the explicit constructor) until the facade is actually removed.

Useful? React with 👍 / 👎.

* size {@code n} should pass {@code create(n, MAX_RATIO)} to leave ~25% headroom in the array.
*/
public static final float MAX_RATIO = 4.0f / 3.0f;
@Deprecated public static final float MAX_RATIO = 4.0f / 3.0f;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Retain Support.MAX_BUCKETS in the facade

Right next to the retained MAX_RATIO, the deprecated facade no longer exposes the package-private MAX_BUCKETS constant that Support previously had. Any in-package consumer (including downstream tests or custom table helpers compiled in datadog.trace.util) that sizes or bounds-checks against Hashtable.Support.MAX_BUCKETS now fails to recompile even though the facade is advertised as source-compatible; keep a deprecated Support.MAX_BUCKETS alias to the outer constant.

Useful? React with 👍 / 👎.

}

/** The first key part this entry was created with. */
public K1 key1() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Avoid colliding with subclass key1 helpers

Adding key1()/key2() to the subclassable D2.Entry base class can break existing custom D2 entries that already used those natural helper names with weaker visibility (for example private or package-private accessors): those subclasses compiled against the old API but now fail to recompile because the methods are treated as invalid overrides. If preserving source compatibility for this internal API matters, consider less collision-prone names or another migration path before adding these accessors.

Useful? React with 👍 / 👎.

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

Labels

comp: core Tracer core tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes type: refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant