diff --git a/core-java-modules/core-java-collections-maps-3/pom.xml b/core-java-modules/core-java-collections-maps-3/pom.xml index f547968b22..577ad58255 100644 --- a/core-java-modules/core-java-collections-maps-3/pom.xml +++ b/core-java-modules/core-java-collections-maps-3/pom.xml @@ -15,7 +15,11 @@ - + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + diff --git a/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java new file mode 100644 index 0000000000..c788dbc27d --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java @@ -0,0 +1,96 @@ +package com.baeldung.map.concurrenthashmap; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(5) +@Threads(10) +@Warmup(iterations = 5) +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class MapPerformanceComparison { + + private int TEST_NO_ITEMS; + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Setup + public void setup() { + TEST_NO_ITEMS = 1000; + } + + @Benchmark + public void randomReadAndWriteSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performReadAndWriteTest(map); + } + + @Benchmark + public void randomReadAndWriteConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performReadAndWriteTest(map); + } + + private void performReadAndWriteTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.get(String.valueOf(randNumber)); + map.put(String.valueOf(randNumber), randNumber); + } + } + + @Benchmark + public void randomWriteSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performWriteTest(map); + } + + @Benchmark + public void randomWriteConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performWriteTest(map); + } + + private void performWriteTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.put(String.valueOf(randNumber), randNumber); + } + } + + @Benchmark + public void randomReadSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performReadTest(map); + } + + @Benchmark + public void randomReadConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performReadTest(map); + } + + private void performReadTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.get(String.valueOf(randNumber)); + } + } +} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorTest.java deleted file mode 100644 index 998496720e..0000000000 --- a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.map.concurrenthashmap; - -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; - -import org.junit.Assert; -import org.junit.Test; - -public class ConcurrentModificationErrorTest { - - @Test(expected = ConcurrentModificationException.class) - public void whenRemoveAndAddOnHashMap_thenConcurrentModificationError() { - Map map = new HashMap<>(); - map.put(1, "baeldung"); - map.put(2, "HashMap"); - Map synchronizedMap = Collections.synchronizedMap(map); - Iterator> iterator = synchronizedMap.entrySet().iterator(); - while (iterator.hasNext()) { - synchronizedMap.put(4, "Modification"); - iterator.next(); - } - } - - public void whenRemoveAndAddOnConcurrentHashMap_thenNoError() { - Map map = new ConcurrentHashMap<>(); - map.put(1, "baeldung"); - map.put(2, "HashMap"); - Iterator> iterator = map.entrySet().iterator(); - while (iterator.hasNext()) { - map.put(4, "Modification"); - iterator.next(); - } - - Assert.assertEquals(4, map.size()); - } -} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapTest.java deleted file mode 100644 index 23c76e59e8..0000000000 --- a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.map.concurrenthashmap; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.junit.Assert; -import org.junit.Test; - -public class NullAllowInMapTest { - - @Test - public void allowOnlyNull_In_SynchronizedMap() { - Map map = Collections - .synchronizedMap(new HashMap()); - map.put(null, 1); - Assert.assertTrue(map.get(null).equals(1)); - } - - @Test(expected = NullPointerException.class) - public void allowOnlyNull_In_ConcurrentHasMap() { - Map map = new ConcurrentHashMap<>(); - map.put(null, 1); - } - -} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/PerformanceTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/PerformanceTest.java deleted file mode 100644 index 5321d33b36..0000000000 --- a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/PerformanceTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.baeldung.map.concurrenthashmap; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.junit.Assert; -import org.junit.Test; - -public class PerformanceTest { - - public final static int THREAD_POOL_SIZE = 5; - public final static int TEST_ITERATIONS = 5; - public final static int TEST_NO_ITEMS = 10000; - - @Test - public void randomReadAndWritePerformaceTest_ConcurrentHashMap_faster() - throws InterruptedException { - // For synchronizedMap - Long totalTimeForSynchronizedMap = 0l; - Map slowerMap = Collections - .synchronizedMap(new HashMap()); - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForSynchronizedMap += performReadAndWriteTest(slowerMap); - } - Long avgTimeForSynchronizedMap = totalTimeForSynchronizedMap / TEST_ITERATIONS; - - // For ConcurrentHashMap Object - Long totalTimeForConcurrentHashMap = 0l; - Map fasterMap = new ConcurrentHashMap<>(); - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForConcurrentHashMap += performReadAndWriteTest(fasterMap); - } - Long avgTimeForConcurrentHashMap = totalTimeForConcurrentHashMap / TEST_ITERATIONS; - - Assert.assertTrue(avgTimeForSynchronizedMap > avgTimeForConcurrentHashMap); - } - - private long performReadAndWriteTest(final Map map) - throws InterruptedException { - long startTime = System.nanoTime(); - ExecutorService exectures = Executors.newFixedThreadPool(THREAD_POOL_SIZE); - for (int j = 0; j < THREAD_POOL_SIZE; j++) { - exectures.execute(new Runnable() { - @Override - public void run() { - for (int i = 0; i < TEST_NO_ITEMS; i++) { - Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); - map.get(String.valueOf(randNumber)); - map.put(String.valueOf(randNumber), randNumber); - } - } - }); - } - exectures.shutdown(); - exectures.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); - long entTime = System.nanoTime(); - return (entTime - startTime) / 1000000L; - } - - @Test - public void randomWritePerformaceTest_ConcurrentHashMap_faster() throws InterruptedException { - // For synchronizedMap - Long totalTimeForSynchronizedMap = 0l; - Map slowerMap = Collections - .synchronizedMap(new HashMap()); - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForSynchronizedMap += performWriteTest(slowerMap); - } - Long avgTimeForSynchronizedMap = totalTimeForSynchronizedMap / TEST_ITERATIONS; - - // For ConcurrentHashMap Object - Long totalTimeForConcurrentHashMap = 0l; - Map fasterMap = new ConcurrentHashMap<>(); - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForConcurrentHashMap += performWriteTest(fasterMap); - } - Long avgTimeForConcurrentHashMap = totalTimeForConcurrentHashMap / TEST_ITERATIONS; - - Assert.assertTrue(avgTimeForSynchronizedMap > avgTimeForConcurrentHashMap); - } - - private long performWriteTest(final Map map) throws InterruptedException { - long startTime = System.nanoTime(); - ExecutorService exectures = Executors.newFixedThreadPool(THREAD_POOL_SIZE); - for (int j = 0; j < THREAD_POOL_SIZE; j++) { - exectures.execute(new Runnable() { - @Override - public void run() { - for (int i = 0; i < TEST_NO_ITEMS; i++) { - Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); - map.put(String.valueOf(randNumber), randNumber); - } - } - }); - } - exectures.shutdown(); - exectures.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); - long entTime = System.nanoTime(); - return (entTime - startTime) / 1000000L; - } - - @Test - public void randomReadPerformaceTest_ConcurrentHashMap_faster() throws InterruptedException { - - Map slowerMap = Collections - .synchronizedMap(addItems(new HashMap())); - // For synchronizedMap - Long totalTimeForSynchronizedMap = 0l; - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForSynchronizedMap += performReadTest(slowerMap); - } - Long avgTimeForSynchronizedMap = totalTimeForSynchronizedMap / TEST_ITERATIONS; - - Map fasterMap = addItems(new ConcurrentHashMap()); - // For ConcurrentHashMap Object - Long totalTimeForConcurrentHashMap = 0l; - new ConcurrentHashMap<>(); - for (int i = 0; i < TEST_ITERATIONS; i++) { - totalTimeForConcurrentHashMap += performReadTest(fasterMap); - } - Long avgTimeForConcurrentHashMap = totalTimeForConcurrentHashMap / TEST_ITERATIONS; - - Assert.assertTrue(avgTimeForSynchronizedMap > avgTimeForConcurrentHashMap); - } - - private Map addItems(Map map) { - for (int i = 0; i < TEST_NO_ITEMS; i++) { - Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); - map.put(String.valueOf(randNumber), randNumber); - } - return map; - } - - private long performReadTest(final Map map) throws InterruptedException { - long startTime = System.nanoTime(); - ExecutorService exectures = Executors.newFixedThreadPool(THREAD_POOL_SIZE); - for (int j = 0; j < THREAD_POOL_SIZE; j++) { - exectures.execute(new Runnable() { - @Override - public void run() { - for (int i = 0; i < TEST_NO_ITEMS; i++) { - Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); - map.get(String.valueOf(randNumber)); - } - } - }); - } - exectures.shutdown(); - exectures.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); - long entTime = System.nanoTime(); - return (entTime - startTime) / 1000000L; - } -} \ No newline at end of file