Bigint-buffer:TC39 BigInt提案的缓冲公用事业
大缓冲 是工具转换 TC39 提议的大意 来往于缓冲. 这种用法是必需的,因为BigInts按提议不支持Buffers(或UInt8Arrays)之间的直接转换,而是要求从缓冲线到十六进制字符串再转换为BigInts,这是次优. 这种工具包括了N-API绑定,因此在节点下,转换是在不产生十六进制字符串的情况下进行的. 在浏览器中,使用正常的字符串转换.
为什么要用BigInts?
BigInts目前是一个第3阶段提案,在Node 10和V8 v 6.7.中被支持. BigInts是原始的任意精度整数,克服了javascript中数字类型的限制,它只支持高达53位精度.
在许多应用中,操纵64,128甚至256位数字相当常见. 例如,数据库标识符通常为128位,散列常为256位(如果寻求散列支持,请尝试 长发)在BigInts之前,安全地操纵这些数字需要分配缓冲器或UInt8Arrays,这与一个数字相比相当昂贵,因为缓冲器是在堆积上分配的.
BigInts通过引入一个可以持有的原始来解决这个问题
任意精确整数,减少内存压力并允许
运行时间可以更好地优化算术操作。 这导致了显著的性能改进——10x-100x的简单平等比较(使用: === 对 Buffer.compare():
Buffer equality comparison: 11916844±4.23% ops/s 83.91±17.293 ns/op (91 runs)
bigint equality comparison: 798024851±0.29% ops/s 1.25±0.017 ns/op (91 runs)
在BigInts之前,您可能使用过像被广泛使用的图书馆 bn.js (中文(简体) )。 。 。 . bn.js的票价比平地缓冲器略好,但仍比大调慢:
BN equality comparison: 73255774±0.67% ops/s 13.65±0.442 ns/op (89 runs)
比方说,比方说比算术要好得多, 比方说比BN乘以2的结果 128位整数,得到4x改进:
BN multiply: 4763236±0.49% ops/s 209.94±5.111 ns/op (93 runs)
bigint multiply: 15268666±0.92% ops/s 65.49±2.938 ns/op (92 runs)
有什么问题吗?
不幸的是,BigInts缺乏在缓冲器之间进行回转的有效途径. 在处理序列化数据或遗留节点代码时,往往会想从缓冲器中生成BigInt,或者将BigInt转换为Buffer来将BigInt发送到电线上.
目前,产生新BigInt的唯一方法是与BigInt构造器. 不幸的是,它不支持缓冲器,尽管它可能在未来:
> BigInt(Buffer.from([1]))
SyntaxError: Cannot convert to a BigInt
相反,您需要将缓冲转换成正确格式的十六进制字符串。 例如:
> BigInt(`0x${buf.toString('hex')}`);
1n
这些转换不仅相当昂贵, 也排除了很多我们从BigInts获得的绩效收益。 例如,在大型缓冲器上,这种转换可以占用100x以上的时间来进行比较:
bigint from hex string from buffer (huge): 1230607±1.02% ops/s 812.61±40.013 ns/op (89 runs)
还有... 大块头怎么帮?
bigint-buffer引入了4个功能,用于缓冲器和bigint之间的转换. 以下是一个小例子:
import {toBigIntBE, toBigIntLE, toBufferBE, toBufferLE} from 'bigint-buffer';
// Get a big endian buffer of the given width
toBufferBE(0xdeadbeefn, 8);
// ↪ <Buffer 00 00 00 00 de ad be ef>
// Get a little endian buffer of the given width
toBufferLE(0xdeadbeefn, 8);
// ↪ <Buffer ef be ad de 00 00 00 00>
// Get a BigInt from a buffer in big endian format
toBigIntBE(Buffer.from('deadbeef', 'hex'));
// ↪ 3735928559n (0xdeadbeefn)
// Get a BigInt from a buffer in little endian format
toBigIntLE(Buffer.from('deadbeef', 'hex'));
// ↪ 4022250974n (0xefbeadd0en)
bigint-buffer 使用 N- API 本地绑定来高效地进行转换,而不生成 直接六分弦 需要用纯的javascript。 这导致业绩显著提高, 用于小缓冲器到比奇特转换的大约2x,以及比BN更好的8x:
BN to buffer (small): 981703±68.30% ops/s 1018.64±3194.648 ns/op (81 runs)
bigint from hex string from buffer (small): 2804915±5.00% ops/s 356.52±85.371 ns/op (88 runs)
LE bigint-buffer ToBigInt (small): 5932704±1.62% ops/s 168.56±12.971 ns/op (87 runs)
约3.3x用于活化转换 17x优于BN:
BN to buffer (large): 339437±2.85% ops/s 2946.06±385.504 ns/op (81 runs)
BE bigint to hex string to buffer (large): 1714292±1.35% ops/s 583.33±37.995 ns/op (90 runs)
BE bigint-buffer to buffer (large, truncated): 5977218±4.68% ops/s 167.30±37.284 ns/op (87 runs)
您可以通过运行来运行基准 npm run benchmark。 。 。 .
键入符支持
bigint-buffer 提供打字符绑定, 但是 Bigint 仍然不支持打字符, 尽管 已经启动了拉动请求,因此,支持应该很快到来。 如果你使用打字机, @calebsander提出拉出请求 这个员额。 。 。 .
安装
在您的项目中添加比金特缓冲器 :
npm install bigint-buffer
文档
基本 API 文档可见 这里。请注意 v1.0.0 变化 用于符合样式准则的原始函数名称.
基准
基准可通过执行来管理 npm run benchmark 从软件包目录.