8322149: ConcurrentHashMap smarter presizing for copy constructor and putAll

Reviewed-by: shade, simonis
This commit is contained in:
Joshua Cao 2024-01-24 18:52:38 +00:00 committed by Volker Simonis
parent fb822e49f2
commit c432dc008b
2 changed files with 26 additions and 3 deletions

View file

@ -848,7 +848,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* @param m the map * @param m the map
*/ */
public ConcurrentHashMap(Map<? extends K, ? extends V> m) { public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
this.sizeCtl = DEFAULT_CAPACITY; this(m.size());
putAll(m); putAll(m);
} }
@ -1084,7 +1084,9 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* @param m mappings to be stored in this map * @param m mappings to be stored in this map
*/ */
public void putAll(Map<? extends K, ? extends V> m) { public void putAll(Map<? extends K, ? extends V> m) {
tryPresize(m.size()); if (table != null) {
tryPresize(size() + m.size());
}
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
putVal(e.getKey(), e.getValue(), false); putVal(e.getKey(), e.getValue(), false);
} }

View file

@ -28,6 +28,7 @@ import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.State;
@ -48,6 +49,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class Maps { public class Maps {
private SimpleRandom rng; private SimpleRandom rng;
private Map<Integer, Integer> map; private Map<Integer, Integer> map;
private Map<Integer, Integer> staticMap;
private Integer[] key; private Integer[] key;
private int removesPerMaxRandom; private int removesPerMaxRandom;
@ -55,9 +57,11 @@ public class Maps {
private int total; private int total;
private int position; private int position;
@Param("10000")
private int nkeys;
@Setup @Setup
public void initTest() { public void initTest() {
int nkeys = 10000;
int pRemove = 10; int pRemove = 10;
int pInsert = 90; int pInsert = 90;
removesPerMaxRandom = (int) ((pRemove / 100.0 * 0x7FFFFFFFL)); removesPerMaxRandom = (int) ((pRemove / 100.0 * 0x7FFFFFFFL));
@ -65,10 +69,12 @@ public class Maps {
rng = new SimpleRandom(); rng = new SimpleRandom();
map = new ConcurrentHashMap<>(); map = new ConcurrentHashMap<>();
staticMap = new ConcurrentHashMap<>();
total = 0; total = 0;
key = new Integer[nkeys]; key = new Integer[nkeys];
for (int i = 0; i < key.length; ++i) { for (int i = 0; i < key.length; ++i) {
key[i] = rng.next(); key[i] = rng.next();
staticMap.put(rng.next(), rng.next());
} }
position = key.length / 2; position = key.length / 2;
} }
@ -106,6 +112,21 @@ public class Maps {
position = pos; position = pos;
} }
@Benchmark
public ConcurrentHashMap<Integer, Integer> testConcurrentHashMapCopyConstructor() {
return new ConcurrentHashMap<>(staticMap);
}
@Benchmark
public ConcurrentHashMap<Integer, Integer> testConcurrentHashMapPutAll() {
ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>(nkeys);
for (int i = 0; i < nkeys; ++i) {
map.put(rng.next(), rng.next());
}
map.putAll(staticMap);
return map;
}
private static class SimpleRandom { private static class SimpleRandom {
private final static long multiplier = 0x5DEECE66DL; private final static long multiplier = 0x5DEECE66DL;
private final static long addend = 0xBL; private final static long addend = 0xBL;