我有一个基于 Node-Webkit 的应用程序,它执行一些繁重的 WebGL 工作(足以强调高端 GPU)、相当大量的 JS 处理,并且我正在OSC
以 ~4kb/s 的顺序发送数据节点dgram
模块给一个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));
};