gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 22:20:28 28 4
gpt4 key购买 nike

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

背景:我有麦克风流进来,我想避免额外的复制操作以节省整个系统的 MIPS。我知道对于音频流来说,即使在引擎盖下有 memcopy,也不会花费大量的 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;

问题如下:

  1. 为了能够执行流控制,source.pipe(dest) 是在幕后执行从源内存到目标内存的 memcpy,还是将内存中的引用传递到目标?
  2. 评论的代码包含一个 PassThrough 类实例化 - 我目前假设 PassThrough 也会导致 memcopies,所以我在整个系统中保存了一个 memcpy 操作,因为我在上面的评论中添加了?
  3. 如果我必须在一个进程和一个生成的子进程之间创建一个管道(使用 child_process.spawn() ,如 How to transfer/stream big data from/to child processes in node.js without using the blocking stdio? 所示),我认为这肯定会导致 memcpy?有没有办法使它成为一个引用而不是复制?
  4. 此行为是否因操作系统而异?我认为它应该与操作系统无关,但无论如何都要问这个问题。

在此先感谢您的帮助。它将对我的架构有很大帮助。

最佳答案

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

我试着根据 theese 和其他一些文件写了一个复杂/庞大的解释,但是我得出的结论是最好给你一个总结,说明我的经验/阅读告诉我 Node 内部是如何工作的:

pipe 简单地连接流,使其看起来好像 .on("data", …).write(…) 调用,中间没有任何臃肿的东西。

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

如果您将进程的标准输出连接到某个 .on("data", …) 监听器,它会将传入的 block 复制到 Buffer 对象中,以便在 js 世界中进一步使用。
在 js 世界中,你有 .pause() 等方法(正如你在 Node steam api 文档中看到的那样),以防止进程占用内存,以防传入数据流速度快于其处理速度。

通过管道连接进程的标准输出和例如传出的 tcp 端口将导致类似于 nginx 操作方式的连接。它将连接这些流,就好像它们会通过将传入数据直接复制到传出流来直接相互对话一样。

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

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

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

block 方式将允许您一次将数据发送到多个客户端,并且会保持内存占用非常低。

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

关于node.js - .pipe() 是否在 node.js 中执行 memcpy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35110911/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com