Skip to content

Commit 62816f2

Browse files
author
LongYinan
committed
refactor(crc32): use faster implement
1 parent 74dcaf9 commit 62816f2

File tree

14 files changed

+361
-55
lines changed

14 files changed

+361
-55
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# node-rs
2+
3+
When `NodeJS` meet `Rust` = 🚀

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
],
5656
"*.@(yml|yaml)": [
5757
"prettier --parser yaml --write"
58+
],
59+
"*.md": [
60+
"prettier --parser markdown --write"
5861
]
5962
},
6063
"prettier": {

packages/crc32/COPYING

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright 2011, The Snappy-Rust Authors. All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are
5+
met:
6+
7+
* Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
* Redistributions in binary form must reproduce the above
10+
copyright notice, this list of conditions and the following disclaimer
11+
in the documentation and/or other materials provided with the
12+
distribution.
13+
* Neither the name of the copyright holder nor the names of its
14+
contributors may be used to endorse or promote products derived from
15+
this software without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

packages/crc32/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ crate-type = ["cdylib"]
1010
[dependencies]
1111
napi-rs = { version = "0.2" }
1212
napi-rs-derive = { version = "0.1" }
13-
crc32c = "0.4"
1413
crc32fast = "1.2"
1514

1615
[build-dependencies]

packages/crc32/LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2020-present LongYinan
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

packages/crc32/README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
# `base64`
1+
# `@node-rs/crc32`
22

3-
> TODO: description
3+
Fastest `crc32` implement in `NodeJS`
44

5-
## Usage
5+
## API
66

7+
```ts
8+
export function crc32(input: Buffer, crc?: number): number
9+
export function crc32c(input: Buffer, crc?: number): number
710
```
8-
const base64 = require('base64');
911

10-
// TODO: DEMONSTRATE API
12+
## Usage
13+
14+
```ts
15+
const { crc32 } = require('@node-rs/crc32')
16+
const { readFileSync } = require('fs')
17+
18+
const content = readFileSync('./avatar.png')
19+
20+
crc32(content)
1121
```

packages/crc32/benchmark/calculate.js

Lines changed: 0 additions & 44 deletions
This file was deleted.

packages/crc32/benchmark/crc32.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
const { Suite } = require('benchmark')
2+
const Sse4Crc32 = require('sse4_crc32')
3+
const { crc32: crc32Node } = require('crc')
4+
const chalk = require('chalk')
5+
6+
const { crc32c, crc32 } = require('../crc32.node')
7+
8+
const TEST_BUFFER = Buffer.from(`Lorem ipsum dolor sit amet, consectetur
9+
adipiscing elit. Morbi mollis cursus metus vel tristique. Proin congue massa
10+
massa, a malesuada dolor ullamcorper a. Nulla eget leo vel orci venenatis
11+
placerat. Donec semper condimentum justo, vel sollicitudin dolor consequat id.
12+
Nunc sed aliquet felis, eget congue nisi. Mauris eu justo suscipit, elementum
13+
turpis ut, molestie tellus. Mauris ornare rutrum fringilla. Nulla dignissim
14+
luctus pretium. Nullam nec eros hendrerit sapien pellentesque sollicitudin.
15+
Integer eget ligula dui. Mauris nec cursus nibh. Nunc interdum elementum leo, eu
16+
sagittis eros sodales nec. Duis dictum nulla sed tincidunt malesuada. Quisque in
17+
vulputate sapien. Sed sit amet tellus a est porta rhoncus sed eu metus. Mauris
18+
non pulvinar nisl, volutpat luctus enim. Suspendisse est nisi, sagittis at risus
19+
quis, ultricies rhoncus sem. Donec ullamcorper purus eget sapien facilisis, eu
20+
eleifend felis viverra. Suspendisse elit neque, semper aliquet neque sed,
21+
egestas tempus leo. Duis condimentum turpis duis.`)
22+
23+
const initialCrc32 = crc32Node(TEST_BUFFER)
24+
const initialCrc32c = Sse4Crc32.calculate(TEST_BUFFER)
25+
26+
console.assert(crc32(TEST_BUFFER), initialCrc32)
27+
console.assert(crc32c(TEST_BUFFER), initialCrc32c)
28+
29+
const suite = new Suite('crc32c without initial crc')
30+
31+
suite
32+
.add('SIMD + NAPI', () => {
33+
crc32c(TEST_BUFFER)
34+
})
35+
.add('sse4_crc32', () => {
36+
Sse4Crc32.calculate(TEST_BUFFER)
37+
})
38+
.on('cycle', function (event) {
39+
console.info(String(event.target))
40+
})
41+
.on('complete', function () {
42+
console.info(`${this.name} bench suite: Fastest is ${chalk.green(this.filter('fastest').map('name'))}`)
43+
})
44+
.run()
45+
46+
const suite2 = new Suite('crc32c with initial crc')
47+
48+
suite2
49+
.add('SIMD + NAPI', () => {
50+
crc32c(TEST_BUFFER, initialCrc32c)
51+
})
52+
.add('sse4_crc32', () => {
53+
Sse4Crc32.calculate(TEST_BUFFER, initialCrc32c)
54+
})
55+
.on('cycle', function (event) {
56+
console.info(String(event.target))
57+
})
58+
.on('complete', function () {
59+
console.info(`${this.name} bench suite: Fastest is ${chalk.green(this.filter('fastest').map('name'))}`)
60+
})
61+
.run()
62+
63+
const suite3 = new Suite('crc32 without initial crc')
64+
65+
suite3
66+
.add('SIMD + NAPI', () => {
67+
crc32(TEST_BUFFER)
68+
})
69+
.add('Node crc', () => {
70+
crc32Node(TEST_BUFFER)
71+
})
72+
.on('cycle', function (event) {
73+
console.info(String(event.target))
74+
})
75+
.on('complete', function () {
76+
console.info(`${this.name} bench suite: Fastest is ${chalk.green(this.filter('fastest').map('name'))}`)
77+
})
78+
.run()
79+
80+
const suite4 = new Suite('crc32 with initial crc')
81+
82+
suite4
83+
.add('SIMD + NAPI', () => {
84+
crc32(TEST_BUFFER, initialCrc32)
85+
})
86+
.add('Node crc32', () => {
87+
crc32Node(TEST_BUFFER, initialCrc32)
88+
})
89+
.on('cycle', function (event) {
90+
console.info(String(event.target))
91+
})
92+
.on('complete', function () {
93+
console.info(`${this.name} bench suite: Fastest is ${chalk.green(this.filter('fastest').map('name'))}`)
94+
})
95+
.run()

packages/crc32/build.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,79 @@
11
extern crate napi_build;
22

33
use std::env;
4+
use std::fs::File;
5+
use std::io::{self, Write};
6+
use std::path::{Path, PathBuf};
47

5-
fn main() {
8+
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
9+
10+
const CASTAGNOLI_POLY: u32 = 0x82f63b78;
11+
12+
fn main() -> Result<()> {
613
napi_build::setup();
714

8-
env::set_var("RUSTFLAGS", "-C target-feature=+sse4.2");
15+
let out_dir = match env::var_os("OUT_DIR") {
16+
None => return Err(From::from("OUT_DIR environment variable not defined")),
17+
Some(out_dir) => PathBuf::from(out_dir),
18+
};
19+
write_crc_tables(&out_dir)?;
20+
21+
Ok(())
22+
}
23+
24+
fn write_crc_tables(out_dir: &Path) -> Result<()> {
25+
let out_path = out_dir.join("crc32_table.rs");
26+
let mut out = io::BufWriter::new(File::create(out_path)?);
27+
28+
let table = make_table(CASTAGNOLI_POLY);
29+
let table16 = make_table16(CASTAGNOLI_POLY);
30+
31+
writeln!(out, "pub const TABLE: [u32; 256] = [")?;
32+
for &x in table.iter() {
33+
writeln!(out, " {},", x)?;
34+
}
35+
writeln!(out, "];\n")?;
36+
37+
writeln!(out, "pub const TABLE16: [[u32; 256]; 16] = [")?;
38+
for table in table16.iter() {
39+
writeln!(out, " [")?;
40+
for &x in table.iter() {
41+
writeln!(out, " {},", x)?;
42+
}
43+
writeln!(out, " ],")?;
44+
}
45+
writeln!(out, "];")?;
46+
47+
out.flush()?;
48+
49+
Ok(())
50+
}
51+
52+
fn make_table16(poly: u32) -> [[u32; 256]; 16] {
53+
let mut tab = [[0; 256]; 16];
54+
tab[0] = make_table(poly);
55+
for i in 0..256 {
56+
let mut crc = tab[0][i];
57+
for j in 1..16 {
58+
crc = (crc >> 8) ^ tab[0][crc as u8 as usize];
59+
tab[j][i] = crc;
60+
}
61+
}
62+
tab
63+
}
64+
65+
fn make_table(poly: u32) -> [u32; 256] {
66+
let mut tab = [0; 256];
67+
for i in 0u32..256u32 {
68+
let mut crc = i;
69+
for _ in 0..8 {
70+
if crc & 1 == 1 {
71+
crc = (crc >> 1) ^ poly;
72+
} else {
73+
crc >>= 1;
74+
}
75+
}
76+
tab[i as usize] = crc;
77+
}
78+
tab
979
}

packages/crc32/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"files": [
1919
"index.js",
2020
"index.d.ts",
21-
"index.*.node"
21+
"index.*.node",
22+
"LICENSE",
23+
"COPYING"
2224
],
2325
"repository": {
2426
"type": "git",

0 commit comments

Comments
 (0)