简体   繁体   中英

ConcurrentHashMap Initialization

We are using below ConcurrentHashMap as a Cache in our multithreaded application.

private static Map<String, TransactionPriceItemDetailSummaryVO> pritmSummaryMap = new ConcurrentHashMap<String, TransactionPriceItemDetailSummaryVO>();

We are creating 130 Threads which are accessing and updating this Map.

Final Map size is around 100 Million (Objects).

I have read online that we need to specify parameters for ConcurrentHasMap to improve it's performance.

Can anyone suggest how can we calculate parameters for our case?

Also, is it a best practice to call clear() on this map to release the memory?

From java doc : Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table. Since you say

... 130 Threads which are accessing and updating this Map

then you should use

new ConcurrentHashMap<String, TransactionPriceItemDetailSummaryVO>(130)

And as @Bohemian says, set some greater value to avoid resize. Call clear only if you don't need the content.

You can configure your Map with the following constructor:

ConcurrentHashMap<K,V>(initialCapacity, loadFactor, concurrencyLevel) .

initialCapacity : Although you have mentioned that you will be inserting 100M objects, are you going to keep them in the map? or is it like adding and removing objects? if you are going to keep all of them and not removing them, makes sense to keep this value as 110_000_000 suggested by Bohemian, otherwise, you should keep it as the appx avg size of the map at any given point of time.

loadFactor : The higher value of load factor reduces space overhead but increase the lookup cost. Meaning it has a significant effect on get and put because both of these methods does lookup internally. By default, it's 0.75 which is usually considered as a good tradeoff between space utilization and look up time.

concurrencyLevel : The estimated number of concurrently updating threads. In which case, you have mentioned number to be 130

Above values could further be drilled down by analyzing when you are calling clear() to remove all elements.

100 Million objects on a Map!

IMO, having this much objects in a static map is never a good idea. Also, this bloats your memory usage by Java since the Map will be occupying so much memory. You can experience frequent out of memory error in your application server and the dump will always have java.util.Map(followed by useless hash code) on the top every time.

Trust me, you don't want to see it the hard way. Also, when 130 threads are accessing, and who knows your application may even hold more than 200 Million objects tomorrow,300 Million the day-after! Always keep in mind what can cause this go hay-wire!

Suggestion : You can go ahead with serializing (by converting to JSON?) TransactionPriceItemDetailSummaryVO and saving it in Redis. Sensing some scalability? Simple, add hardware to your redis server!

Also, Redis has many expiry policies(ttl, which is wonderful!)

With such a large number of entries and threads, you can help the implementation perform better by telling it the expected sizing of such via a constructor :

new ConcurrentHashMap<>(110_000_000, 10, 130);

Experiment with different numbers to find what works.

Note that with that many items, you're going to get a high hash collision rate. Consider using nested maps based on different keys so each map has less entries, say under 1M.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM