-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
posts/5-java-mundane-performance-tricks #30
Comments
Very informative |
Great tips! |
If we're going to go through the trouble of making a composite key "wrapper" object (item 2), we should consider making it mutable and reusing it. I created my own Pair (running Java 17, don't have javafx), and made it so the elements are mutable, and created another benchmark:
I see a further 5% performance improvement, and (obviously) a complete elimination of allocations
Of course, one must make sure they never reuse such a "wrapper" object that was |
@danjmarques that saves 2ns and 24 bytes per lookup, but risks a memory leak. I would proceed with caution in that direction, and only if this is your application’s primary function and bottleneck. |
@danjmarques @richardstartin the That said, unless this is a critical bottleneck, why not avoid this risk/work and let the JVM optimize (maybe scalar replacement is even possible in some cases?). When JEP 169 (value types) goes to GA, it seems like compatible value type replacements might also supersede this when keys are composite on primitives. |
@mikejhill @richardstartin Mutability of keys is dangerous, of course, if the key object is the one stored in the map. For lookups, they are safe (I mean, presuming some other thread isn't changing the key). It seems that, once it becomes important to make "lookup much faster and reduce allocation rate" you might want make it even faster and eliminate allocation all together. The flyweight as map key is actually a pretty standard trick in low-latency messaging. Let's say each message you receive has a "topic" and you need to do some lookup based on that topic. If your message is just some bytes you've received into a buffer, and you know that the "topic" is some offset N into the buffer, of length L, you just wrap the buffer under your pre-allocated flyweight key, and do the lookup with that. Of course, you must be careful to make sure you don't accidentally store that pre-allocated key in the map. |
@danjmarques there are applications where it makes sense to avoid allowing the GC to run, so keep allocation at an absolute minimum, but the post isn’t aimed at people working on low latency systems, this is more about how someone working on the median Java application can arm themselves with simple defence mechanisms to avoid unnecessary inefficiency. You’re right, you can go further than this post demonstrates, but it wouldn’t be appropriate in some teams where some developer will end up putting a mutable key in the map and mutating it. |
@richardstartin "...about how someone working on the median Java application ... simple defence mechanisms to avoid unnecessary inefficiency". Yes, understood, and I think your examples do a great job of that. I was just expanding on one of those examples - I figured that a developer which saw/understood the ideas you presented for the first time might be interested to "push it" a bit further ("can we eliminate the allocations completely? how much performance do we gain?"). And I think once someone understands why that flyweight key can't be put into the map they show a pretty significant maturity as a dev (and I love asking a similar question when I interview). |
I don't understand , on tip number 2, the reason why wrapping is better than String concatenation . You say "String instance caches its hash code, and constructing a new String requires calculation of a new hash code and String’s hash code algorithm also isn’t very efficient." I guess that it's also required to calculate Pair hash in and I don't think that Pair's hashing algorithm be worse than String's Thanks |
Let's say you have two |
This is very interesting. Thanks for sharing! I reproduced your benchmarks and realized that for Those are my results
My code is here Again, thanks for sharing! |
5 Mundane Java Performance Tips | Richard Startin’s Blog
Most of the time it isn’t really necessary to optimise software, but this post contains 5 tips to avoid making software written in Java slower for the sake of it.
https://richardstartin.github.io/posts/5-java-mundane-performance-tricks
The text was updated successfully, but these errors were encountered: