Skip to content

Commit 3028a17

Browse files
committed
fix: hmac string passing
1 parent 054aefb commit 3028a17

12 files changed

Lines changed: 300 additions & 49 deletions

File tree

example/src/benchmarks/benchmarks.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ export class BenchmarkSuite {
2828

2929
async run() {
3030
this.results = [];
31-
const promises = this.benchmarks.map(async benchFn => {
31+
// Run benchmarks sequentially to avoid timing interference
32+
for (const benchFn of this.benchmarks) {
3233
const b = await benchFn();
3334
await b.run();
3435
this.processResults(b);
35-
this.state = 'done';
36-
});
37-
await Promise.all(promises);
36+
}
37+
this.state = 'done';
3838
}
3939

4040
processResults = (b: Bench): void => {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import rnqc from 'react-native-quick-crypto';
2+
// @ts-expect-error - crypto-browserify is not typed
3+
import browserify from 'crypto-browserify';
4+
import { gcm } from '@noble/ciphers/aes.js';
5+
import type { BenchFn } from '../../types/benchmarks';
6+
import { Bench } from 'tinybench';
7+
import { buffer1MB } from '../testData';
8+
9+
// Generate a key for AES-256-GCM
10+
const key = rnqc.randomBytes(32);
11+
const iv = rnqc.randomBytes(12);
12+
13+
// @noble requires Uint8Array
14+
const nobleKey = new Uint8Array(key);
15+
const nobleIv = new Uint8Array(iv);
16+
17+
const cipher_aes256gcm_1mb_buffer: BenchFn = () => {
18+
const bench = new Bench({
19+
name: 'cipher aes256gcm 1MB Buffer',
20+
iterations: 1,
21+
warmupIterations: 0,
22+
});
23+
24+
const nobleData = new Uint8Array(buffer1MB);
25+
26+
bench
27+
.add('rnqc', () => {
28+
const cipher = rnqc.createCipheriv('aes-256-gcm', key, iv);
29+
cipher.update(buffer1MB);
30+
cipher.final();
31+
})
32+
.add('@noble/ciphers/aes', () => {
33+
const cipher = gcm(nobleKey, nobleIv);
34+
cipher.encrypt(nobleData);
35+
})
36+
.add('browserify', () => {
37+
const cipher = browserify.createCipheriv('aes-256-gcm', key, iv);
38+
cipher.update(buffer1MB);
39+
cipher.final();
40+
});
41+
42+
return bench;
43+
};
44+
45+
export default [cipher_aes256gcm_1mb_buffer];

example/src/benchmarks/hash/hash.ts

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,14 @@ import { sha256 } from '@noble/hashes/sha2';
44
import browserify from 'crypto-browserify';
55
import type { BenchFn } from '../../types/benchmarks';
66
import { Bench } from 'tinybench';
7+
import { text1MB, text8MB, buffer1MB, buffer8MB } from '../testData';
78

8-
// Generate test data of different sizes using repeating pattern
9-
const generateString = (sizeInMB: number): string => {
10-
const chunk =
11-
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
12-
const bytesPerMB = 1024 * 1024;
13-
const totalBytes = Math.floor(sizeInMB * bytesPerMB);
14-
const repeatCount = Math.ceil(totalBytes / chunk.length);
15-
return chunk.repeat(repeatCount).substring(0, totalBytes);
16-
};
17-
18-
// Pre-generate test data (8MB as reported in issue)
19-
const text100KB = generateString(0.1);
20-
const text1MB = generateString(1);
21-
const text8MB = generateString(8);
22-
23-
const hash_sha256_8mb: BenchFn = () => {
9+
const hash_sha256_8mb_string: BenchFn = () => {
2410
const bench = new Bench({
2511
name: 'hash sha256 8MB string',
26-
time: 10,
27-
iterations: 1,
28-
warmupIterations: 0,
12+
iterations: 3,
13+
warmupIterations: 1,
14+
time: 0,
2915
});
3016

3117
bench
@@ -46,12 +32,12 @@ const hash_sha256_8mb: BenchFn = () => {
4632
return bench;
4733
};
4834

49-
const hash_sha256_1mb: BenchFn = () => {
35+
const hash_sha256_1mb_string: BenchFn = () => {
5036
const bench = new Bench({
5137
name: 'hash sha256 1MB string',
52-
time: 50,
53-
iterations: 2,
54-
warmupIterations: 0,
38+
iterations: 5,
39+
warmupIterations: 2,
40+
time: 0,
5541
});
5642

5743
bench
@@ -72,29 +58,61 @@ const hash_sha256_1mb: BenchFn = () => {
7258
return bench;
7359
};
7460

75-
const hash_sha256_100kb: BenchFn = () => {
61+
const hash_sha256_8mb_buffer: BenchFn = () => {
62+
const bench = new Bench({
63+
name: 'hash sha256 8MB Buffer',
64+
iterations: 3,
65+
warmupIterations: 1,
66+
time: 0,
67+
});
68+
69+
bench
70+
.add('rnqc', () => {
71+
const hash = rnqc.createHash('sha256');
72+
hash.update(buffer8MB);
73+
hash.digest('hex');
74+
})
75+
.add('@noble/hashes/sha256', () => {
76+
sha256(buffer8MB);
77+
})
78+
.add('browserify', () => {
79+
const hash = browserify.createHash('sha256');
80+
hash.update(buffer8MB);
81+
hash.digest('hex');
82+
});
83+
84+
return bench;
85+
};
86+
87+
const hash_sha256_1mb_buffer: BenchFn = () => {
7688
const bench = new Bench({
77-
name: 'hash sha256 100KB string',
89+
name: 'hash sha256 1MB Buffer',
7890
iterations: 5,
91+
warmupIterations: 2,
92+
time: 0,
7993
});
8094

8195
bench
8296
.add('rnqc', () => {
8397
const hash = rnqc.createHash('sha256');
84-
hash.update(text100KB);
98+
hash.update(buffer1MB);
8599
hash.digest('hex');
86100
})
87101
.add('@noble/hashes/sha256', () => {
88-
sha256(text100KB);
102+
sha256(buffer1MB);
89103
})
90104
.add('browserify', () => {
91105
const hash = browserify.createHash('sha256');
92-
hash.update(text100KB);
106+
hash.update(buffer1MB);
93107
hash.digest('hex');
94108
});
95109

96-
bench.warmupTime = 100;
97110
return bench;
98111
};
99112

100-
export default [hash_sha256_100kb, hash_sha256_1mb, hash_sha256_8mb];
113+
export default [
114+
hash_sha256_1mb_string,
115+
hash_sha256_1mb_buffer,
116+
hash_sha256_8mb_string,
117+
hash_sha256_8mb_buffer,
118+
];
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import rnqc from 'react-native-quick-crypto';
2+
// @ts-expect-error - crypto-browserify is not typed
3+
import browserify from 'crypto-browserify';
4+
import { hmac } from '@noble/hashes/hmac';
5+
import { sha256 } from '@noble/hashes/sha2';
6+
import type { BenchFn } from '../../types/benchmarks';
7+
import { Bench } from 'tinybench';
8+
import { text1MB, text8MB, buffer1MB, buffer8MB } from '../testData';
9+
10+
const hmacKey = 'test-key-for-hmac-benchmarks';
11+
12+
const hmac_sha256_8mb_string: BenchFn = () => {
13+
const bench = new Bench({
14+
name: 'hmac sha256 8MB string',
15+
iterations: 3,
16+
warmupIterations: 1,
17+
time: 0,
18+
});
19+
20+
bench
21+
.add('rnqc', () => {
22+
const h = rnqc.createHmac('sha256', hmacKey);
23+
h.update(text8MB);
24+
h.digest('hex');
25+
})
26+
.add('@noble/hashes/hmac', () => {
27+
hmac(sha256, hmacKey, text8MB);
28+
})
29+
.add('browserify', () => {
30+
const h = browserify.createHmac('sha256', hmacKey);
31+
h.update(text8MB);
32+
h.digest('hex');
33+
});
34+
35+
return bench;
36+
};
37+
38+
const hmac_sha256_1mb_string: BenchFn = () => {
39+
const bench = new Bench({
40+
name: 'hmac sha256 1MB string',
41+
iterations: 5,
42+
warmupIterations: 2,
43+
time: 0,
44+
});
45+
46+
bench
47+
.add('rnqc', () => {
48+
const h = rnqc.createHmac('sha256', hmacKey);
49+
h.update(text1MB);
50+
h.digest('hex');
51+
})
52+
.add('@noble/hashes/hmac', () => {
53+
hmac(sha256, hmacKey, text1MB);
54+
})
55+
.add('browserify', () => {
56+
const h = browserify.createHmac('sha256', hmacKey);
57+
h.update(text1MB);
58+
h.digest('hex');
59+
});
60+
61+
return bench;
62+
};
63+
64+
const hmac_sha256_8mb_buffer: BenchFn = () => {
65+
const bench = new Bench({
66+
name: 'hmac sha256 8MB Buffer',
67+
iterations: 3,
68+
warmupIterations: 1,
69+
time: 0,
70+
});
71+
72+
bench
73+
.add('rnqc', () => {
74+
const h = rnqc.createHmac('sha256', hmacKey);
75+
h.update(buffer8MB);
76+
h.digest('hex');
77+
})
78+
.add('@noble/hashes/hmac', () => {
79+
hmac(sha256, hmacKey, buffer8MB);
80+
})
81+
.add('browserify', () => {
82+
const h = browserify.createHmac('sha256', hmacKey);
83+
h.update(buffer8MB);
84+
h.digest('hex');
85+
});
86+
87+
return bench;
88+
};
89+
90+
const hmac_sha256_1mb_buffer: BenchFn = () => {
91+
const bench = new Bench({
92+
name: 'hmac sha256 1MB Buffer',
93+
iterations: 5,
94+
warmupIterations: 2,
95+
time: 0,
96+
});
97+
98+
bench
99+
.add('rnqc', () => {
100+
const h = rnqc.createHmac('sha256', hmacKey);
101+
h.update(buffer1MB);
102+
h.digest('hex');
103+
})
104+
.add('@noble/hashes/hmac', () => {
105+
hmac(sha256, hmacKey, buffer1MB);
106+
})
107+
.add('browserify', () => {
108+
const h = browserify.createHmac('sha256', hmacKey);
109+
h.update(buffer1MB);
110+
h.digest('hex');
111+
});
112+
113+
return bench;
114+
};
115+
116+
export default [
117+
hmac_sha256_1mb_string,
118+
hmac_sha256_1mb_buffer,
119+
hmac_sha256_8mb_string,
120+
hmac_sha256_8mb_buffer,
121+
];

example/src/benchmarks/testData.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Shared test data for benchmarks
2+
// Generate test data of different sizes using repeating pattern
3+
const generateString = (sizeInMB: number): string => {
4+
const chunk =
5+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6+
const bytesPerMB = 1024 * 1024;
7+
const totalBytes = Math.floor(sizeInMB * bytesPerMB);
8+
const repeatCount = Math.ceil(totalBytes / chunk.length);
9+
return chunk.repeat(repeatCount).substring(0, totalBytes);
10+
};
11+
12+
// Pre-generate test data once for all benchmarks
13+
export const text100KB = generateString(0.1);
14+
export const text1MB = generateString(1);
15+
export const text8MB = generateString(8);
16+
17+
// Pre-generate Buffer versions for comparison
18+
export const buffer100KB = Buffer.from(text100KB);
19+
export const buffer1MB = Buffer.from(text1MB);
20+
export const buffer8MB = Buffer.from(text8MB);

example/src/components/BenchmarkResultItem.tsx

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,36 @@ export const BenchmarkResultItemHeader: React.FC = () => {
2424
export const BenchmarkResultItem: React.FC<BenchmarkResultItemProps> = ({
2525
result,
2626
}: BenchmarkResultItemProps) => {
27+
// Check if benchmark errored out
28+
const usHasError = result.us?.error !== undefined;
29+
const themHasError = result.them?.error !== undefined;
30+
31+
if (usHasError || themHasError) {
32+
return (
33+
<View>
34+
<View style={styles.subContainer}>
35+
<Text style={[styles.sub, styles.benchName]}>{result.benchName}</Text>
36+
</View>
37+
<View style={styles.subContainer}>
38+
<Text style={[styles.sub, styles.subLabel]}>error</Text>
39+
<Text style={[styles.sub, styles.subValue, styles.slower]}>
40+
{usHasError ? 'rnqc failed' : ''}
41+
{usHasError && themHasError ? ' / ' : ''}
42+
{themHasError ? `${result.challenger} failed` : ''}
43+
</Text>
44+
</View>
45+
</View>
46+
);
47+
}
48+
49+
const hasComparison = result.them !== undefined;
50+
2751
const rows = ['throughput', 'latency'].map((key, i) => {
2852
const us = result.us![key as Key].mean;
29-
const them = result.them![key as Key].mean;
53+
const them = hasComparison ? result.them![key as Key].mean : 0;
3054
const comparison = key === 'throughput' ? us > them : us < them;
3155
const places = key === 'throughput' ? 2 : 3;
32-
const times = calculateTimes(us, them);
56+
const times = hasComparison ? calculateTimes(us, them) : 0;
3357
const emoji = comparison ? '🐇' : '🐢';
3458
const timesType = comparison ? 'faster' : 'slower';
3559
const timesStyle = timesType === 'faster' ? styles.faster : styles.slower;
@@ -41,11 +65,15 @@ export const BenchmarkResultItem: React.FC<BenchmarkResultItemProps> = ({
4165
<Text style={[styles.text, styles.description]}>
4266
{key} {key === 'throughput' ? '(ops/s)' : '(ms)'}
4367
</Text>
44-
<Text style={[styles.value, timesStyle]}>
45-
{formatNumber(times, 2, 'x')}
46-
</Text>
68+
{hasComparison && (
69+
<Text style={[styles.value, timesStyle]}>
70+
{formatNumber(times, 2, 'x')}
71+
</Text>
72+
)}
4773
<Text style={styles.value}>{formatNumber(us, places, '')}</Text>
48-
<Text style={styles.value}>{formatNumber(them, places, '')}</Text>
74+
{hasComparison && (
75+
<Text style={styles.value}>{formatNumber(them, places, '')}</Text>
76+
)}
4977
</View>
5078
</View>
5179
);

0 commit comments

Comments
 (0)