mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
zlib: add crc32c
Add zlib.crc32c(data[, value]), which computes the CRC-32C checksum (Castagnoli polynomial, RFC 3720 section 12.1). CRC-32C has better error detection properties than the CRC-32 of zlib.crc32() and is the checksum required by many current protocols, formats and services, among them: - iSCSI header and data digests (RFC 7143) - SCTP packet checksums (RFC 9260) - iWARP MPA framing (RFC 5044) - NVMe/TCP header and data digests - ext4, Btrfs and XFS metadata checksums - the Snappy framing format - Apache Kafka record batches - LevelDB and RocksDB block checksums - TensorFlow TFRecord files - Google Cloud Storage and Amazon S3 object checksums Implementing any of these in JavaScript currently needs a userland CRC-32C, which is far slower than native code. The function mirrors zlib.crc32(): it accepts a string (encoded as UTF-8) or an ArrayBufferView, takes an optional 32-bit unsigned starting value so a checksum can be continued across chunks, and has a V8 fast API path. The checksum is computed by absl::ExtendCrc32c() from the bundled Abseil, which is already built and linked into node, so this adds no new dependency and no new checksum implementation. absl_crc32c is added to the libraries linked with --shared-abseil. Abseil selects its hardware-accelerated CRC-32C path (SSE4.2 and PCLMULQDQ on x64, the CRC32 and PMULL extensions on arm64) at compile time, so with node's default compiler flags the portable table-driven implementation is used. It runs at about the same speed as zlib.crc32() (about 6.5 GB/s on a recent x64 machine), while the hardware path reaches about 38 GB/s. Builds whose target CPU baseline already includes those instructions get the hardware path without changes. Enabling it for generic builds is left out on purpose: on x64, Abseil uses the accelerated code for unrecognized CPUs without a runtime feature check, so compiling it in unconditionally would fault on CPUs without SSE4.2. Signed-off-by: Philipp Dunkel <pip@pipobscure.com> PR-URL: https://github.com/nodejs/node/pull/66828 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
1 parent
754325cd2f
commit
df2ea49e00
8 files changed
+258
-1
No files matched your search
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common.js');
|
||||
const { crc32c } = require('zlib');
|
||||
|
||||
// Benchmark crc32c on Buffer and String inputs across sizes.
|
||||
// Iteration count is scaled inversely with input length to keep runtime sane.
|
||||
// Example:
|
||||
// node benchmark/zlib/crc32c.js type=buffer len=4096 n=4000000
|
||||
// ./out/Release/node benchmark/zlib/crc32c.js --test
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
type: ['buffer', 'string'],
|
||||
len: [32, 256, 4096, 65536],
|
||||
n: [4e6],
|
||||
});
|
||||
|
||||
function makeBuffer(size) {
|
||||
const buf = Buffer.allocUnsafe(size);
|
||||
for (let i = 0; i < size; i++) buf[i] = (i * 1103515245 + 12345) & 0xff;
|
||||
return buf;
|
||||
}
|
||||
|
||||
function makeAsciiString(size) {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
||||
let out = '';
|
||||
for (let i = 0, j = 0; i < size; i++, j = (j + 7) % chars.length) out += chars[j];
|
||||
return out;
|
||||
}
|
||||
|
||||
function main({ type, len, n }) {
|
||||
// Scale iterations so that total processed bytes roughly constant around n*4096 bytes.
|
||||
const scale = 4096 / len;
|
||||
const iters = Math.max(1, Math.floor(n * scale));
|
||||
|
||||
const data = type === 'buffer' ? makeBuffer(len) : makeAsciiString(len);
|
||||
|
||||
let acc = 0;
|
||||
for (let i = 0; i < Math.min(iters, 10000); i++) acc ^= crc32c(data, 0);
|
||||
|
||||
bench.start();
|
||||
let sum = 0;
|
||||
for (let i = 0; i < iters; i++) sum ^= crc32c(data, 0);
|
||||
bench.end(iters);
|
||||
|
||||
if (sum === acc - 1) process.stderr.write('');
|
||||
}
|
||||
Reference in new issue
Block a user