1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.perftests;
18 
19 import android.perftests.utils.BenchmarkState;
20 import android.perftests.utils.PerfStatusReporter;
21 
22 import androidx.test.filters.LargeTest;
23 import androidx.test.runner.AndroidJUnit4;
24 
25 import dalvik.annotation.optimization.CriticalNative;
26 import dalvik.annotation.optimization.FastNative;
27 
28 import org.junit.Assert;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 
33 import java.util.concurrent.TimeUnit;
34 
35 @RunWith(AndroidJUnit4.class)
36 @LargeTest
37 public class SystemPerfTest {
38 
39     static {
40         System.loadLibrary("perftestscore_jni");
41     }
42 
43     @Rule
44     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
45 
46     @Test
testNanoTimePerf()47     public void testNanoTimePerf() {
48         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
49         while (state.keepRunning()) {
50             System.nanoTime();
51         }
52     }
53 
54     @Test
testBenchmarkOverhead()55     public void testBenchmarkOverhead() {
56         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
57         while (state.keepRunning()) {}
58     }
59 
spinBlock(long durationNs)60     void spinBlock(long durationNs) {
61         long start = System.nanoTime();
62         while (System.nanoTime() - start < durationNs) {}
63     }
64 
65     @Test
testBenchmarkPauseResumeOverhead()66     public void testBenchmarkPauseResumeOverhead() {
67         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
68         while (state.keepRunning()) {
69             state.pauseTiming();
70             spinBlock(TimeUnit.MICROSECONDS.toNanos(5));
71             state.resumeTiming();
72         }
73     }
74 
75     @Test
testJniArrayNoop()76     public void testJniArrayNoop() {
77         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
78         final int[] data = new int[450];
79         while (state.keepRunning()) {
80             jintarrayArgumentNoop(data, data.length);
81         }
82     }
83 
84     @Test
testJniArrayGetLength()85     public void testJniArrayGetLength() {
86         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
87         final int[] data = new int[450];
88         while (state.keepRunning()) {
89             jintarrayGetLength(data);
90         }
91     }
92 
93     @Test
testJniArrayCriticalAccess()94     public void testJniArrayCriticalAccess() {
95         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
96         final int[] data = new int[450];
97         while (state.keepRunning()) {
98             jintarrayCriticalAccess(data, 50);
99         }
100     }
101 
102     @Test
testJniArrayBasicAccess()103     public void testJniArrayBasicAccess() {
104         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
105         final int[] data = new int[450];
106         while (state.keepRunning()) {
107             jintarrayBasicAccess(data, 50);
108         }
109     }
110 
111     /** this result should be compared with {@link #testJniCriticalNativeAccess()}. */
112     @Test
testJniFastNativeAccess()113     public void testJniFastNativeAccess() {
114         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
115         while (state.keepRunning()) {
116             jintFastNativeAccess(50);
117         }
118     }
119 
120     /**
121      * This result should be compared with {@link #testJniFastNativeAccess()}.
122      *
123      * <p>In theory, the result should be better than {@link #testJniFastNativeAccess()}.
124      */
125     @Test
testJniCriticalNativeAccess()126     public void testJniCriticalNativeAccess() {
127         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
128         while (state.keepRunning()) {
129             jintCriticalNativeAccess(50);
130         }
131     }
132 
133     /** The result should be compared with {@link #testJniCriticalNativeCheckNullPointer()}. */
134     @Test
testJniFastNativeCheckNullPointer()135     public void testJniFastNativeCheckNullPointer() {
136         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
137         while (state.keepRunning()) {
138             final int echoNumber = jintFastNativeCheckNullPointer(50);
139         }
140     }
141 
142     /**
143      * The result should be compared with {@link #testJniFastNativeCheckNullPointer()}.
144      *
145      * <p>CriticalNative can't reference JavaEnv in native layer. It means it should check the null
146      * pointer in java layer. It's a comparison between native layer and java layer.
147      */
148     @Test
testJniCriticalNativeCheckNullPointer()149     public void testJniCriticalNativeCheckNullPointer() {
150         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
151         while (state.keepRunning()) {
152             final int echoNumber = jintCriticalNativeCheckNullPointer(50);
153             if (echoNumber == -1) {
154                 Assert.fail("It shouldn't be here");
155             }
156         }
157     }
158 
159     /**
160      * The result should be compared with {@link #testJniCriticalNativeThrowNullPointerException()}.
161      */
162     @Test
testJniFastNativeThrowNullPointerException()163     public void testJniFastNativeThrowNullPointerException() {
164         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
165         while (state.keepRunning()) {
166             try {
167                 jintFastNativeCheckNullPointer(0);
168             } catch (NullPointerException e) {
169                 continue;
170             }
171             Assert.fail("It shouldn't be here");
172         }
173     }
174 
175     /**
176      * The result should be compared with {@link #testJniFastNativeThrowNullPointerException()}.
177      *
178      * <p>CriticalNative can't reference JavaEnv in native layer. It means it should check the null
179      * pointer in java layer. It's a comparison between native layer and java layer.
180      */
181     @Test
testJniCriticalNativeThrowNullPointerException()182     public void testJniCriticalNativeThrowNullPointerException() {
183         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
184         while (state.keepRunning()) {
185             try {
186                 final int echoNumber = jintCriticalNativeCheckNullPointer(0);
187                 if (echoNumber == -1) {
188                     throw new NullPointerException();
189                 }
190             } catch (NullPointerException e) {
191                 continue;
192             }
193             Assert.fail("It shouldn't be here");
194         }
195     }
196 
197     // ----------- @FastNative ------------------
198     @FastNative
jintarrayArgumentNoop(int[] array, int length)199     private static native void jintarrayArgumentNoop(int[] array, int length);
200     @FastNative
jintarrayGetLength(int[] array)201     private static native int jintarrayGetLength(int[] array);
202     @FastNative
jintarrayCriticalAccess(int[] array, int index)203     private static native int jintarrayCriticalAccess(int[] array, int index);
204     @FastNative
jintarrayBasicAccess(int[] array, int index)205     private static native int jintarrayBasicAccess(int[] array, int index);
206 
207     @FastNative
jintFastNativeAccess(int echoNumber)208     private static native int jintFastNativeAccess(int echoNumber);
209 
210     @FastNative
jintFastNativeCheckNullPointer(int echoNumber)211     private static native int jintFastNativeCheckNullPointer(int echoNumber);
212 
213     // ----------- @CriticalNative ------------------
214     @CriticalNative
jintCriticalNativeAccess(int echoNumber)215     private static native int jintCriticalNativeAccess(int echoNumber);
216 
217     @CriticalNative
jintCriticalNativeCheckNullPointer(int echoNumber)218     private static native int jintCriticalNativeCheckNullPointer(int echoNumber);
219 }
220