• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Code Intelligence GmbH
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.code_intelligence.jazzer.runtime;
16 
17 import java.io.UnsupportedEncodingException;
18 import java.util.Arrays;
19 import java.util.Random;
20 import java.util.concurrent.ThreadLocalRandom;
21 import java.util.concurrent.TimeUnit;
22 import org.openjdk.jmh.annotations.Benchmark;
23 import org.openjdk.jmh.annotations.BenchmarkMode;
24 import org.openjdk.jmh.annotations.Fork;
25 import org.openjdk.jmh.annotations.Measurement;
26 import org.openjdk.jmh.annotations.Mode;
27 import org.openjdk.jmh.annotations.OutputTimeUnit;
28 import org.openjdk.jmh.annotations.Param;
29 import org.openjdk.jmh.annotations.Scope;
30 import org.openjdk.jmh.annotations.Setup;
31 import org.openjdk.jmh.annotations.State;
32 import org.openjdk.jmh.annotations.Warmup;
33 
34 @Warmup(iterations = 5, time = 1)
35 @Measurement(iterations = 5, time = 1)
36 @Fork(value = 3)
37 @OutputTimeUnit(TimeUnit.NANOSECONDS)
38 @BenchmarkMode(Mode.AverageTime)
39 public class FuzzerCallbacksBenchmark {
40   @State(Scope.Benchmark)
41   public static class TraceCmpIntState {
42     int arg1 = 0xCAFECAFE;
43     int arg2 = 0xFEEDFEED;
44     int pc = 0x12345678;
45   }
46 
47   @Benchmark
traceCmpInt(TraceCmpIntState state)48   public void traceCmpInt(TraceCmpIntState state) {
49     FuzzerCallbacks.traceCmpInt(state.arg1, state.arg2, state.pc);
50   }
51 
52   @Benchmark
traceCmpIntWithPc(TraceCmpIntState state)53   public void traceCmpIntWithPc(TraceCmpIntState state) {
54     FuzzerCallbacksWithPc.traceCmpInt(state.arg1, state.arg2, state.pc);
55   }
56 
57   @Benchmark
58   @Fork(jvmArgsAppend = {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:+CriticalJNINatives"})
traceCmpIntOptimizedCritical(TraceCmpIntState state)59   public void traceCmpIntOptimizedCritical(TraceCmpIntState state) {
60     FuzzerCallbacksOptimizedCritical.traceCmpInt(state.arg1, state.arg2, state.pc);
61   }
62 
63   // Uncomment to benchmark Project Panama-backed implementation (requires JDK 16+).
64   //  @Benchmark
65   //  @Fork(jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED", "--add-modules",
66   //            "jdk.incubator.foreign"})
67   //  public void
68   //  traceCmpIntPanama(TraceCmpIntState state) throws Throwable {
69   //    FuzzerCallbacksPanama.traceCmpInt(state.arg1, state.arg2, state.pc);
70   //  }
71 
72   @State(Scope.Benchmark)
73   public static class TraceSwitchState {
74     @Param({"5", "10"}) int numCases;
75 
76     long val;
77     long[] cases;
78     int pc = 0x12345678;
79 
80     @Setup
setup()81     public void setup() {
82       cases = new long[2 + numCases];
83       Random random = ThreadLocalRandom.current();
84       Arrays.setAll(cases, i -> {
85         switch (i) {
86           case 0:
87             return numCases;
88           case 1:
89             return 32;
90           default:
91             return random.nextInt();
92         }
93       });
94       Arrays.sort(cases, 2, cases.length);
95       val = random.nextInt();
96     }
97   }
98 
99   @Benchmark
traceSwitch(TraceSwitchState state)100   public void traceSwitch(TraceSwitchState state) {
101     FuzzerCallbacks.traceSwitch(state.val, state.cases, state.pc);
102   }
103 
104   @Benchmark
traceSwitchWithPc(TraceSwitchState state)105   public void traceSwitchWithPc(TraceSwitchState state) {
106     FuzzerCallbacksWithPc.traceSwitch(state.val, state.cases, state.pc);
107   }
108 
109   @Benchmark
110   @Fork(jvmArgsAppend = {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:+CriticalJNINatives"})
traceSwitchOptimizedCritical(TraceSwitchState state)111   public void traceSwitchOptimizedCritical(TraceSwitchState state) {
112     FuzzerCallbacksOptimizedCritical.traceSwitch(state.val, state.cases, state.pc);
113   }
114 
115   @Benchmark
traceSwitchOptimizedNonCritical(TraceSwitchState state)116   public void traceSwitchOptimizedNonCritical(TraceSwitchState state) {
117     FuzzerCallbacksOptimizedNonCritical.traceSwitch(state.val, state.cases, state.pc);
118   }
119 
120   // Uncomment to benchmark Project Panama-backed implementation (requires JDK 16+).
121   //  @Benchmark
122   //  @Fork(jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED", "--add-modules",
123   //            "jdk.incubator.foreign"})
124   //  public void
125   //  traceCmpSwitchPanama(TraceSwitchState state) throws Throwable {
126   //    FuzzerCallbacksPanama.traceCmpSwitch(state.val, state.cases, state.pc);
127   //  }
128 
129   @State(Scope.Benchmark)
130   public static class TraceMemcmpState {
131     @Param({"10", "100", "1000"}) int length;
132 
133     byte[] array1;
134     byte[] array2;
135     int pc = 0x12345678;
136 
137     @Setup
setup()138     public void setup() {
139       array1 = new byte[length];
140       array2 = new byte[length];
141 
142       Random random = ThreadLocalRandom.current();
143       random.nextBytes(array1);
144       random.nextBytes(array2);
145       // Make the arrays agree unil the midpoint to benchmark the "average"
146       // case of an interesting memcmp.
147       System.arraycopy(array1, 0, array2, 0, length / 2);
148     }
149   }
150 
151   @Benchmark
traceMemcmp(TraceMemcmpState state)152   public void traceMemcmp(TraceMemcmpState state) {
153     FuzzerCallbacks.traceMemcmp(state.array1, state.array2, 1, state.pc);
154   }
155 
156   @Benchmark
157   @Fork(jvmArgsAppend = {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:+CriticalJNINatives"})
traceMemcmpOptimizedCritical(TraceMemcmpState state)158   public void traceMemcmpOptimizedCritical(TraceMemcmpState state) {
159     FuzzerCallbacksOptimizedCritical.traceMemcmp(state.array1, state.array2, 1, state.pc);
160   }
161 
162   @Benchmark
traceMemcmpOptimizedNonCritical(TraceMemcmpState state)163   public void traceMemcmpOptimizedNonCritical(TraceMemcmpState state) {
164     FuzzerCallbacksOptimizedNonCritical.traceMemcmp(state.array1, state.array2, 1, state.pc);
165   }
166 
167   @State(Scope.Benchmark)
168   public static class TraceStrstrState {
169     @Param({"10", "100", "1000"}) int length;
170     @Param({"true", "false"}) boolean asciiOnly;
171 
172     String haystack;
173     String needle;
174     int pc = 0x12345678;
175 
176     @Setup
setup()177     public void setup() {
178       haystack = randomString(length, asciiOnly);
179       needle = randomString(length, asciiOnly);
180     }
181 
randomString(int length, boolean asciiOnly)182     private String randomString(int length, boolean asciiOnly) {
183       String asciiString =
184           ThreadLocalRandom.current()
185               .ints('a', 'z' + 1)
186               .limit(length)
187               .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
188               .toString();
189       if (asciiOnly) {
190         return asciiString;
191       }
192       // Force String to be non-Latin-1 to preclude compact string optimization.
193       return "\uFFFD" + asciiString.substring(1);
194     }
195   }
196 
197   @Benchmark
traceStrstr(TraceStrstrState state)198   public void traceStrstr(TraceStrstrState state) {
199     FuzzerCallbacks.traceStrstr(state.haystack, state.needle, state.pc);
200   }
201 
202   @Benchmark
traceStrstrOptimizedNonCritical(TraceStrstrState state)203   public void traceStrstrOptimizedNonCritical(TraceStrstrState state) {
204     FuzzerCallbacksOptimizedNonCritical.traceStrstr(state.haystack, state.needle, state.pc);
205   }
206 
207   @Benchmark
208   @Fork(jvmArgsAppend = {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:+CriticalJNINatives"})
traceStrstrOptimizedJavaCritical(TraceStrstrState state)209   public void traceStrstrOptimizedJavaCritical(TraceStrstrState state)
210       throws UnsupportedEncodingException {
211     FuzzerCallbacksOptimizedCritical.traceStrstrJava(state.haystack, state.needle, state.pc);
212   }
213 
214   @Benchmark
traceStrstrOptimizedJavaNonCritical(TraceStrstrState state)215   public void traceStrstrOptimizedJavaNonCritical(TraceStrstrState state)
216       throws UnsupportedEncodingException {
217     FuzzerCallbacksOptimizedNonCritical.traceStrstrJava(state.haystack, state.needle, state.pc);
218   }
219 }
220