1
+ /*
2
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
+ *
5
+ * This code is free software; you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License version 2 only, as
7
+ * published by the Free Software Foundation.
8
+ *
9
+ * This code is distributed in the hope that it will be useful, but WITHOUT
10
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
+ * version 2 for more details (a copy is included in the LICENSE file that
13
+ * accompanied this code).
14
+ *
15
+ * You should have received a copy of the GNU General Public License version
16
+ * 2 along with this work; if not, write to the Free Software Foundation,
17
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
+ *
19
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
+ * or visit www.oracle.com if you need additional information or have any
21
+ * questions.
22
+ */
23
+ package org .openjdk .bench .java .lang ;
24
+
25
+ import org .openjdk .jmh .annotations .Benchmark ;
26
+ import org .openjdk .jmh .annotations .BenchmarkMode ;
27
+ import org .openjdk .jmh .annotations .Fork ;
28
+ import org .openjdk .jmh .annotations .Measurement ;
29
+ import org .openjdk .jmh .annotations .Mode ;
30
+ import org .openjdk .jmh .annotations .OutputTimeUnit ;
31
+ import org .openjdk .jmh .annotations .Scope ;
32
+ import org .openjdk .jmh .annotations .State ;
33
+ import org .openjdk .jmh .annotations .Warmup ;
34
+
35
+ import java .lang .invoke .MethodHandle ;
36
+ import java .lang .invoke .MethodHandles ;
37
+ import java .util .Map ;
38
+ import java .util .concurrent .TimeUnit ;
39
+
40
+ /**
41
+ * Performance test of String.hashCode() function with constant folding.
42
+ * The tests are using a Map that holds a MethodHandle to better expose
43
+ * any potential lack of constant folding.
44
+ */
45
+ @ BenchmarkMode (Mode .AverageTime )
46
+ @ OutputTimeUnit (TimeUnit .NANOSECONDS )
47
+ @ State (Scope .Thread )
48
+ @ Warmup (iterations = 5 , time = 1 )
49
+ @ Measurement (iterations = 5 , time = 1 )
50
+ @ Fork (value = 3 )
51
+ public class StringHashCodeStatic {
52
+
53
+ private static final String HASHCODE = "abcdefghijkl" ;
54
+ private static final String HASHCODE_0 = new String (new char []{72 , 90 , 100 , 89 , 105 , 2 , 72 , 90 , 100 , 89 , 105 , 2 });
55
+ private static final String EMPTY = new String ();
56
+
57
+ private static final Map <String , MethodHandle > MAP = Map .of (
58
+ HASHCODE , mh (HASHCODE .hashCode ()),
59
+ HASHCODE_0 , mh (HASHCODE_0 .hashCode ()),
60
+ EMPTY , mh (EMPTY .hashCode ()));
61
+
62
+ /**
63
+ * Benchmark testing String.hashCode() with a regular 12 char string with
64
+ * the result possibly cached in String
65
+ */
66
+ @ Benchmark
67
+ public int nonZero () throws Throwable {
68
+ return (int )MAP .get (HASHCODE ).invokeExact ();
69
+ }
70
+
71
+ /**
72
+ * Benchmark testing String.hashCode() with a 12 char string with the
73
+ * hashcode = 0.
74
+ */
75
+ @ Benchmark
76
+ public int zero () throws Throwable {
77
+ return (int )MAP .get (HASHCODE_0 ).invokeExact ();
78
+ }
79
+
80
+ /**
81
+ * Benchmark testing String.hashCode() with the empty string. an
82
+ * empty String has hashCode = 0.
83
+ */
84
+ @ Benchmark
85
+ public int empty () throws Throwable {
86
+ return (int )MAP .get (EMPTY ).invokeExact ();
87
+ }
88
+
89
+ static MethodHandle mh (int value ) {
90
+ return MethodHandles .constant (int .class , value );
91
+ }
92
+
93
+ }
0 commit comments