├── src └── test │ └── java │ └── string │ ├── EnumValues.md │ ├── EnumValueOf.md │ ├── EqualsChar.md │ ├── EmptyStringEquals.md │ ├── EnumValueOf0.md │ ├── RemoveChar.md │ ├── ReplaceAllPrecompiled.md │ ├── StartsWith.md │ ├── EnumValues.java │ ├── EnumValueOf0.java │ ├── EqualsIgnoreCase.java │ ├── WidgetProperty.java │ ├── StartsWith.java │ ├── EqualChar.java │ ├── EmptyStringEquals.java │ ├── ReplaceAllPrecompiled.java │ ├── ReplaceAll.java │ ├── EnumValueOf.java │ ├── EqualsIgnoreCase.md │ ├── ReplaceCustom.md │ ├── RemoveChar.java │ ├── ReplaceCustom.java │ └── ReplaceAll.md ├── README.md └── pom.xml /src/test/java/string/EnumValues.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | Benchmark Mode Cnt Score Error Units 4 | EnumValues.enumValuesMethod avgt 10 21.576 ± 0.225 ns/op 5 | EnumValues.enumValuesVariable avgt 10 16.811 ± 0.095 ns/op -------------------------------------------------------------------------------- /src/test/java/string/EnumValueOf.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | //with random input 5 | Benchmark Mode Cnt Score Error Units 6 | EnumValueOf.enumMap avgt 50 7.800 ± 0.097 ns/op 7 | EnumValueOf.enumSwitch avgt 50 19.734 ± 0.350 ns/op 8 | EnumValueOf.enumValueOf avgt 50 9.292 ± 0.826 ns/op 9 | ``` -------------------------------------------------------------------------------- /src/test/java/string/EqualsChar.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Benchmark (url) Mode Cnt Score Error Units 3 | EqualChar.equalsOptimized / avgt 10 3.806 ± 0.075 ns/op 4 | EqualChar.equalsPost / avgt 10 5.706 ± 0.089 ns/op 5 | EqualChar.equalsPre / avgt 10 5.960 ± 0.062 ns/op 6 | 7 | EqualChar.equalsOptimized /my/server/url avgt 10 3.250 ± 0.204 ns/op 8 | EqualChar.equalsPost /my/server/url avgt 10 3.464 ± 0.116 ns/op 9 | EqualChar.equalsPre /my/server/url avgt 10 3.786 ± 0.027 ns/op 10 | ``` 11 | -------------------------------------------------------------------------------- /src/test/java/string/EmptyStringEquals.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Benchmark (strParams) Mode Cnt Score Error Units 3 | EmptyStringEquals.equalsPost avgt 10 4.348 ± 0.056 ns/op 4 | EmptyStringEquals.nonNullAndIsEmpty avgt 10 3.029 ± 0.033 ns/op 5 | EmptyStringEquals.preEquals avgt 10 4.360 ± 0.060 ns/op 6 | 7 | EmptyStringEquals.equalsPost nonEmptyString avgt 10 3.552 ± 0.024 ns/op 8 | EmptyStringEquals.nonNullAndIsEmpty nonEmptyString avgt 10 3.031 ± 0.082 ns/op 9 | EmptyStringEquals.preEquals nonEmptyString avgt 10 3.813 ± 0.115 ns/op 10 | ``` -------------------------------------------------------------------------------- /src/test/java/string/EnumValueOf0.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | //with predicted input 5 | Benchmark (strParams) Mode Cnt Score Error Units 6 | EnumValueOf.enumMap LABEL avgt 10 11.749 ± 0.761 ns/op 7 | EnumValueOf.enumMap ON_LABEL avgt 10 11.778 ± 0.306 ns/op 8 | EnumValueOf.enumMap MAX avgt 10 10.517 ± 0.056 ns/op 9 | EnumValueOf.enumSwitch LABEL avgt 80 7.149 ± 0.030 ns/op 10 | EnumValueOf.enumSwitch ON_LABEL avgt 80 7.758 ± 0.077 ns/op 11 | EnumValueOf.enumSwitch MAX avgt 80 6.948 ± 0.083 ns/op 12 | EnumValueOf.enumValueOf LABEL avgt 80 15.659 ± 0.450 ns/op 13 | EnumValueOf.enumValueOf ON_LABEL avgt 80 14.734 ± 0.542 ns/op 14 | EnumValueOf.enumValueOf MAX avgt 80 15.153 ± 0.578 ns/op 15 | ``` -------------------------------------------------------------------------------- /src/test/java/string/RemoveChar.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | Benchmark (value) Mode Cnt Score Error Units 5 | RemoveChar.remove avgt 10 4.405 ± 1.646 ns/op 6 | RemoveChar.remove somePathNoDoT avgt 10 7.820 ± 0.296 ns/op 7 | RemoveChar.remove some.Path.With.Dot avgt 10 92.185 ± 3.752 ns/op 8 | 9 | RemoveChar.removeApache avgt 10 3.708 ± 0.070 ns/op 10 | RemoveChar.removeApache somePathNoDoT avgt 10 10.018 ± 0.103 ns/op 11 | RemoveChar.removeApache some.Path.With.Dot avgt 10 37.822 ± 0.486 ns/op 12 | 13 | RemoveChar.removeSpring avgt 10 3.609 ± 0.033 ns/op 14 | RemoveChar.removeSpring somePathNoDoT avgt 10 7.996 ± 0.308 ns/op 15 | RemoveChar.removeSpring some.Path.With.Dot avgt 10 87.148 ± 1.391 ns/op 16 | ``` -------------------------------------------------------------------------------- /src/test/java/string/ReplaceAllPrecompiled.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | Benchmark (value) Mode Cnt Score Error Units 5 | ReplaceAllPrecompiled.replace avgt 10 3.843 ± 0.100 ns/op 6 | ReplaceAllPrecompiled.replace somePathNoDoT avgt 10 8.693 ± 0.693 ns/op 7 | ReplaceAllPrecompiled.replace some.Path.With.Dot avgt 10 127.022 ± 8.842 ns/op 8 | 9 | ReplaceAllPrecompiled.replaceAll avgt 10 156.550 ± 10.741 ns/op 10 | ReplaceAllPrecompiled.replaceAll somePathNoDoT avgt 10 159.619 ± 4.654 ns/op 11 | ReplaceAllPrecompiled.replaceAll some.Path.With.Dot avgt 10 391.912 ± 11.445 ns/op 12 | 13 | ReplaceAllPrecompiled.replaceAllPrecompiled avgt 10 52.466 ± 0.791 ns/op 14 | ReplaceAllPrecompiled.replaceAllPrecompiled somePathNoDoT avgt 10 64.337 ± 0.854 ns/op 15 | ReplaceAllPrecompiled.replaceAllPrecompiled some.Path.With.Dot avgt 10 274.867 ± 3.535 ns/op 16 | ``` -------------------------------------------------------------------------------- /src/test/java/string/StartsWith.md: -------------------------------------------------------------------------------- 1 | ``` 2 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 3 | 4 | Benchmark (url) Mode Cnt Score Error Units 5 | StartsWith.regionMatches http://facebook.com/loginMe avgt 10 5.025 ± 0.032 ns/op 6 | StartsWith.substringEqualsIgnoreCase http://facebook.com/loginMe avgt 10 19.390 ± 0.922 ns/op 7 | StartsWith.toLowerCaseStartsWith http://facebook.com/loginMe avgt 10 40.815 ± 0.550 ns/op 8 | 9 | StartsWith.regionMatches Http://facebook.com/loginMe avgt 10 14.469 ± 0.164 ns/op 10 | StartsWith.substringEqualsIgnoreCase Http://facebook.com/loginMe avgt 10 21.758 ± 0.304 ns/op 11 | StartsWith.toLowerCaseStartsWith Http://facebook.com/loginMe avgt 10 46.457 ± 0.643 ns/op 12 | 13 | StartsWith.regionMatches not url at all avgt 10 10.076 ± 0.092 ns/op 14 | StartsWith.substringEqualsIgnoreCase not url at all avgt 10 18.300 ± 0.131 ns/op 15 | StartsWith.toLowerCaseStartsWith not url at all avgt 10 17.197 ± 0.143 ns/op 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /src/test/java/string/EnumValues.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Scope; 10 | import org.openjdk.jmh.annotations.State; 11 | import org.openjdk.jmh.annotations.Warmup; 12 | import org.openjdk.jmh.infra.Blackhole; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class EnumValues { 23 | 24 | @Benchmark 25 | public void enumValuesMethod(Blackhole bh) { 26 | for (WidgetProperty property : WidgetProperty.values()) { 27 | bh.consume(property); 28 | } 29 | } 30 | 31 | @Benchmark 32 | public void enumValuesVariable(Blackhole bh) { 33 | for (WidgetProperty property : WidgetProperty.values) { 34 | bh.consume(property); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/string/EnumValueOf0.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class EnumValueOf0 { 23 | 24 | @Param({"LABEL", "ON_LABEL", "MAX"}) 25 | String strParams; 26 | 27 | @Benchmark 28 | public WidgetProperty enumValueOf() { 29 | return WidgetProperty.valueOf(strParams); 30 | } 31 | 32 | @Benchmark 33 | public WidgetProperty enumSwitch() { 34 | return WidgetProperty.valueOfSwitch(strParams); 35 | } 36 | 37 | @Benchmark 38 | public WidgetProperty enumMap() { 39 | return WidgetProperty.valueOfMap(strParams); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/string/EqualsIgnoreCase.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class EqualsIgnoreCase { 23 | 24 | @Param({"HELLO WORLD", "Hello World", "hello world", "otherParam"}) 25 | String strParams; 26 | 27 | @Benchmark 28 | public boolean equalsAndToLowerCase() { 29 | return "hello world".equals(strParams.toLowerCase()); 30 | } 31 | 32 | @Benchmark 33 | public boolean equalsIgnoreCase() { 34 | return "hello world".equalsIgnoreCase(strParams); 35 | } 36 | 37 | @Benchmark 38 | public boolean equals() { 39 | return "hello world".equals(strParams); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/string/WidgetProperty.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public enum WidgetProperty { 7 | 8 | LABEL, 9 | COLOR, 10 | ON_LABEL, 11 | OFF_LABEL, 12 | MIN, 13 | MAX; 14 | 15 | public static final WidgetProperty[] values = values(); 16 | 17 | private final static Map cache; 18 | static { 19 | cache = new HashMap<>(); 20 | for (WidgetProperty widgetProperty : values()) { 21 | cache.put(widgetProperty.name(), widgetProperty); 22 | } 23 | } 24 | 25 | public static WidgetProperty valueOfMap(String value) { 26 | return cache.get(value); 27 | } 28 | 29 | public static WidgetProperty valueOfSwitch(String value) { 30 | switch (value) { 31 | case "LABEL" : 32 | return WidgetProperty.LABEL; 33 | case "COLOR" : 34 | return WidgetProperty.COLOR; 35 | case "ON_LABEL" : 36 | return WidgetProperty.ON_LABEL; 37 | case "OFF_LABEL" : 38 | return WidgetProperty.OFF_LABEL; 39 | case "MIN" : 40 | return WidgetProperty.MIN; 41 | case "MAX" : 42 | return WidgetProperty.MAX; 43 | } 44 | return null; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/string/StartsWith.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class StartsWith { 23 | 24 | @Param({"http://facebook.com/loginMe", "Http://facebook.com/loginMe", "not url at all"}) 25 | String url; 26 | 27 | @Benchmark 28 | public boolean regionMatches() { 29 | return url.regionMatches(true, 0, "http", 0, "http".length()); 30 | } 31 | 32 | @Benchmark 33 | public boolean toLowerCaseStartsWith() { 34 | return url.toLowerCase().startsWith("http"); 35 | } 36 | 37 | @Benchmark 38 | public boolean substringEqualsIgnoreCase() { 39 | return url.substring(0, 4).equalsIgnoreCase("http"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/string/EqualChar.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class EqualChar { 23 | 24 | @Param({"/", "/my/server/url"}) 25 | private String url; 26 | 27 | @Benchmark 28 | public boolean equalsPost() { 29 | return url != null && url.equals("/"); 30 | } 31 | 32 | @Benchmark 33 | public boolean equalsPre() { 34 | return "/".equals(url); 35 | } 36 | 37 | @Benchmark 38 | public boolean equalsOptimized() { 39 | return equalsOneChar(url); 40 | } 41 | 42 | private static boolean equalsOneChar(String url) { 43 | return url != null && url.length() == 1 && url.charAt(0) == '/'; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/test/java/string/EmptyStringEquals.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * The Blynk Project. 18 | * Created by Dmitro Dumanskiy. 19 | * Created on 13.12.16. 20 | */ 21 | @BenchmarkMode(Mode.AverageTime) 22 | @Fork(1) 23 | @State(Scope.Thread) 24 | @Warmup(iterations = 5, time = 1) 25 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 26 | @Measurement(iterations = 10, time = 1) 27 | public class EmptyStringEquals { 28 | 29 | @Param({"", "nonEmptyString"}) 30 | private String strParams; 31 | 32 | @Benchmark 33 | public boolean nonNullAndIsEmpty() { 34 | return strParams != null && strParams.isEmpty(); 35 | } 36 | 37 | @Benchmark 38 | public boolean equalsPost() { 39 | return strParams != null && strParams.equals(""); 40 | } 41 | 42 | @Benchmark 43 | public boolean preEquals() { 44 | return "".equals(strParams); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/string/ReplaceAllPrecompiled.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | import java.util.regex.Pattern; 16 | 17 | @BenchmarkMode(Mode.AverageTime) 18 | @Fork(1) 19 | @State(Scope.Thread) 20 | @Warmup(iterations = 5, time = 1) 21 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 22 | @Measurement(iterations = 10, time = 1) 23 | public class ReplaceAllPrecompiled { 24 | 25 | @Param({"", "somePathNoDoT", "some.Path.With.Dot"}) 26 | String value; 27 | 28 | private static final Pattern DOT_PATTERN = Pattern.compile("\\."); 29 | @Benchmark 30 | public String replaceAllPrecompiled() { 31 | return DOT_PATTERN.matcher(value).replaceAll("%2E"); 32 | } 33 | 34 | @Benchmark 35 | public String replaceAll() { 36 | return value.replaceAll("\\.", "%2E"); 37 | } 38 | 39 | @Benchmark 40 | public String replace() { 41 | return value.replace(".", "%2E"); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/string/ReplaceAll.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Param; 10 | import org.openjdk.jmh.annotations.Scope; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | @BenchmarkMode(Mode.AverageTime) 17 | @Fork(1) 18 | @State(Scope.Thread) 19 | @Warmup(iterations = 5, time = 1) 20 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 21 | @Measurement(iterations = 10, time = 1) 22 | public class ReplaceAll { 23 | 24 | @Param({"", "somePathNoDoT", "some.Path.With.Dot"}) 25 | String value; 26 | 27 | @Benchmark 28 | public String replaceAllWithContains() { 29 | return value.contains(".") ? value.replaceAll("\\.", "%2E") : value; 30 | } 31 | 32 | @Benchmark 33 | public String replaceAll() { 34 | return value.replaceAll("\\.", "%2E"); 35 | } 36 | 37 | @Benchmark 38 | public String replace() { 39 | return value.replace(".", "%2E"); 40 | } 41 | 42 | @Benchmark 43 | public String replaceWithContains() { 44 | return value.contains(".") ? value.replace(".", "%2E") : value; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/string/EnumValueOf.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.BenchmarkMode; 5 | import org.openjdk.jmh.annotations.Fork; 6 | import org.openjdk.jmh.annotations.Measurement; 7 | import org.openjdk.jmh.annotations.Mode; 8 | import org.openjdk.jmh.annotations.OutputTimeUnit; 9 | import org.openjdk.jmh.annotations.Scope; 10 | import org.openjdk.jmh.annotations.Setup; 11 | import org.openjdk.jmh.annotations.State; 12 | import org.openjdk.jmh.annotations.Warmup; 13 | 14 | import java.util.Random; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @BenchmarkMode(Mode.AverageTime) 18 | @Fork(1) 19 | @State(Scope.Thread) 20 | @Warmup(iterations = 5, time = 1) 21 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 22 | @Measurement(iterations = 10, time = 1) 23 | public class EnumValueOf { 24 | 25 | String[] names; 26 | int index; 27 | 28 | @Setup 29 | public void init() { 30 | WidgetProperty[] values = WidgetProperty.values(); 31 | names = new Random(0).ints(4096, 0, values.length) 32 | .mapToObj(i -> values[i].name()) 33 | .toArray(String[]::new); 34 | index = 0; 35 | } 36 | 37 | private String nextName() { 38 | return names[index++ & (names.length - 1)]; 39 | } 40 | 41 | @Benchmark 42 | public WidgetProperty enumValueOf() { 43 | return WidgetProperty.valueOf(nextName()); 44 | } 45 | 46 | @Benchmark 47 | public WidgetProperty enumSwitch() { 48 | return WidgetProperty.valueOfSwitch(nextName()); 49 | } 50 | 51 | @Benchmark 52 | public WidgetProperty enumMap() { 53 | return WidgetProperty.valueOfMap(nextName()); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/string/EqualsIgnoreCase.md: -------------------------------------------------------------------------------- 1 | JDK 1.8.0_265, OpenJDK 64-Bit Server VM, 25.265-b01 2 | 3 | ``` 4 | Benchmark (strParams) Mode Cnt Score Error Units 5 | EqualsIgnoreCase.equalsAndToLowerCase HELLO WORLD avgt 10 67.110 ± 0.891 ns/op 6 | EqualsIgnoreCase.equalsIgnoreCase HELLO WORLD avgt 10 46.485 ± 0.671 ns/op 7 | 8 | EqualsIgnoreCase.equalsAndToLowerCase Hello World avgt 10 57.092 ± 1.146 ns/op 9 | EqualsIgnoreCase.equalsIgnoreCase Hello World avgt 10 29.846 ± 0.292 ns/op 10 | 11 | EqualsIgnoreCase.equalsAndToLowerCase hello world avgt 10 23.289 ± 0.188 ns/op 12 | EqualsIgnoreCase.equalsIgnoreCase hello world avgt 10 18.668 ± 0.291 ns/op 13 | 14 | EqualsIgnoreCase.equalsAndToLowerCase otherParam avgt 10 49.020 ± 1.436 ns/op 15 | EqualsIgnoreCase.equalsIgnoreCase otherParam avgt 10 2.885 ± 0.056 ns/op 16 | 17 | EqualsIgnoreCase.equals hello world avgt 10 6.947 ± 0.134 ns/op 18 | ``` 19 | 20 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 21 | 22 | ``` 23 | EqualsIgnoreCase.equalsAndToLowerCase HELLO WORLD avgt 10 37.890 ± 0.547 ns/op 24 | EqualsIgnoreCase.equalsIgnoreCase HELLO WORLD avgt 10 42.518 ± 0.451 ns/op 25 | 26 | EqualsIgnoreCase.equalsAndToLowerCase Hello World avgt 10 33.204 ± 0.525 ns/op 27 | EqualsIgnoreCase.equalsIgnoreCase Hello World avgt 10 27.891 ± 0.288 ns/op 28 | 29 | EqualsIgnoreCase.equalsAndToLowerCase hello world avgt 10 18.047 ± 0.233 ns/op 30 | EqualsIgnoreCase.equalsIgnoreCase hello world avgt 10 19.639 ± 0.184 ns/op 31 | 32 | EqualsIgnoreCase.equalsAndToLowerCase otherParam avgt 10 30.211 ± 0.460 ns/op 33 | EqualsIgnoreCase.equalsIgnoreCase otherParam avgt 10 3.489 ± 0.026 ns/op 34 | 35 | EqualsIgnoreCase.equals hello world avgt 10 7.287 ± 0.182 ns/op 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /src/test/java/string/ReplaceCustom.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | Benchmark (value) Mode Cnt Score Error Units 5 | ReplaceCustom.replace avgt 10 4.497 ± 1.085 ns/op 6 | ReplaceCustom.replace somePathNoDoT avgt 10 7.944 ± 0.289 ns/op 7 | ReplaceCustom.replace some.Path.With.Dot avgt 10 106.270 ± 5.095 ns/op 8 | 9 | ReplaceCustom.replaceApache avgt 10 3.784 ± 0.065 ns/op 10 | ReplaceCustom.replaceApache somePathNoDoT avgt 10 8.168 ± 0.052 ns/op 11 | ReplaceCustom.replaceApache some.Path.With.Dot avgt 10 121.248 ± 1.935 ns/op 12 | 13 | ReplaceCustom.replaceChar avgt 10 3.689 ± 0.040 ns/op 14 | ReplaceCustom.replaceChar somePathNoDoT avgt 10 8.787 ± 0.119 ns/op 15 | ReplaceCustom.replaceChar some.Path.With.Dot avgt 10 26.824 ± 0.391 ns/op 16 | 17 | ReplaceCustom.springCustomReplace avgt 10 3.628 ± 0.058 ns/op 18 | ReplaceCustom.springCustomReplace somePathNoDoT avgt 10 7.991 ± 0.268 ns/op 19 | ReplaceCustom.springCustomReplace some.Path.With.Dot avgt 10 108.191 ± 6.138 ns/op 20 | ``` 21 | 22 | JDK 1.8.0_265, OpenJDK 64-Bit Server VM, 25.265-b01 23 | 24 | ``` 25 | Benchmark (value) Mode Cnt Score Error Units 26 | ReplaceCustom.replace avgt 10 116.851 ± 3.107 ns/op 27 | ReplaceCustom.replace somePathNoDoT avgt 10 124.806 ± 3.289 ns/op 28 | ReplaceCustom.replace some.Path.With.Dot avgt 10 376.608 ± 4.225 ns/op 29 | ReplaceCustom.replaceChar avgt 10 3.445 ± 0.093 ns/op 30 | ReplaceCustom.replaceChar somePathNoDoT avgt 10 11.484 ± 0.074 ns/op 31 | ReplaceCustom.replaceChar some.Path.With.Dot avgt 10 31.191 ± 0.641 ns/op 32 | ReplaceCustom.springCustomReplace avgt 10 2.963 ± 0.054 ns/op 33 | ReplaceCustom.springCustomReplace somePathNoDoT avgt 10 8.943 ± 0.102 ns/op 34 | ReplaceCustom.springCustomReplace some.Path.With.Dot avgt 10 109.930 ± 1.716 ns/op 35 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Micro optimizations in Java 2 | Benchmarks for series of articles "Micro optimizations in Java." 3 | 4 | **NOTE**: You need JMH Plugin in order to launch the benchmarks from the IDE. 5 | 6 | ### Content 7 | 8 | [Micro optimizations in Java. String.equals()](https://medium.com/javarevisited/micro-optimizations-in-java-string-equals-22be19fd8416?source=friends_link&sk=61649c9c9fccfb59c0515fcb9f7447ef) benchmarks: 9 | - ["".equals(s) vs s.isEmpty()](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/EmptyStringEquals.java) 10 | - [s.equals("/") vs oneCharEquals('/')](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/EqualChar.java) 11 | 12 | [Micro optimizations in Java. String.equalsIgnoreCase()](https://medium.com/@ddumanskiy/micro-optimizations-in-java-string-equalsignorecase-ea25dfb03f95?source=friends_link&sk=28001856b9085e3c927de376298323fd) benchmarks: 13 | - [s.equalsIgnoreCase() vs s.equals(s.toLowerCase())](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/EqualsIgnoreCase.java#L28) 14 | - [s.toLowerCase().startsWith() vs s.regionMatches()](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/StartsWith.java#L22) 15 | 16 | [Micro optimizations in Java. Good, nice and slow Enum](https://medium.com/javarevisited/micro-optimizations-in-java-good-nice-and-slow-enum-261e6f77bd2e?source=friends_link&sk=2efd362f40b01c300b09f425d57a9bb0) benchmarks: 17 | - [Enum.valueOf vs switch](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/EnumValueOf.java#L22) 18 | - [Enum.values() vs cache variable](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/EnumValues.java#L22) 19 | 20 | [Micro optimizations in Java. String.replaceAll](https://medium.com/@ddumanskiy/micro-optimizations-in-java-string-replaceall-c6d0edf2ef6?source=friends_link&sk=54fe79994e5a8eea966c905e338eb744) benchmarks: 21 | - [String.replaceAll vs String.replace](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/ReplaceAll.java#L22) 22 | - [String.replace(String, String) vs String.replace(char, char)](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/ReplaceCustom.java#L23) 23 | - [String.replace(String, String) vs StringUtils.remove(String, char)](https://github.com/doom369/java-micro-optimizations/blob/master/src/test/java/string/RemoveChar.java) 24 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | java-micro-optimizations 8 | core 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 1.25 13 | 3.8.1 14 | 3.11 15 | 33.2.1-jre 16 | 1.18.12 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | ${maven-compiler-plugin.version} 25 | 26 | 11 27 | 11 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.projectlombok 37 | lombok 38 | ${lombok.version} 39 | provided 40 | 41 | 42 | org.apache.commons 43 | commons-lang3 44 | ${commons-lang3.version} 45 | 46 | 47 | com.google.guava 48 | guava 49 | ${guava.version} 50 | 51 | 52 | org.openjdk.jmh 53 | jmh-core 54 | ${jmh-core.version} 55 | 56 | 57 | org.openjdk.jmh 58 | jmh-generator-annprocess 59 | ${jmh-core.version} 60 | test 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/test/java/string/RemoveChar.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.openjdk.jmh.annotations.Benchmark; 5 | import org.openjdk.jmh.annotations.BenchmarkMode; 6 | import org.openjdk.jmh.annotations.Fork; 7 | import org.openjdk.jmh.annotations.Measurement; 8 | import org.openjdk.jmh.annotations.Mode; 9 | import org.openjdk.jmh.annotations.OutputTimeUnit; 10 | import org.openjdk.jmh.annotations.Param; 11 | import org.openjdk.jmh.annotations.Scope; 12 | import org.openjdk.jmh.annotations.State; 13 | import org.openjdk.jmh.annotations.Warmup; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @BenchmarkMode(Mode.AverageTime) 18 | @Fork(1) 19 | @State(Scope.Thread) 20 | @Warmup(iterations = 5, time = 1) 21 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 22 | @Measurement(iterations = 10, time = 1) 23 | public class RemoveChar { 24 | 25 | @Param({"", "somePathNoDoT", "some.Path.With.Dot"}) 26 | String value; 27 | 28 | @Benchmark 29 | public String remove() { 30 | return value.replace(".", ""); 31 | } 32 | 33 | @Benchmark 34 | public String removeApache() { 35 | return StringUtils.remove(value, '.'); 36 | } 37 | 38 | @Benchmark 39 | public String removeSpring() { 40 | return springDelete(value, "."); 41 | } 42 | 43 | public static String springDelete(String inString, String pattern) { 44 | return replace(inString, pattern, ""); 45 | } 46 | 47 | public static boolean hasLength(String str) { 48 | return (str != null && !str.isEmpty()); 49 | } 50 | 51 | public static String replace(String inString, String oldPattern, String newPattern) { 52 | if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) { 53 | return inString; 54 | } 55 | int index = inString.indexOf(oldPattern); 56 | if (index == -1) { 57 | // no occurrence -> can return input as-is 58 | return inString; 59 | } 60 | 61 | int capacity = inString.length(); 62 | if (newPattern.length() > oldPattern.length()) { 63 | capacity += 16; 64 | } 65 | StringBuilder sb = new StringBuilder(capacity); 66 | 67 | int pos = 0; // our position in the old string 68 | int patLen = oldPattern.length(); 69 | while (index >= 0) { 70 | sb.append(inString, pos, index); 71 | sb.append(newPattern); 72 | pos = index + patLen; 73 | index = inString.indexOf(oldPattern, pos); 74 | } 75 | 76 | // append any characters to the right of a match 77 | sb.append(inString, pos, inString.length()); 78 | return sb.toString(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/string/ReplaceCustom.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.openjdk.jmh.annotations.Benchmark; 5 | import org.openjdk.jmh.annotations.BenchmarkMode; 6 | import org.openjdk.jmh.annotations.Fork; 7 | import org.openjdk.jmh.annotations.Measurement; 8 | import org.openjdk.jmh.annotations.Mode; 9 | import org.openjdk.jmh.annotations.OutputTimeUnit; 10 | import org.openjdk.jmh.annotations.Param; 11 | import org.openjdk.jmh.annotations.Scope; 12 | import org.openjdk.jmh.annotations.State; 13 | import org.openjdk.jmh.annotations.Warmup; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @BenchmarkMode(Mode.AverageTime) 18 | @Fork(1) 19 | @State(Scope.Thread) 20 | @Warmup(iterations = 5, time = 1) 21 | @OutputTimeUnit(TimeUnit.NANOSECONDS) 22 | @Measurement(iterations = 10, time = 1) 23 | public class ReplaceCustom { 24 | 25 | @Param({"", "somePathNoDoT", "some.Path.With.Dot"}) 26 | String value; 27 | 28 | @Benchmark 29 | public String replace() { 30 | return value.replace(".", "/"); 31 | } 32 | 33 | @Benchmark 34 | public String replaceSpring() { 35 | return springReplace(value, ".", "/"); 36 | } 37 | 38 | @Benchmark 39 | public String replaceChar() { 40 | return value.replace('.', '/'); 41 | } 42 | 43 | @Benchmark 44 | public String replaceApache() { 45 | return StringUtils.replace(value, ".", "/"); 46 | } 47 | 48 | @Benchmark 49 | public String replaceApacheChar() { 50 | return StringUtils.replaceChars(value, '.', '/'); 51 | } 52 | 53 | public static boolean hasLength(String str) { 54 | return (str != null && !str.isEmpty()); 55 | } 56 | 57 | public static String springReplace(String inString, String oldPattern, String newPattern) { 58 | if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) { 59 | return inString; 60 | } 61 | int index = inString.indexOf(oldPattern); 62 | if (index == -1) { 63 | // no occurrence -> can return input as-is 64 | return inString; 65 | } 66 | 67 | int capacity = inString.length(); 68 | if (newPattern.length() > oldPattern.length()) { 69 | capacity += 16; 70 | } 71 | StringBuilder sb = new StringBuilder(capacity); 72 | 73 | int pos = 0; // our position in the old string 74 | int patLen = oldPattern.length(); 75 | while (index >= 0) { 76 | sb.append(inString, pos, index); 77 | sb.append(newPattern); 78 | pos = index + patLen; 79 | index = inString.indexOf(oldPattern, pos); 80 | } 81 | 82 | // append any characters to the right of a match 83 | sb.append(inString, pos, inString.length()); 84 | return sb.toString(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/string/ReplaceAll.md: -------------------------------------------------------------------------------- 1 | JDK 11.0.8, OpenJDK 64-Bit Server VM, 11.0.8+10 2 | 3 | ``` 4 | Benchmark (value) Mode Cnt Score Error Units 5 | ReplaceAll.replace avgt 10 3.836 ± 0.060 ns/op 6 | ReplaceAll.replaceAll avgt 10 147.857 ± 1.550 ns/op 7 | ReplaceAll.replaceAllWithContains avgt 10 3.777 ± 0.069 ns/op 8 | ReplaceAll.replaceWithContains avgt 10 3.778 ± 0.075 ns/op 9 | 10 | ReplaceAll.replace somePathNoDoT avgt 10 7.647 ± 0.646 ns/op 11 | ReplaceAll.replaceAll somePathNoDoT avgt 10 156.495 ± 1.751 ns/op 12 | ReplaceAll.replaceAllWithContains somePathNoDoT avgt 10 7.640 ± 0.291 ns/op 13 | ReplaceAll.replaceWithContains somePathNoDoT avgt 10 7.545 ± 0.298 ns/op 14 | 15 | ReplaceAll.replace some.Path.With.Dot avgt 10 123.856 ± 1.686 ns/op 16 | ReplaceAll.replaceAll some.Path.With.Dot avgt 10 389.632 ± 18.308 ns/op 17 | ReplaceAll.replaceAllWithContains some.Path.With.Dot avgt 10 378.527 ± 6.434 ns/op 18 | ReplaceAll.replaceWithContains some.Path.With.Dot avgt 10 126.918 ± 0.940 ns/op 19 | ``` 20 | 21 | JDK 1.8.0_265, OpenJDK 64-Bit Server VM, 25.265-b01 22 | 23 | ``` 24 | Benchmark (value) Mode Cnt Score Error Units 25 | ReplaceAll.replace avgt 10 119.510 ± 2.406 ns/op 26 | ReplaceAll.replace somePathNoDoT avgt 10 124.683 ± 2.547 ns/op 27 | ReplaceAll.replace some.Path.With.Dot avgt 10 391.124 ± 8.022 ns/op 28 | ReplaceAll.replaceAll avgt 10 145.469 ± 3.852 ns/op 29 | ReplaceAll.replaceAll somePathNoDoT avgt 10 147.657 ± 2.917 ns/op 30 | ReplaceAll.replaceAll some.Path.With.Dot avgt 10 359.246 ± 6.925 ns/op 31 | ReplaceAll.replaceAllWithContains avgt 10 3.455 ± 0.111 ns/op 32 | ReplaceAll.replaceAllWithContains somePathNoDoT avgt 10 9.191 ± 0.184 ns/op 33 | ReplaceAll.replaceAllWithContains some.Path.With.Dot avgt 10 363.143 ± 5.813 ns/op 34 | ReplaceAll.replaceWithContains avgt 10 3.479 ± 0.154 ns/op 35 | ReplaceAll.replaceWithContains somePathNoDoT avgt 10 9.138 ± 0.251 ns/op 36 | ReplaceAll.replaceWithContains some.Path.With.Dot avgt 10 398.229 ± 7.236 ns/op 37 | ReplaceAllPrecompiled.replaceAllWithPrecompiled avgt 10 47.852 ± 1.036 ns/op 38 | ReplaceAllPrecompiled.replaceAllWithPrecompiled somePathNoDoT avgt 10 55.192 ± 1.135 ns/op 39 | ReplaceAllPrecompiled.replaceAllWithPrecompiled some.Path.With.Dot avgt 10 264.585 ± 4.044 ns/op 40 | ``` --------------------------------------------------------------------------------