Node.js Undocumented(2)
这一节,我将介绍下Buffer这个module。js本身对文本友好,但是处理二进制数据就不是特别方便,因此node.js提供了Buffer模块来帮助你处理二进制数据,毕竟node.js的定位在网络服务端,不能只对文本协议友好。
Buffer模块本身其实没有多少未公开的方法,重要的方法都在文档里提到了,有两个方法稍微值的提下。
Buffer.get(idx)
跟buffer[idx]是一样的,返回的是第idx个字节,返回的结果是数字,如果要转成字符,用String.fromCharCode(code)即可。
Buffer.inspect()
返回Buffer的字符串表示,每个字节用十六进制表示,当你调用console.dir的时候打印的就是这个方法返回的结果。
Buffer真正值的一提的是它的内部实现。Buffer在node.js内部的cpp代码对应的是SlowBuffer类(src/node_buffer.cc),但是两者之间并不是一一对应。对于创建小于**8K的Buffer,其实是从一个pool里slice出来,只有大于8K的Buffer才是每次都new一个SlowBuffer**。查看源码(lib/buffer.js):
Buffer.poolSize = 8 * 1024;
if (this.length > Buffer.poolSize) {
// Big buffer, just alloc one.
this.parent = new SlowBuffer(this.length);
this.offset = 0;
} else {
// Small buffer.
if (!pool || pool.length - pool.used < this.length) allocPool();
this.parent = pool;
this.offset = pool.used;
pool.used += this.length;
}
因此,我们可以修改Buffer.poolSize这个“静态”变量来改变池的大小
Buffer.poolSize
Buffer类创建的池大小,大于此值则每次new一个SlowBuffer,否则从池中slice返回一个Buffer,如果池剩余空间不够,则新创建一个SlowBuffer做为池。下面的例子打印这个值并修改成16K:
console.log(Buffer.poolSize);
Buffer.poolSize=161024;
SlowBuffer**类*
SlowBuffer类我们可以直接使用的,如果你不想使用Buffer类的话,SlowBuffer类有Buffer模块的所有方法实现,例子如下:
var SlowBuffer=require(‘buffer’).SlowBuffer
var buf=new SlowBuffer(1024)
buf.write(“hello”,’utf-8’);
console.log(buf.toString(‘utf-8’,0,5));
console.log(buf[0]);
var sub=buf.slice(1,3);
console.log(sub.length);
请注意,SlowBuffer默认不是Global的,需要require buffer模块。
使用建议和性能测试
Buffer的这个实现告诉我们,要使用好Buffer类还是有讲究的,每次创建小于8K的Buffer最好大小刚好能被8k整除,这样能充分利用空间;或者每次创建大于8K的Buffer,并充分重用。我们来看一个性能测试,分别循环1000万次创建16K,4096和4097大小的Buffer,看看耗时多少:
function benchmark(size,repeats){
var total=0;
console.log(“create %d size buffer for %d times”,size,repeats);
console.time(“times”);
for(var i=0;i<repeats;i++){
total+=new Buffer(size).length;
}
console.timeEnd(“times”);
}
var repeats=10000000;
console.log(“warm up”)
benchmark(1024,repeats);
console.log(“start benchmark”)
benchmark(16*1024,repeats);
benchmark(4096,repeats);
benchmark(4097,repeats);
创建1024的Buffer是为了做warm up。在我机器上的输出:
start benchmark
create 16384 size buffer for 10000000 times
times: 81973ms
create 4096 size buffer for 10000000 times
times: 80452ms
create 4097 size buffer for 10000000 times
times: 138364ms
创建4096和创建4097大小的Buffer,只差了一个字节,耗时却相差非常大,为什么会这样?读者可以自己根据上面的介绍分析下,有兴趣的可以留言。
另外,可以看到创建16K和创建4K大小的Buffer,差距非常小,平均每秒钟都能创建10万个以上的Buffer,这个效率已经足以满足绝大多数网络应用的需求。
本文来源于"阿里中间件团队播客",原文发表时间" 2011-07-06"
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的