-
Notifications
You must be signed in to change notification settings - Fork 333
Expand file tree
/
Copy pathStringReplaceAllBenchmark.java
More file actions
109 lines (96 loc) · 3.49 KB
/
StringReplaceAllBenchmark.java
File metadata and controls
109 lines (96 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package datadog.trace.util;
import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.util.regex.Pattern;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
/**
* <p>For simple replacements, Strings.replaceAll is recommened.
*
* <p>
* For simple replacements, Strings.replaceAll or String.replace out performs the regex based
* methods String.replaceAll and regex.Matcher.replaceAll by 3x in terms of throughput.
*
* <p>String.replace and Strings.replaceAll also require less allocation.
*
* <p>Strings.replaceAll out performs String.replace by 1.2x in terms of throughput,
* but results may vary depending on the JVM version being used.
*
* <p>When pattern matching is needed, compiling the regex to Pattern slightly improves overhead,
* but dramatically reduces memory allocation to 1/4x of String.replaceAll. <code>
* MacBook M1 with 8 threads (Java 21)
*
* <code>
* MacBook M1 - 8 Threads - Java 21
*
* StringReplaceAllBenchmark.regex_replaceAll thrpt 6 15500559.098 ± 8640183.754 ops/s
* StringReplaceAllBenchmark.regex_replaceAll:gc.alloc.rate thrpt 6 4516.464 ± 2561.063 MB/sec
*
* StringReplaceAllBenchmark.string_replace thrpt 6 35429131.963 ± 3203548.932 ops/s
* StringReplaceAllBenchmark.string_replace:gc.alloc.rate thrpt 6 3185.108 ± 152.601 MB/sec
*
* StringReplaceAllBenchmark.string_replaceAll thrpt 6 14253964.929 ± 4060225.866 ops/s
* StringReplaceAllBenchmark.string_replaceAll:gc.alloc.rate thrpt 6 11114.939 ± 3129.891 MB/sec
*
* StringReplaceAllBenchmark.strings_replaceAll thrpt 6 43789250.524 ± 1910948.420 ops/s
* StringReplaceAllBenchmark.strings_replaceAll:gc.alloc.rate thrpt 6 3079.973 ± 134.617 MB/sec
* </code>
*/
@Fork(2)
@Warmup(iterations = 2)
@Measurement(iterations = 3)
@Threads(8)
@SuppressForbidden
public class StringReplaceAllBenchmark {
static final String[] INPUTS = {
"foo",
"baz",
"foobar",
"foobaz",
"foo=baz",
"bar=foo",
"foo=foo&bar=foo",
"lorem ipsum",
"datadog"
};
static int sharedInputIndex = 0;
static String nextInput() {
int localIndex = ++sharedInputIndex;
if (localIndex >= INPUTS.length) {
sharedInputIndex = localIndex = 0;
}
return INPUTS[localIndex];
}
@Benchmark
public String string_replaceAll() {
return _string_replaceAll(nextInput());
}
static String _string_replaceAll(String input) {
// Underneath, this does Pattern.compile("foo").matcher(str).replaceAll()
return input.replaceAll("foo", "*redacted*");
}
@Benchmark
public String string_replace() {
return _string_replace(nextInput());
}
static String _string_replace(String input) {
return input.replace("foo", "*redacted*");
}
static final Pattern REGEX_COMPILED = Pattern.compile("foo");
@Benchmark
public String regex_replaceAll() {
return _regex_replaceAll(nextInput());
}
static String _regex_replaceAll(String input) {
return REGEX_COMPILED.matcher(input).replaceAll("*redcated*");
}
@Benchmark
public String strings_replaceAll() {
return _strings_replaceAll(nextInput());
}
static String _strings_replaceAll(String input) {
return Strings.replaceAll(input, "foo", "*redacted*");
}
}