1 /*
2  * Copyright (C) 2022 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.libcore.regression;
18 
19 import android.perftests.utils.BenchmarkState;
20 import android.perftests.utils.PerfStatusReporter;
21 import android.test.suitebuilder.annotation.LargeTest;
22 
23 import junitparams.JUnitParamsRunner;
24 import junitparams.Parameters;
25 
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 
30 import java.nio.ByteBuffer;
31 import java.security.MessageDigest;
32 import java.util.Arrays;
33 import java.util.Collection;
34 
35 @RunWith(JUnitParamsRunner.class)
36 @LargeTest
37 public class MessageDigestPerfTest {
38     @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
39 
getData()40     public static Collection<Object[]> getData() {
41         return Arrays.asList(
42                 new Object[][] {
43                     {Algorithm.MD5},
44                     {Algorithm.SHA1},
45                     {Algorithm.SHA256},
46                     {Algorithm.SHA384},
47                     {Algorithm.SHA512}
48                 });
49     }
50 
51     public String mProvider = "AndroidOpenSSL";
52 
53     private static final int DATA_SIZE = 8192;
54     private static final byte[] DATA = new byte[DATA_SIZE];
55 
56     static {
57         for (int i = 0; i < DATA_SIZE; i++) {
58             DATA[i] = (byte) i;
59         }
60     }
61 
62     private static final int LARGE_DATA_SIZE = 256 * 1024;
63     private static final byte[] LARGE_DATA = new byte[LARGE_DATA_SIZE];
64 
65     static {
66         for (int i = 0; i < LARGE_DATA_SIZE; i++) {
67             LARGE_DATA[i] = (byte) i;
68         }
69     }
70 
71     private static final ByteBuffer SMALL_BUFFER = ByteBuffer.wrap(DATA);
72     private static final ByteBuffer SMALL_DIRECT_BUFFER = ByteBuffer.allocateDirect(DATA_SIZE);
73 
74     static {
75         SMALL_DIRECT_BUFFER.put(DATA);
SMALL_DIRECT_BUFFER.flip()76         SMALL_DIRECT_BUFFER.flip();
77     }
78 
79     private static final ByteBuffer LARGE_BUFFER = ByteBuffer.wrap(LARGE_DATA);
80     private static final ByteBuffer LARGE_DIRECT_BUFFER =
81             ByteBuffer.allocateDirect(LARGE_DATA_SIZE);
82 
83     static {
84         LARGE_DIRECT_BUFFER.put(LARGE_DATA);
LARGE_DIRECT_BUFFER.flip()85         LARGE_DIRECT_BUFFER.flip();
86     }
87 
88     public enum Algorithm {
89         MD5,
90         SHA1,
91         SHA256,
92         SHA384,
93         SHA512
94     };
95 
96     @Test
97     @Parameters(method = "getData")
time(Algorithm algorithm)98     public void time(Algorithm algorithm) throws Exception {
99         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
100         while (state.keepRunning()) {
101             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
102             digest.update(DATA, 0, DATA_SIZE);
103             digest.digest();
104         }
105     }
106 
107     @Test
108     @Parameters(method = "getData")
timeLargeArray(Algorithm algorithm)109     public void timeLargeArray(Algorithm algorithm) throws Exception {
110         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
111         while (state.keepRunning()) {
112             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
113             digest.update(LARGE_DATA, 0, LARGE_DATA_SIZE);
114             digest.digest();
115         }
116     }
117 
118     @Test
119     @Parameters(method = "getData")
timeSmallChunkOfLargeArray(Algorithm algorithm)120     public void timeSmallChunkOfLargeArray(Algorithm algorithm) throws Exception {
121         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
122         while (state.keepRunning()) {
123             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
124             digest.update(LARGE_DATA, LARGE_DATA_SIZE / 2, DATA_SIZE);
125             digest.digest();
126         }
127     }
128 
129     @Test
130     @Parameters(method = "getData")
timeSmallByteBuffer(Algorithm algorithm)131     public void timeSmallByteBuffer(Algorithm algorithm) throws Exception {
132         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
133         while (state.keepRunning()) {
134             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
135             SMALL_BUFFER.position(0);
136             SMALL_BUFFER.limit(SMALL_BUFFER.capacity());
137             digest.update(SMALL_BUFFER);
138             digest.digest();
139         }
140     }
141 
142     @Test
143     @Parameters(method = "getData")
timeSmallDirectByteBuffer(Algorithm algorithm)144     public void timeSmallDirectByteBuffer(Algorithm algorithm) throws Exception {
145         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
146         while (state.keepRunning()) {
147             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
148             SMALL_DIRECT_BUFFER.position(0);
149             SMALL_DIRECT_BUFFER.limit(SMALL_DIRECT_BUFFER.capacity());
150             digest.update(SMALL_DIRECT_BUFFER);
151             digest.digest();
152         }
153     }
154 
155     @Test
156     @Parameters(method = "getData")
timeLargeByteBuffer(Algorithm algorithm)157     public void timeLargeByteBuffer(Algorithm algorithm) throws Exception {
158         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
159         while (state.keepRunning()) {
160             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
161             LARGE_BUFFER.position(0);
162             LARGE_BUFFER.limit(LARGE_BUFFER.capacity());
163             digest.update(LARGE_BUFFER);
164             digest.digest();
165         }
166     }
167 
168     @Test
169     @Parameters(method = "getData")
timeLargeDirectByteBuffer(Algorithm algorithm)170     public void timeLargeDirectByteBuffer(Algorithm algorithm) throws Exception {
171         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
172         while (state.keepRunning()) {
173             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
174             LARGE_DIRECT_BUFFER.position(0);
175             LARGE_DIRECT_BUFFER.limit(LARGE_DIRECT_BUFFER.capacity());
176             digest.update(LARGE_DIRECT_BUFFER);
177             digest.digest();
178         }
179     }
180 
181     @Test
182     @Parameters(method = "getData")
timeSmallChunkOfLargeByteBuffer(Algorithm algorithm)183     public void timeSmallChunkOfLargeByteBuffer(Algorithm algorithm) throws Exception {
184         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
185         while (state.keepRunning()) {
186             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
187             LARGE_BUFFER.position(LARGE_BUFFER.capacity() / 2);
188             LARGE_BUFFER.limit(LARGE_BUFFER.position() + DATA_SIZE);
189             digest.update(LARGE_BUFFER);
190             digest.digest();
191         }
192     }
193 
194     @Test
195     @Parameters(method = "getData")
timeSmallChunkOfLargeDirectByteBuffer(Algorithm algorithm)196     public void timeSmallChunkOfLargeDirectByteBuffer(Algorithm algorithm) throws Exception {
197         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
198         while (state.keepRunning()) {
199             MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), mProvider);
200             LARGE_DIRECT_BUFFER.position(LARGE_DIRECT_BUFFER.capacity() / 2);
201             LARGE_DIRECT_BUFFER.limit(LARGE_DIRECT_BUFFER.position() + DATA_SIZE);
202             digest.update(LARGE_DIRECT_BUFFER);
203             digest.digest();
204         }
205     }
206 }
207