Why Netty’s IntObjectHashMap Beats HashMap: Deep Dive into Performance and Design
This article explores Netty’s IntObjectHashMap, explaining how its use of primitive int keys and open‑addressing linear probing reduces memory overhead and improves performance compared to standard HashMap, while detailing its source‑code evolution, capacity handling, probing strategy, load factor, and deletion compaction.
Background
In a Bilibili video about high‑concurrency ticket pricing, Qunar’s engineers showed that compressing data saved 204C and 2160C of server resources, equivalent to 591 machines.
One of the techniques they used was replacing the standard HashMap with Netty’s IntObjectHashMap, which stores primitive int keys.
Finding the Source
The author fetched the Netty source, discovered that IntObjectHashMap is not present in the 4.1 branch but exists in 4.0. The class and its benchmark test were located and examined.
Key Design Points
Uses open addressing with linear probing to resolve hash collisions, minimizing memory footprint.
Key type is primitive int, avoiding the overhead of boxed Integer objects.
Value is stored directly as an Object without extra node structures.
hashIndex Evolution
The method that maps an int key to an index evolved through three commits:
return (key % keys.length + keys.length) % keys.length;
This formula guarantees a non‑negative index regardless of the sign of the key.
put Method Walkthrough
The put method first obtains the index via hashIndex, then checks value[index] == null. If the slot is empty, the key and value are stored; otherwise the method probes the next slot (wrapping to 0 at the end) until an empty slot or the original start index is reached, at which point an “Unable to insert” exception is thrown.
Capacity and Load Factor
The constructor adjusts the requested capacity to an odd number because even capacities can break probing (in 4.0). The maxSize is computed as capacity * loadFactor, with a default load factor of 0.5. A smaller load factor triggers earlier resizing, while a larger one delays it.
Deletion and Compaction
When an entry is removed, the map performs a compaction step that may shift subsequent entries to fill the gap, potentially costing O(N) in the worst case. This is why a modest load factor is recommended.
Later Changes
GitHub issue #2659 shows that the map originally used double hashing and was later switched to linear probing, along with other optimizations such as a different capacity‑adjustment strategy in Netty 4.1.
Conclusion
IntObjectHashMap achieves better performance than HashMap by eliminating boxed keys, reducing per‑entry overhead, and using a memory‑efficient probing strategy, making it suitable for high‑throughput scenarios like Qunar’s ticket‑pricing service.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
