Nodejs的Buffer对象(下)—— 源代码实现浅析

原创 Lin_Grady 教程 nodejs 42阅读 30 天前 举报

前言

一开始全文是基于《Nodejs深入浅出》,但是因为有段年头有些API已经是被废弃的,而且越往下走问题越多,最后只好自从查阅资料从头开始研究,所以这里的demo都是以Nodejs10.0为准。
因为内容实在太多,已经超过20000字限制,而且太长看着太烦了,所以我会分成三篇博文发布,后面发布了会补上跳转地址,分别是:
Nodejs的Buffer对象(上)—— API废弃与更新 (基于官网文档)
Nodejs的Buffer对象(中)—— 基本原理与使用要点(基于nodejs 深入浅出)
Nodejs的Buffer对象(下)—— 源代码实现浅析(基于nodejs源码)

因为靠自己整理输出,如果有哪些遗漏错误希望可以指教一下。

总流程图


(此图按个人理解输出,不代表实际如此)

初始池

bindingObj.zeroFill来龙去脉是什么我也没搞懂,反正知道是填充0就好了。
ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写。而ArrayBuffer是C++直接分配内存生成

allocate()

这里就是负责pool池分配内存的源代码了,
1,size <= 0,返回new FastBuffer()

2,size < 4 * 1024
1)如果内存不够调用createPool()初始化;
2)返回处理后的new FastBuffer();

,3,返回createUnsafeBuffer()

(明明是8K池但是却限制在4K,这里没懂。)

new FastBuffer() && createUnsafeBuffer(size)

Uint8Array类型数组表示的8位无符号整数数组。内容被初始化为0。一旦建立,您可以使用对象的方法或使用标准数组索引语法(即使用括号表示法)引用数组中的元素,所以 FastBuffer 其实就是继承自 Uint8ArrayBuffer 的类。
之前说过,Nodejs采用C++層面申請内存,Javascript中分配内存的策略,所以FastBuffer类也是采用Javascript分配的。

createUnsafeBuffer() 最终也是输出ArrayBuffer参数的FastBuffer实例,而且是共用内存不是另外分配。

Buffer.from()

我们先看看这个方法的源码。

Buffer.from(str[, encoding])

如果是字符串

输出方法代码

createFromString()是C++分配内存的方法。
大体就是如果参数没问题,小Buffer对象用new FastBuffer(),大Buffer对象采用createFromString()。

Buffer.from(arrayBuffer[, byteOffset[, length]])

相关判断代码

isAnyArrayBuffer(value) 应该是检测类型的方法,源码有个优雅降级的方案。

接下来重点是输出方法

整段代码来看其实也就是做些参数处理,最终返回的还是FastBuffer类实例。

主代码

我们跳过源码里的判断分支句直接看主逻辑

valueOf 返回 Array 对象的原始值,然后有值情况下拿原始值重新调用自身。

只看这段也知道_copy是做到复制写入的作用。
后面的代码根据不同情况也就输出new FastBuffer() 和 fromArrayLike() 两种,FastBuffer类已经知道了,我们直接看fromArrayLike() 的源码。

所以 fromArrayLike 内部也是调用 allocate()。

总结

内存分配可以简单记忆有两种:
createUnsafeBuffer():C++分配
其余:allocate分配

Buffer.from()大概分三种情况:
1,String:使用fromString转变为Buffer对象输出,调用allocate分配内存;
2,arrayBuffer:使用ArrayBuffer与新创建的Buffer共享内存,调用C++直接分配内存;
3,其他:返回复制值的副本Buffer对象,调用allocate分配内存;

Buffer.alloc()

我们看看这个方法的源码。

上面说过,createUnsafeBuffer(size)最终也是输出ArrayBuffer参数的FastBuffer实例,而_fill会对它做些处理。
再看看 assertSize() 方法。

都是些容错代码,忽略。

代码很多,但是只是做些处理判断,然后返回处理后的buf或者报错。

Buffer.allocUnsafe()

相当于Buffer(num),默认情况下创建一个非零填充的缓冲区,返回allocate(size)。

Buffer.allocUnsafeSlow()

最终也是输出ArrayBuffer参数的FastBuffer实例。

参考资料

Node.js v10.6.0 文档
nodejs 深入浅出
node/lib/buffer.js

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复