我将如何为node.jsdevise和实现一个无阻塞的内存映射模块

存在node.js的mmap模块: https : //github.com/bnoordhuis/node-mmap/

正如作者Ben Noordhuis指出的那样,访问映射的内存可能会阻塞,这就是为什么他不再推荐它并停止使用它。

所以我不知道如何devisenode.js的无阻塞内存映射模块? 线程,纤维,?

显然这附近引发了一个问题,如果线程在node.js只会发生在别处而不是请求处理程序。

当谈到以非阻塞的方式实现一些本地设施时,首先要看的是libuv 。 节点的核心模块是如何与底层平台进行交互的。 特别感兴趣的是工作队列 API。

如果我们快速浏览一下node-mmap的源代码 ,我们可以看到它实际上非常简单。 它调用mmap并返回包装映射内存区域的节点Buffer

从此Buffer读取的结果是操作系统执行I / O。 因为那必然发生在JS线程上,所以我们最终用磁盘I / O阻塞了JS线程。

而不是返回一个允许JS直接访问映射的内存的Buffer ,你应该编写一个封装类在C ++编组通过工作队列读写。 这样,磁盘I / O将在单独的线程上发生。

在JS中,你会使用这样的东西:

 fs.open('/path/to/file', 'r', function(err, fd) { fs.fstat(fd, function(err, stats) { var mapped = mmap.map(stats.size, mmap.PROT_READ, mmap.MAP_SHARED, fd, 0); mapped.read(start, len, function(err, data) { // ... }); }); }); 

在C中, read函数会创build一个libuv工作请求并将其排入工作队列中。 C工作者函数然后将读取映射的内存范围(根据调用者的规格),这可能会导致磁盘I / O,但这是安全的,因为它发生在一个单独的线程。

接下来发生的事情很有趣。 安全的方法是让工作人员从映射的内存中分配一块新的内存和memcpy 。 工作人员然后传递一个指向副本的指针,Ccallback将其包装在一个Buffer ,以返回到JS-land。

您也可以尝试读取范围(以便在工作线程上发生任何必需的I / O),但实际上并没有对数据做任何事情,然后使用Ccallback将映射的内存范围简单地包装在Buffer 。 从理论上讲,工作人员读取的文件部分将保留在RAM中,因此访问映射内存的那部分不会被阻塞。 不过,我真的不知道映射的内存是否足以说明你是否会咬你。


最后,我怀疑这是否会提供任何额外的性能超过节点的常规fs方法。 如果我正在做一些真正合理使用mmap东西,我只能走这条路。

Interesting Posts