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