gnodet opened a new pull request, #23766:
URL: https://github.com/apache/camel/pull/23766

   ## Summary
   
   Replace the `TreeMap`-based `CaseInsensitiveMap` with a custom hash table 
implementation, improving the performance of every header access in every Camel 
route.
   
   `CaseInsensitiveMap` is the default headers map for every `Exchange` in 
Camel. It is the most accessed data structure in the framework — every 
`message.getHeader()`, `setHeader()`, `removeHeader()`, and header iteration 
goes through it.
   
   ### Before (TreeMap with `CASE_INSENSITIVE_ORDER`)
   - **O(log n)** for `get`, `put`, `containsKey`, `remove`
   - String comparisons at every tree node during lookup
   - Deserialized header keys allocate duplicate `String` objects across 
exchanges
   - To get O(1), users needed the `camel-headersmap` dependency (cedarsoftware 
`java-util`, which uses `ThreadLocal` internally — problematic with virtual 
threads)
   
   ### After (custom hash table)
   - **O(1)** for `get`, `put`, `containsKey`, `remove`
   - **Zero allocation on lookups** — case-insensitive hash computed 
char-by-char with `Character.toLowerCase(Character.toUpperCase(c))`, keys 
compared with `equalsIgnoreCase()`. No `toLowerCase()` string copies
   - **Header key deduplication** — well-known `Exchange` header constants (141 
keys) are registered at startup; deserialized keys matching a known constant 
are replaced with the canonical interned reference, reducing memory across 
exchanges
   - Entries stored in **insertion order** (deterministic iteration)
   - Original key case preserved (first-put case wins, same as before)
   - No external dependencies, no `ThreadLocal`
   - Eliminates the need for `camel-headersmap` in most cases
   
   ### Design
   
   The map extends `AbstractMap` and implements its own hash table with 
separate chaining using parallel arrays (`keys[]`, `values[]`, `chainNext[]`). 
This gives cache-friendly storage and avoids per-entry object allocation 
overhead of `HashMap.Node`.
   
   The hash function uses the same two-step fold as `String.equalsIgnoreCase()` 
— `Character.toLowerCase(Character.toUpperCase(c))` — ensuring hash consistency 
even for Unicode edge cases (e.g., Turkish dotless-ı).
   
   `DefaultHeadersMapFactory` registers all `Exchange` string constants at 
startup via `CaseInsensitiveMap.registerKnownKeys()`. On `put()`, a 
zero-allocation lookup in the static known-keys table replaces deserialized 
keys with canonical references.
   
   ### Compatibility
   
   - The `Map<String, Object>` API is unchanged
   - `DefaultHeadersMapFactory` and `instanceof CaseInsensitiveMap` checks work 
as before
   - No code in the codebase uses `SortedMap`/`NavigableMap` methods on this map
   - Iteration order changes from alphabetical (TreeMap) to insertion order — 
no code depends on alphabetical ordering
   - All existing tests pass; 10 new tests added
   
   ## Test plan
   
   - [x] `CaseInsensitiveMapTest` — 32 tests (+ 10 new: insertion order, 
iterator removal, entry setValue, entrySet remove, remove-then-reput, 
resize/rehash, containsValue, null values, clear-reuse, known key deduplication)
   - [x] `DefaultMessageHeaderTest` — 16 tests
   - [x] Formatter and import sort clean


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to