1
+ /*
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
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
+ * A copy of the License is located at
7
+ *
8
+ * http://aws.amazon.com/apache2.0
9
+ *
10
+ * or in the "license" file accompanying this file. This file is distributed
11
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
+ * express or implied. See the License for the specific language governing
13
+ * permissions and limitations under the License.
14
+ */
15
+
16
+ package software .amazon .awssdk .benchmark .checksum ;
17
+
18
+ import org .openjdk .jmh .annotations .Benchmark ;
19
+ import org .openjdk .jmh .annotations .Param ;
20
+ import org .openjdk .jmh .annotations .Scope ;
21
+ import org .openjdk .jmh .annotations .Setup ;
22
+ import org .openjdk .jmh .annotations .State ;
23
+ import org .openjdk .jmh .infra .Blackhole ;
24
+ import software .amazon .awssdk .checksums .DefaultChecksumAlgorithm ;
25
+ import software .amazon .awssdk .checksums .SdkChecksum ;
26
+ import software .amazon .awssdk .checksums .internal .CrcCloneOnMarkChecksum ;
27
+ import software .amazon .awssdk .crt .checksums .CRC32C ;
28
+
29
+ /**
30
+ * Benchmarks for testing CRT implementations of checksums.
31
+ * <p>
32
+ * There are pitfalls with passing buffers to and from native code since it could lead to lots of copying.
33
+ */
34
+ public class CrtChecksumBenchmark {
35
+ private static final int KB = 1024 ;
36
+ private static final int MB = 1024 * KB ;
37
+ private static final int PAYLOAD_SIZE = 512 * MB ;
38
+
39
+ public enum Algorithm {
40
+ CRC32C ,
41
+ CRC64 ,
42
+ ;
43
+ }
44
+
45
+ public enum Size {
46
+ SZ_512_KB (512 * KB ),
47
+ SZ_1_MB (MB ),
48
+ SZ_2_MB (2 * MB ),
49
+ SZ_4_MB (4 * MB ),
50
+ SZ_8_MB (8 * MB ),
51
+ SZ_16_MB (16 * MB ),
52
+ SZ_32_MB (32 * MB ),
53
+ SZ_64_MB (64 * MB ),
54
+ SZ_128_MB (128 * MB ),
55
+ SZ_256_MB (256 * MB );
56
+
57
+ private int numBytes ;
58
+
59
+ Size (int bytes ) {
60
+
61
+ this .numBytes = bytes ;
62
+ }
63
+
64
+ public int getNumBytes () {
65
+ return numBytes ;
66
+ }
67
+ }
68
+
69
+ @ State (Scope .Benchmark )
70
+ public static class ChunkedState {
71
+ private SdkChecksum crc ;
72
+
73
+ private byte [] chunkData ;
74
+
75
+ @ Param ({"SZ_512_KB" ,
76
+ "SZ_1_MB" ,
77
+ "SZ_2_MB" ,
78
+ "SZ_4_MB" ,
79
+ "SZ_8_MB" ,
80
+ "SZ_16_MB" ,
81
+ "SZ_32_MB" ,
82
+ "SZ_64_MB" ,
83
+ "SZ_128_MB" ,
84
+ "SZ_256_MB" })
85
+ private Size chunkSize ;
86
+
87
+ @ Param ({"CRC64" , "CRC32C" })
88
+ private Algorithm algorithm ;
89
+
90
+ @ Setup
91
+ public void setup () {
92
+ crc = getSdkChecksum (algorithm );
93
+ chunkData = new byte [chunkSize .getNumBytes ()];
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Approximates where we feed a fixed number of bytes (PAYLOAD_BYTES), using different chunk sizes.
99
+ */
100
+ @ Benchmark
101
+ public void chunked (ChunkedState s , Blackhole bh ) {
102
+ int chunkSize = s .chunkSize .getNumBytes ();
103
+
104
+ int nChunks = PAYLOAD_SIZE / chunkSize ;
105
+
106
+ s .crc .reset ();
107
+ for (int i = 0 ; i < nChunks ; ++i ) {
108
+ s .crc .update (s .chunkData );
109
+ }
110
+ bh .consume (s .crc .getChecksumBytes ());
111
+ }
112
+
113
+ /**
114
+ * This benchmark approximates use cases where crc64.update(byte[], offset, length) is called where length is
115
+ * smaller than the length of byte[]. For example, the application might have a *large* read buffer, but only fills
116
+ * a small portion of it and calls crc64.update() with only that portion.
117
+ */
118
+ @ State (Scope .Benchmark )
119
+ public static class FixedInputBufferSizeState {
120
+ @ Param ({"SZ_32_MB" , "SZ_64_MB" , "SZ_128_MB" , "SZ_256_MB" })
121
+ private Size fixedBufferSize ;
122
+
123
+ @ Param ({"SZ_512_KB" , "SZ_1_MB" , "SZ_2_MB" })
124
+ private Size chunkSize ;
125
+
126
+ @ Param ({"CRC64" , "CRC32C" })
127
+ private Algorithm algorithm ;
128
+
129
+ private byte [] buffer ;
130
+
131
+ private SdkChecksum crc ;
132
+
133
+ @ Setup
134
+ public void setup () {
135
+ buffer = new byte [fixedBufferSize .getNumBytes ()];
136
+ crc = getSdkChecksum (algorithm );
137
+ }
138
+ }
139
+
140
+ @ Benchmark
141
+ public void fixedBufferSize (FixedInputBufferSizeState s , Blackhole bh ) {
142
+ int chunkSize = s .chunkSize .getNumBytes ();
143
+
144
+ int nChunks = PAYLOAD_SIZE / chunkSize ;
145
+
146
+ s .crc .reset ();
147
+ for (int i = 0 ; i < nChunks ; ++i ) {
148
+ s .crc .update (s .buffer , 0 , chunkSize );
149
+ }
150
+ bh .consume (s .crc .getChecksumBytes ());
151
+ }
152
+
153
+ private static SdkChecksum getSdkChecksum (Algorithm algorithm ) {
154
+ switch (algorithm ) {
155
+ case CRC32C :
156
+ // Construct directly instead of using forAlgorithm because it
157
+ // will pick up the JVM provided one if it's available.
158
+ return new CrcCloneOnMarkChecksum (new CRC32C ());
159
+ case CRC64 :
160
+ return SdkChecksum .forAlgorithm (DefaultChecksumAlgorithm .CRC64NVME );
161
+ default :
162
+ throw new RuntimeException ("Unsupported algorithm: " + algorithm );
163
+ }
164
+ }
165
+ }
0 commit comments