/Users/deen/code/yugabyte-db/src/yb/util/crc-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | |
33 | | #include "yb/util/crc.h" |
34 | | #include "yb/util/status.h" |
35 | | #include "yb/util/stopwatch.h" |
36 | | #include "yb/util/test_util.h" |
37 | | |
38 | | namespace yb { |
39 | | namespace crc { |
40 | | |
41 | | using strings::Substitute; |
42 | | |
43 | | class CrcTest : public YBTest { |
44 | | protected: |
45 | | |
46 | | // Returns pointer to data which must be deleted by caller. |
47 | 1 | static void GenerateBenchmarkData(const uint8_t** bufptr, size_t* buflen) { |
48 | 1 | const uint32_t kNumNumbers = 1000000; |
49 | 1 | const uint32_t kBytesPerNumber = sizeof(uint32_t); |
50 | 1 | const uint32_t kLength = kNumNumbers * kBytesPerNumber; |
51 | 1 | auto buf = new uint8_t[kLength]; |
52 | 1.00M | for (uint32_t i = 0; i < kNumNumbers; i++) { |
53 | 1.00M | memcpy(buf + (i * kBytesPerNumber), &i, kBytesPerNumber); |
54 | 1.00M | } |
55 | 1 | *bufptr = buf; |
56 | 1 | *buflen = kLength; |
57 | 1 | } |
58 | | |
59 | | }; |
60 | | |
61 | | // Basic functionality test. |
62 | 1 | TEST_F(CrcTest, TestCRC32C) { |
63 | 1 | const string test_data("abcdefgh"); |
64 | 1 | Crc* crc32c = GetCrc32cInstance(); |
65 | 1 | uint64_t data_crc = 0; |
66 | 1 | crc32c->Compute(test_data.data(), test_data.length(), &data_crc); |
67 | 1 | char buf[kFastToBufferSize]; |
68 | 1 | const char* output = FastHex64ToBuffer(data_crc, buf); |
69 | 1 | LOG(INFO) << "CRC32C of " << test_data << " is: 0x" << output << " (full 64 bits)"; |
70 | 1 | output = FastHex32ToBuffer(static_cast<uint32_t>(data_crc), buf); |
71 | 1 | LOG(INFO) << "CRC32C of " << test_data << " is: 0x" << output << " (truncated 32 bits)"; |
72 | 1 | ASSERT_EQ(0xa9421b7, data_crc); // Known value from crcutil usage test program. |
73 | 1 | } |
74 | | |
75 | | // Simple benchmark of CRC32C throughput. |
76 | | // We should expect about 8 bytes per cycle in throughput on a single core. |
77 | 1 | TEST_F(CrcTest, BenchmarkCRC32C) { |
78 | 1 | std::unique_ptr<const uint8_t[]> data; |
79 | 1 | const uint8_t* buf; |
80 | 1 | size_t buflen; |
81 | 1 | GenerateBenchmarkData(&buf, &buflen); |
82 | 1 | data.reset(buf); |
83 | 1 | Crc* crc32c = GetCrc32cInstance(); |
84 | 1 | int kNumRuns = 1000; |
85 | 1 | if (AllowSlowTests()) { |
86 | 0 | kNumRuns = 40000; |
87 | 0 | } |
88 | 1 | const uint64_t kNumBytes = kNumRuns * buflen; |
89 | 1 | Stopwatch sw; |
90 | 1 | sw.start(); |
91 | 1.00k | for (int i = 0; i < kNumRuns; i++) { |
92 | 1.00k | uint64_t cksum; |
93 | 1.00k | crc32c->Compute(buf, buflen, &cksum); |
94 | 1.00k | } |
95 | 1 | sw.stop(); |
96 | 1 | CpuTimes elapsed = sw.elapsed(); |
97 | 1 | LOG(INFO) << Substitute("$0 runs of CRC32C on $1 bytes of data (total: $2 bytes)" |
98 | 1 | " in $3 seconds; $4 bytes per millisecond, $5 bytes per nanosecond!", |
99 | 1 | kNumRuns, buflen, kNumBytes, elapsed.wall_seconds(), |
100 | 1 | (kNumBytes / elapsed.wall_millis()), |
101 | 1 | (kNumBytes / elapsed.wall)); |
102 | 1 | } |
103 | | |
104 | | } // namespace crc |
105 | | } // namespace yb |