.pipe()是否在node.js中执行memcpy?

Ash*_*ish 8 v8 pipe node.js libuv

这是关于系统级优化的概念性查询.通过阅读NodeJS文档,我的理解是管道可以方便地对流进行流量控制.

背景:我有麦克风流进来,我想避免额外的复制操作,以节省整体系统MIPS.据我所知,对于音频流来说,即使在引擎盖下有记忆镜,也不会花费大量的MIPS,但我也计划在30fps和UHD分辨率下以相机帧流式传输.以30fps制作UHD分辨率像素数据的多个副本是非常低效的,因此需要一些关于此的建议.

示例代码:

var spawn = require('child_process').spawn
var PassThrough = require('stream').PassThrough;

var ps = null;
//var audioStream = new PassThrough;
//var infoStream = new PassThrough;

var start = function() {
    if(ps == null) {
        ps = spawn('rec', ['-b', 16, '--endian', 'little', '-c', 1, '-r', 16000, '-e', 'signed-integer', '-t', 'raw', '-']);
        //ps.stdout.pipe(audioStream);
        //ps.stderr.pipe(infoStream);
        exports.audioStream = ps.stdout;
        exports.infoStream = ps.stderr;
    }
};

var stop = function() {
    if(ps) {
        ps.kill();
        ps = null;
    }
};

//exports.audioStream = audioStream;
//exports.infoStream = infoStream;
exports.startCapture = start;
exports.stopCapture = stop;
Run Code Online (Sandbox Code Playgroud)

以下是问题:

  1. 为了能够执行流量控制,source.pipe(dest)是否会执行从源内存到目标内存的memcpy,或者它会将内存中的引用传递到目标吗?
  2. 注释代码包含PassThrough类实例化 - 我目前假设PassThrough也会导致memcopies,所以我在整个系统中保存了一个memcpy操作,因为我在上面的注释中添加了?
  3. 如果我必须在Process和Spawned Child进程之间创建一个管道(使用child_process.spawn(),如如何在不使用阻塞stdio的情况下从node.js中的子进程传输/流传输大数据?),我假设肯定会产生memcpy?反正有没有提到参考而不是复制?
  4. 这种行为是否因操作系统而异?我认为它应该是OS不可知的,但无论如何要问这个.

在此先感谢您的帮助.它将有助于我的架构很多.

Got*_*ttZ 4

一些网址供参考:https://github.com/nodejs/node/
\n https://github.com/nodejs/node/blob/master/src/stream_wrap.cc
\n https://github .com/nodejs/node/blob/master/src/stream_base.cc
\n https://github.com/libuv/libuv/blob/v1.x/src/unix/stream.c
\n https://github .com/libuv/libuv/blob/v1.x/src/win/stream.c

\n\n

我尝试根据这些文件和其他一些文件编写一个复杂/庞大的解释,但是我得出的结论是最好向您总结我的经验/阅读告诉我节点内部如何工作:

\n\n

管道只是连接流,使其看起来好像.on("data", \xe2\x80\xa6)被调用,.write(\xe2\x80\xa6)中间没有任何臃肿的东西。

\n\n

现在我们需要将 js 世界与 c++/c 世界分开。
\n在js中处理数据时我们使用缓冲区。 https://github.com/nodejs/node/blob/master/src/node_buffer.cc
\n它们只是代表分配的内存,上面有一些糖果来对其进行操作。

\n\n

如果您将进程的 stdout 连接到某个.on("data", \xe2\x80\xa6)侦听器,它会将传入的块复制到 Buffer 对象中,以便在 js 世界中进一步使用。
\在 js 世界中,您可以使用诸如此类的方法.pause()(如您在 Nodes steam api 文档中看到的那样)来防止进程在传入数据流比其处理速度快的情况下消耗内存。

\n\n

连接进程的 stdout,例如通过管道连接传出 tcp 端口将产生类似于 nginx 操作方式的连接。它将连接这些流,就好像它们通过将传入数据直接复制到传出流来直接相互通信一样。

\n\n

一旦暂停流,节点将使用内部缓冲,以防无法暂停传入流。

\n\n

因此,对于您的场景,您应该只进行测试。
\n尝试通过节点中的传入流接收数据,暂停流并看看会发生什么。
不确定节点是否会使用内部缓冲,或者您尝试运行的进程是否会停止,直到它可以继续发送数据。
\ni 希望该过程停止,直到您继续流。

\n\n

为了传输巨大的图像,我建议将它们分块传输或将它们直接通过管道传输到传出端口。

\n\n

块方式允许您一次将数据发送到多个客户端,并且内存占用量相当低。

\n\n

PS你应该看看我刚刚发现的这个要点: https: //gist.github.com/joyrexus/10026630
\nit深入解释了如何与流交互

\n