4 ms·
Why and how we use primitive maps
- _old_dude_ 5y agoI think the busy loop version can use Thread.onSpinWait() to improve performance if the tryLock fails. [1] https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html#onSpinWait https://docs.oracle.com/en/java/javase/17/docs/api/java.base...()
- charleslmunger 5y agoIndeed, although userspace spinlocks are almost always a bad idea, it's possible to write a much better one than repurposing ReadWriteLock. 1. As you say, use onSpinWait 2. It emits a load barrier on each failed trylock call, from the underlying strong integer CAS. Ideally it would use a cas with relaxed memory order, and use an acquire fence only if successful. 3. The read path emits store barriers on release, which is unnecessary. Releasing could use a relaxed order fetch-add instruction. It's theoretically possible that the JIT would be smart enough to optimize these with the existing code, but that's asking a lot from its analysis, including that the thread local storage writes for detecting reentrance aren't "real" writes that need to be made visible to other threads.
- MattPalmer1086 5y agoInteresting. I don't have anything to add to this, but by a very strange coincidence I was working on exactly the same things as this article describes today - packing smaller fields into an integer with bitwise operations and using the primitive maps in fastutil.
- jenny91 5y agoIs this saying every Java object (struct?) has 16 bytes of storage overhead? Does that apply to arrays of objects too?
- deleted 5y ago[deleted]
- djur 5y agoYes, in 64-bit HotSpot every object has a 16-byte header, and it applies to arrays if by that you mean that each object in an array still has a header. There's a good overview of what that space is used for here: https://wiki.openjdk.java.net/display/lilliput/Main https://wiki.openjdk.java.net/display/lilliput/Main