From 61ef5289a506ff3c5eb220be2657a3035c6b7698 Mon Sep 17 00:00:00 2001 From: Fabio Silva Date: Fri, 6 Dec 2019 10:02:29 -0300 Subject: [PATCH 1/4] Pre-compile the regex pattern into a Pattern object and reuse --- .../pattern/PatternJava11UnitTest.java | 31 ++++++++ .../pattern/PatternPerformanceComparison.java | 71 +++++++++++++++++++ .../com/baeldung/pattern/PatternUnitTest.java | 68 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java create mode 100644 core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java create mode 100644 core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java new file mode 100644 index 0000000000..ebb8065a78 --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.pattern; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PatternJava11UnitTest { + + private static final String VALID_NAME = "Fabio Silva"; + private static final String INVALID_NAME = "Fabio Luis Silva"; + private static final List NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME); + private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}"); + + @Test + public void givenPreCompiledPattern_whenCallAsMatchPredicate_thenReturnMatchPredicateToMatchesThePatternInTheListElements() { + Predicate patternAsMatchPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asMatchPredicate(); + List validatedNames = NAMES_TO_VALIDATE.stream() + .filter(patternAsMatchPredicate) + .collect(Collectors.toList()); + + assertTrue(validatedNames.contains(VALID_NAME)); + assertFalse(validatedNames.contains(INVALID_NAME)); + } +} diff --git a/core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java b/core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java new file mode 100644 index 0000000000..711ae3fa85 --- /dev/null +++ b/core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java @@ -0,0 +1,71 @@ +package com.baeldung.pattern; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PatternPerformanceComparison { + + private static final String PATTERN = "\\d*[02468]"; + private static List values; + + public static void main(String[] args) { + loadValues(); + + // 5_000_000 Pattern objects created + // 5_000_000 Matcher objects created + Instant start = Instant.now(); + for (String value : values) { + value.matches(PATTERN); + } + System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> String.matchs(regex)"); + + // Above approach "value.matches(PATTERN)" makes this internally + // 5_000_000 Pattern objects created + // 5_000_000 Matcher objects created + start = Instant.now(); + for (String value : values) { + Pattern.matches(PATTERN, value); + } + System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.matches(regex, charSequence)"); + + // Above approach "Pattern.matches(PATTERN, value)" makes this internally + // 5_000_000 Pattern objects created + // 5_000_000 Matcher objects created + start = Instant.now(); + for (String value : values) { + Pattern.compile(PATTERN).matcher(value).matches(); + } + System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.compile(regex).matcher(charSequence).matches()"); + + // With pre-compiled pattern + // 1 Pattern object created + // 5_000_000 Matcher objects created + Pattern preCompiledPattern = Pattern.compile(PATTERN); + start = Instant.now(); + for (String value : values) { + preCompiledPattern.matcher(value).matches(); + } + System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> preCompiledPattern.matcher(value).matches()"); + + //With pre-compiled pattern and reusing the matcher + // 1 Pattern object created + // 1 Matcher objects created + Matcher matcherFromPreCompiledPattern = preCompiledPattern.matcher(""); + start = Instant.now(); + for (String value : values) { + matcherFromPreCompiledPattern.reset(value).matches(); + } + System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> matcherFromPreCompiledPattern.reset(value).matches()"); + } + + private static void loadValues() { + values = new ArrayList<>(); + for (int x = 1; x <= 5_000_000; x++) { + values.add(String.valueOf(x)); + } + } +} diff --git a/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java b/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java new file mode 100644 index 0000000000..df5c7a3b1d --- /dev/null +++ b/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java @@ -0,0 +1,68 @@ +package com.baeldung.pattern; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class PatternUnitTest { + + private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}"); + private static final String VALID_NAME = "Fabio Silva"; + private static final String INVALID_NAME = "Mr. Silva"; + private static final List NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME); + + private static final Pattern SPLIT_PRE_COMPILED_PATTERN = Pattern.compile("__"); + private static final String TEXT_TO_SPLIT = "My_Name__is__Fabio_Silva"; + + @Test + public void givenPreCompiledPattern_whenCallMatcher_thenReturnAMatcherToMatches() { + Matcher matcherName1 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(VALID_NAME); + Matcher matcherName2 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(INVALID_NAME); + + boolean matchesName1 = matcherName1.matches(); + boolean matchesName2 = matcherName2.matches(); + + assertTrue(matchesName1); + assertFalse(matchesName2); + } + + @Test + public void givenPreCompiledPattern_whenCallAsPredicate_thenReturnPredicateToFindThePatternInTheListElements() { + Predicate patternsAsPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asPredicate(); + + List validNames = NAMES_TO_VALIDATE.stream() + .filter(patternsAsPredicate) + .collect(Collectors.toList()); + + assertEquals(1,validNames.size()); + assertTrue(validNames.contains(VALID_NAME)); + } + + @Test + public void givenPreCompiledPattern_whenCallSplit_thenReturnArrayWithValuesSplitByThePattern() { + String[] textSplit = SPLIT_PRE_COMPILED_PATTERN.split(TEXT_TO_SPLIT); + + assertEquals("My_Name", textSplit[0]); + assertEquals("is", textSplit[1]); + assertEquals("Fabio_Silva", textSplit[2]); + } + + @Test + public void givenPreCompiledPattern_whenCallSplitAsStream_thenReturnArrayWithValuesSplitByThePattern() { + Stream textSplitAsStream = SPLIT_PRE_COMPILED_PATTERN.splitAsStream(TEXT_TO_SPLIT); + String[] textSplit = textSplitAsStream.toArray(String[]::new); + + assertEquals("My_Name", textSplit[0]); + assertEquals("is", textSplit[1]); + assertEquals("Fabio_Silva", textSplit[2]); + } + +} From 9f78f6273205aa58c13c3161ac71ae0b9e6e9a60 Mon Sep 17 00:00:00 2001 From: Fabio Silva Date: Sun, 8 Dec 2019 15:57:34 -0300 Subject: [PATCH 2/4] =?UTF-8?q?Ruy=20Vil=C3=A3o=20suggestions:=20no=20poin?= =?UTF-8?q?t=20in=20declaring=20the=20variables=20for=20the=20match=20resu?= =?UTF-8?q?lt,=20let's=20put=20them=20directly=20in=20the=20assert=20(to?= =?UTF-8?q?=20be=20fixed=20in=20both=20tutorial=20and=20code).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pattern/PatternJava11UnitTest.java | 16 +++++++------- .../com/baeldung/pattern/PatternUnitTest.java | 21 +++++++------------ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java index ebb8065a78..029755820f 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java @@ -13,19 +13,17 @@ import static org.junit.Assert.assertTrue; public class PatternJava11UnitTest { - private static final String VALID_NAME = "Fabio Silva"; - private static final String INVALID_NAME = "Fabio Luis Silva"; - private static final List NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME); - private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}"); - @Test public void givenPreCompiledPattern_whenCallAsMatchPredicate_thenReturnMatchPredicateToMatchesThePatternInTheListElements() { - Predicate patternAsMatchPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asMatchPredicate(); - List validatedNames = NAMES_TO_VALIDATE.stream() + List namesToValidate = Arrays.asList("Fabio Silva", "Fabio Luis Silva"); + Pattern firstLastNamePreCompiledPattern = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}"); + + Predicate patternAsMatchPredicate = firstLastNamePreCompiledPattern.asMatchPredicate(); + List validatedNames = namesToValidate.stream() .filter(patternAsMatchPredicate) .collect(Collectors.toList()); - assertTrue(validatedNames.contains(VALID_NAME)); - assertFalse(validatedNames.contains(INVALID_NAME)); + assertTrue(validatedNames.contains("Fabio Silva")); + assertFalse(validatedNames.contains("Fabio Luis Silva")); } } diff --git a/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java b/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java index df5c7a3b1d..20c98480db 100644 --- a/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java +++ b/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java @@ -15,17 +15,12 @@ import static org.junit.Assert.*; public class PatternUnitTest { private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}"); - private static final String VALID_NAME = "Fabio Silva"; - private static final String INVALID_NAME = "Mr. Silva"; - private static final List NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME); - private static final Pattern SPLIT_PRE_COMPILED_PATTERN = Pattern.compile("__"); - private static final String TEXT_TO_SPLIT = "My_Name__is__Fabio_Silva"; @Test public void givenPreCompiledPattern_whenCallMatcher_thenReturnAMatcherToMatches() { - Matcher matcherName1 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(VALID_NAME); - Matcher matcherName2 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(INVALID_NAME); + Matcher matcherName1 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher("Fabio Silva"); + Matcher matcherName2 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher("Mr. Silva"); boolean matchesName1 = matcherName1.matches(); boolean matchesName2 = matcherName2.matches(); @@ -36,19 +31,20 @@ public class PatternUnitTest { @Test public void givenPreCompiledPattern_whenCallAsPredicate_thenReturnPredicateToFindThePatternInTheListElements() { + List namesToValidate = Arrays.asList("Fabio Silva", "Mr. Silva"); Predicate patternsAsPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asPredicate(); - List validNames = NAMES_TO_VALIDATE.stream() + List validNames = namesToValidate.stream() .filter(patternsAsPredicate) .collect(Collectors.toList()); - assertEquals(1,validNames.size()); - assertTrue(validNames.contains(VALID_NAME)); + assertEquals(1, validNames.size()); + assertTrue(validNames.contains("Fabio Silva")); } @Test public void givenPreCompiledPattern_whenCallSplit_thenReturnArrayWithValuesSplitByThePattern() { - String[] textSplit = SPLIT_PRE_COMPILED_PATTERN.split(TEXT_TO_SPLIT); + String[] textSplit = SPLIT_PRE_COMPILED_PATTERN.split("My_Name__is__Fabio_Silva"); assertEquals("My_Name", textSplit[0]); assertEquals("is", textSplit[1]); @@ -57,12 +53,11 @@ public class PatternUnitTest { @Test public void givenPreCompiledPattern_whenCallSplitAsStream_thenReturnArrayWithValuesSplitByThePattern() { - Stream textSplitAsStream = SPLIT_PRE_COMPILED_PATTERN.splitAsStream(TEXT_TO_SPLIT); + Stream textSplitAsStream = SPLIT_PRE_COMPILED_PATTERN.splitAsStream("My_Name__is__Fabio_Silva"); String[] textSplit = textSplitAsStream.toArray(String[]::new); assertEquals("My_Name", textSplit[0]); assertEquals("is", textSplit[1]); assertEquals("Fabio_Silva", textSplit[2]); } - } From 2d6be72eab939fc659811c12d19335cd674f5f62 Mon Sep 17 00:00:00 2001 From: Fabio Silva Date: Thu, 12 Dec 2019 09:52:43 -0300 Subject: [PATCH 3/4] Josh Cummings suggestions: Package renamed and Benchmark using JMH --- .../PatternJava11UnitTest.java | 2 +- core-java-modules/core-java-text/pom.xml | 13 +++ .../PatternPerformanceComparison.java | 108 +++++++++++------- .../PatternUnitTest.java | 2 +- 4 files changed, 79 insertions(+), 46 deletions(-) rename core-java-modules/core-java-11/src/test/java/com/baeldung/{pattern => patternreuse}/PatternJava11UnitTest.java (96%) rename core-java-modules/core-java-text/src/main/java/com/baeldung/{pattern => patternreuse}/PatternPerformanceComparison.java (60%) rename core-java-modules/core-java-text/src/test/java/com/baeldung/{pattern => patternreuse}/PatternUnitTest.java (98%) diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/patternreuse/PatternJava11UnitTest.java similarity index 96% rename from core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/patternreuse/PatternJava11UnitTest.java index 029755820f..94c8a39c95 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/pattern/PatternJava11UnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/patternreuse/PatternJava11UnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.pattern; +package com.baeldung.patternreuse; import org.junit.jupiter.api.Test; diff --git a/core-java-modules/core-java-text/pom.xml b/core-java-modules/core-java-text/pom.xml index 43b0df6309..f26dddfae4 100644 --- a/core-java-modules/core-java-text/pom.xml +++ b/core-java-modules/core-java-text/pom.xml @@ -13,6 +13,19 @@ ../../parent-java + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + + + core-java-text diff --git a/core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java b/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java similarity index 60% rename from core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java rename to core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java index 711ae3fa85..01a6121ad0 100644 --- a/core-java-modules/core-java-text/src/main/java/com/baeldung/pattern/PatternPerformanceComparison.java +++ b/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java @@ -1,68 +1,88 @@ -package com.baeldung.pattern; +package com.baeldung.patternreuse; -import java.time.Duration; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.RunnerException; + +import java.io.IOException; import java.time.Instant; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 1, warmups = 1) +@Warmup(iterations = 5) +@State(Scope.Benchmark) public class PatternPerformanceComparison { private static final String PATTERN = "\\d*[02468]"; private static List values; - public static void main(String[] args) { - loadValues(); + private static Matcher matcherFromPreCompiledPattern; + private static Pattern preCompiledPattern; + public static void main(String[] args) throws IOException, RunnerException { + org.openjdk.jmh.Main.main(args); + } + + @Benchmark + public void matcherFromPreCompiledPatternResetMatches() { + //With pre-compiled pattern and reusing the matcher + // 1 Pattern object created + // 1 Matcher objects created + for (String value : values) { + matcherFromPreCompiledPattern.reset(value).matches(); + } + } + + @Benchmark + public void preCompiledPatternMatcherMatches() { + // With pre-compiled pattern + // 1 Pattern object created + // 5_000_000 Matcher objects created + for (String value : values) { + preCompiledPattern.matcher(value).matches(); + } + } + + @Benchmark + public void patternCompileMatcherMatches() { + // Above approach "Pattern.matches(PATTERN, value)" makes this internally + // 5_000_000 Pattern objects created + // 5_000_000 Matcher objects created + for (String value : values) { + Pattern.compile(PATTERN).matcher(value).matches(); + } + } + + @Benchmark + public void patternMatches() { + // Above approach "value.matches(PATTERN)" makes this internally + // 5_000_000 Pattern objects created + // 5_000_000 Matcher objects created + for (String value : values) { + Pattern.matches(PATTERN, value); + } + } + + @Benchmark + public void stringMatchs() { // 5_000_000 Pattern objects created // 5_000_000 Matcher objects created Instant start = Instant.now(); for (String value : values) { value.matches(PATTERN); } - System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> String.matchs(regex)"); - - // Above approach "value.matches(PATTERN)" makes this internally - // 5_000_000 Pattern objects created - // 5_000_000 Matcher objects created - start = Instant.now(); - for (String value : values) { - Pattern.matches(PATTERN, value); - } - System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.matches(regex, charSequence)"); - - // Above approach "Pattern.matches(PATTERN, value)" makes this internally - // 5_000_000 Pattern objects created - // 5_000_000 Matcher objects created - start = Instant.now(); - for (String value : values) { - Pattern.compile(PATTERN).matcher(value).matches(); - } - System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.compile(regex).matcher(charSequence).matches()"); - - // With pre-compiled pattern - // 1 Pattern object created - // 5_000_000 Matcher objects created - Pattern preCompiledPattern = Pattern.compile(PATTERN); - start = Instant.now(); - for (String value : values) { - preCompiledPattern.matcher(value).matches(); - } - System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> preCompiledPattern.matcher(value).matches()"); - - //With pre-compiled pattern and reusing the matcher - // 1 Pattern object created - // 1 Matcher objects created - Matcher matcherFromPreCompiledPattern = preCompiledPattern.matcher(""); - start = Instant.now(); - for (String value : values) { - matcherFromPreCompiledPattern.reset(value).matches(); - } - System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> matcherFromPreCompiledPattern.reset(value).matches()"); } - private static void loadValues() { + @Setup() + public void setUp() { + preCompiledPattern = Pattern.compile(PATTERN); + matcherFromPreCompiledPattern = preCompiledPattern.matcher(""); + values = new ArrayList<>(); for (int x = 1; x <= 5_000_000; x++) { values.add(String.valueOf(x)); diff --git a/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java b/core-java-modules/core-java-text/src/test/java/com/baeldung/patternreuse/PatternUnitTest.java similarity index 98% rename from core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java rename to core-java-modules/core-java-text/src/test/java/com/baeldung/patternreuse/PatternUnitTest.java index 20c98480db..70f5c59a95 100644 --- a/core-java-modules/core-java-text/src/test/java/com/baeldung/pattern/PatternUnitTest.java +++ b/core-java-modules/core-java-text/src/test/java/com/baeldung/patternreuse/PatternUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.pattern; +package com.baeldung.patternreuse; import org.junit.jupiter.api.Test; From 9c512c4a82a7920cda404e7be08328036b31a08d Mon Sep 17 00:00:00 2001 From: Fabio Silva Date: Thu, 19 Dec 2019 07:28:51 -0300 Subject: [PATCH 4/4] Josh Cummings suggestions: JMH documentation states that benchmark methods should return a value in order to defend against Dead Code Elimination --- .../PatternPerformanceComparison.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java b/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java index 01a6121ad0..01f8df9ec6 100644 --- a/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java +++ b/core-java-modules/core-java-text/src/main/java/com/baeldung/patternreuse/PatternPerformanceComparison.java @@ -1,6 +1,7 @@ package com.baeldung.patternreuse; import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; import org.openjdk.jmh.runner.RunnerException; import java.io.IOException; @@ -29,52 +30,52 @@ public class PatternPerformanceComparison { } @Benchmark - public void matcherFromPreCompiledPatternResetMatches() { + public void matcherFromPreCompiledPatternResetMatches(Blackhole bh) { //With pre-compiled pattern and reusing the matcher // 1 Pattern object created // 1 Matcher objects created for (String value : values) { - matcherFromPreCompiledPattern.reset(value).matches(); + bh.consume(matcherFromPreCompiledPattern.reset(value).matches()); } } @Benchmark - public void preCompiledPatternMatcherMatches() { + public void preCompiledPatternMatcherMatches(Blackhole bh) { // With pre-compiled pattern // 1 Pattern object created // 5_000_000 Matcher objects created for (String value : values) { - preCompiledPattern.matcher(value).matches(); + bh.consume(preCompiledPattern.matcher(value).matches()); } } @Benchmark - public void patternCompileMatcherMatches() { + public void patternCompileMatcherMatches(Blackhole bh) { // Above approach "Pattern.matches(PATTERN, value)" makes this internally // 5_000_000 Pattern objects created // 5_000_000 Matcher objects created for (String value : values) { - Pattern.compile(PATTERN).matcher(value).matches(); + bh.consume(Pattern.compile(PATTERN).matcher(value).matches()); } } @Benchmark - public void patternMatches() { + public void patternMatches(Blackhole bh) { // Above approach "value.matches(PATTERN)" makes this internally // 5_000_000 Pattern objects created // 5_000_000 Matcher objects created for (String value : values) { - Pattern.matches(PATTERN, value); + bh.consume(Pattern.matches(PATTERN, value)); } } @Benchmark - public void stringMatchs() { + public void stringMatchs(Blackhole bh) { // 5_000_000 Pattern objects created // 5_000_000 Matcher objects created Instant start = Instant.now(); for (String value : values) { - value.matches(PATTERN); + bh.consume(value.matches(PATTERN)); } }