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
+ private 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" , "SZ_1_MB" , "SZ_2_MB" , "SZ_4_MB" , "SZ_8_MB" , "SZ_16_MB" , "SZ_32_MB" , "SZ_64_MB" , "SZ_128_MB" , "SZ_256_MB" })
76
+ private Size chunkSize ;
77
+
78
+ @ Param ({"CRC64" , "CRC32C" })
79
+ private Algorithm algorithm ;
80
+
81
+ @ Setup
82
+ public void setup () {
83
+ crc = getSdkChecksum (algorithm );
84
+ chunkData = new byte [chunkSize .getNumBytes ()];
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Approximates where we feed a fixed number of bytes (PAYLOAD_BYTES), using different chunk sizes.
90
+ */
91
+ @ Benchmark
92
+ public void chunked (ChunkedState s , Blackhole bh ) {
93
+ int chunkSize = s .chunkSize .getNumBytes ();
94
+
95
+ int nChunks = PAYLOAD_SIZE / chunkSize ;
96
+
97
+ s .crc .reset ();
98
+ for (int i = 0 ; i < nChunks ; ++i ) {
99
+ s .crc .update (s .chunkData );
100
+ }
101
+ bh .consume (s .crc .getChecksumBytes ());
102
+ }
103
+
104
+ /**
105
+ * This benchmark approximates use cases where crc64.update(byte[], offset, length) is called where length is
106
+ * smaller than the length of byte[]. For example, the application might have a *large* read buffer, but only fills
107
+ * a small portion of it and calls crc64.update() with only that portion.
108
+ */
109
+ @ State (Scope .Benchmark )
110
+ public static class FixedInputBufferSizeState {
111
+ @ Param ({"SZ_32_MB" , "SZ_64_MB" , "SZ_128_MB" , "SZ_256_MB" })
112
+ private Size fixedBufferSize ;
113
+
114
+ @ Param ({"SZ_512_KB" , "SZ_1_MB" , "SZ_2_MB" })
115
+ private Size chunkSize ;
116
+
117
+ @ Param ({"CRC64" , "CRC32C" })
118
+ private Algorithm algorithm ;
119
+
120
+ private byte [] buffer ;
121
+
122
+ private SdkChecksum crc ;
123
+
124
+ @ Setup
125
+ public void setup () {
126
+ buffer = new byte [fixedBufferSize .getNumBytes ()];
127
+ crc = getSdkChecksum (algorithm );
128
+ }
129
+ }
130
+
131
+ @ Benchmark
132
+ public void fixedBufferSize (FixedInputBufferSizeState s , Blackhole bh ) {
133
+ int chunkSize = s .chunkSize .getNumBytes ();
134
+
135
+ int nChunks = PAYLOAD_SIZE / chunkSize ;
136
+
137
+ s .crc .reset ();
138
+ for (int i = 0 ; i < nChunks ; ++i ) {
139
+ s .crc .update (s .buffer , 0 , chunkSize );
140
+ }
141
+ bh .consume (s .crc .getChecksumBytes ());
142
+ }
143
+
144
+ private static SdkChecksum getSdkChecksum (Algorithm algorithm ) {
145
+ switch (algorithm ) {
146
+ case CRC32C :
147
+ // Construct directly instead of using forAlgorithm because it
148
+ // will pick up the JVM provided one if it's available.
149
+ return new CrcCloneOnMarkChecksum (new CRC32C ());
150
+ case CRC64 :
151
+ return SdkChecksum .forAlgorithm (DefaultChecksumAlgorithm .CRC64NVME );
152
+ default :
153
+ throw new RuntimeException ("Unsupported algorithm: " + algorithm );
154
+ }
155
+ }
156
+ }
0 commit comments