-
Notifications
You must be signed in to change notification settings - Fork 49
Add fastutil to optimize primitive collections #552
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
base: develop
Are you sure you want to change the base?
Conversation
|
This looks very intersting! Have you profiled it to see how much faster it is and how much memory it saves? I don't know anything about fastutil, so I will have to do a little research before I can review you PR with any confidence, so please be patient with me. Minor issue: |
|
The gain from micro optimizations like these is generally pretty small, unless you’re doing thousands of operations per second. There was a time, 30 years ago, when JVMs really sucked at this kind of thing, but that’s no longer the case. And I would like to point out that these commits have been created by Claude, which means that any contribution it makes is rather questionable in terms of copyright. |
Replaced six HashMaps with fastutil primitive collections to eliminate autoboxing overhead in ProfileData: Changes: - Map<Integer, Double> transactionBuyTax → Int2DoubleOpenHashMap - Map<Long, Double> transactionSellTax → Long2DoubleOpenHashMap - Map<Long, Double> marketOrdersBrokersFee → Long2DoubleOpenHashMap - Map<Integer, MarketPriceData> transactionSellPriceData → Int2ObjectOpenHashMap - Map<Integer, MarketPriceData> transactionBuyPriceData → Int2ObjectOpenHashMap - Map<Integer, List<MyAsset>> uniqueAssetsDuplicates → Int2ObjectOpenHashMap Added dependency: - it.unimi.dsi:fastutil:8.5.15 (Apache 2.0 license) Technical details: - Fastutil primitive maps avoid wrapper object allocation - Used primitive get(long)/put(long, double) methods - Added null-checking: fastutil returns 0.0 for missing keys instead of null - Explicit primitive casts to avoid method ambiguity - Int2ObjectOpenHashMap uses primitive int keys with object values - No boxing/unboxing on key operations (get/put/containsKey) - Method signature updated: createTransactionsPriceData() now uses Int2ObjectOpenHashMap Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Convert many HashMap instances with primitive keys (Long, Integer) or primitive values (Double, Float) to fastutil primitive collections. This eliminates autoboxing overhead which caused millions of wrapper object allocations during data operations. Changes across ~46 files: - Int2ObjectOpenHashMap for Integer-keyed maps (~25 instances) - Long2ObjectOpenHashMap for Long-keyed maps (~30 instances) - Int2DoubleOpenHashMap for Integer->Double maps (~8 instances) - Int2FloatOpenHashMap for Integer->Float maps (~3 instances) - Long2LongOpenHashMap for Long->Long maps (2 instances) Key areas converted: - Core data structures (StaticData, Settings, ProfileData) - ESI layer (EsiConverter, getters, manufacturing prices) - Persistence layer (readers, writers, profile tables) - GUI data models (MenuData, StockpileData, OutbidProcesser) Also fixes deprecation warnings by using primitive-specific methods: - .longValue()/.intValue() for map key access - long2ObjectEntrySet()/int2DoubleEntrySet() for iteration - .getLongKey()/.getIntKey() for entry key access Test results: 81 offline tests pass, build compiles cleanly with -Werror GC improvement: Full data update completes with 0 full GC pauses Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
I would say an approximate upper-bound on memory savings is 10-15% of memory from what I have seen. What is happening is that all of the places where EVE resource IDs (typically |
501e4e6 to
c6ba33f
Compare
This pull request adds
fastutiland replaces a number of standard JavaMaps with type-specific implementations that avoid the autoboxing of numeric primitives into objects. This has the effect of modestly reducing the application's memory footprint in various cases, reducing the need for full-GC runs during normal operations.