我有一个基于Node-Webkit的应用程序,它执行一些繁重的WebGL工作(足以强调高端GPU),相当大量的JS处理,我正在发送OSC
数据节点dgram
模块~4kb / s的顺序到scsynth
子进程来控制音频。
OSC数据每10帧动画包含在一个包中,音频相当容忍它收到的消息中的一些延迟或不规则,但不是我正在经历的规模。
不幸的是,我发现在调用socket.send(...)
和实际发送数据之间存在很大的延迟。似乎在某些情况下,调度程序将实际发送数据的优先级设置得非常低,以至于每个新数据包几乎无限期地陷入停顿状态,然后突然在溢出scsynth
命令队列的大量不受控制的突发中释放。
我无法将udp代码放入WebWorker中,因为node.js
对象在该上下文中不起作用。我正在考虑尝试设置一个单独的窗口(因此,进程),单独负责将通过window.postMessage
接收的数据转发到UDP(反之亦然),但由于postMessage
本身也是异步的,如果它不可见,那么另一个窗口本身可能具有低优先级,我想知道这是否可能提供很多好处。
我很确定主要问题在于在Javascript中安排工作而不是在流程中的其他任何地方;我认为在接收端没有特别的麻烦,尽管可能会对此进行更密切的评估。
这是一个简短的片段,展示了如何设置和使用套接字(包括在发送回调上收集一些基本统计信息)。
udp = require('dgram').createSocket('udp4');
//...
var udpStats = {lastSendDelay: 0, minSendDelay:Number.MAX_VALUE, maxSendDelay:-1, meanSendDelay:undefined};
var udpSend = function(buf) {
var t = new Date();
var wasSent = function(timeOfRequest) {
return function(err) {
if ((err)) sclog("UDP send Error: " + err);
var t2 = new Date();
var dt = t2 - timeOfRequest;
udpStats.lastSendDelay = dt;
udpStats.minSendDelay = Math.min(dt, udpStats.minSendDelay);
udpStats.maxSendDelay = Math.max(dt, udpStats.maxSendDelay);
udpStats.meanSendDelay = udpStats.meanSendDelay === undefined ? dt : (udpStats.meanSendDelay+dt)/2;
};
};
udp.send(buf, 0, buf.length, UDP_PORT, 'localhost', wasSent(t));
};
答案 0 :(得分:1)
如果它可以帮助其他人,我们通过将对requestAnimationFrame的调用替换为超时1ms的调用和requestAnimationFrame来解决这个问题。这允许其他东西(例如udp发送/接收处理)在1ms dealy中挤入线程,而不会显着影响整体fps。
~~~
P.S。 使用nw 8.5我发现使用setTimeout延迟requestAnimationFrame效果最好,典型的OSC往返时间为2ms。延迟使用process.setTick给OSC的往返时间约为20ms。直接调用requestAnimationFrame会导致几乎完整的OSC消息块。
使用nw 12.1没有问题,并且所有三种变体表现几乎完全相同,典型的往返时间为2ms。
由于我们的webGL代码无法与ANGLE一起使用,因此我们一直被限制使用nw 8.5,而后续版本的nw不适用于-use-gl = desktop。使用最新版本的nw,ANGLE工作得更好,而-use-gl = desktop也在使用。