Javascript 使node.js及时发送数据报套接字数据
我有一个基于Node Webkit的应用程序,它做了一些繁重的WebGL工作(足够强调高端GPU),相当多的JS处理,我用NodeJavascript 使node.js及时发送数据报套接字数据,javascript,node.js,sockets,datagram,node-webkit,Javascript,Node.js,Sockets,Datagram,Node Webkit,我有一个基于Node Webkit的应用程序,它做了一些繁重的WebGL工作(足够强调高端GPU),相当多的JS处理,我用Nodedgram模块将OSC数据以~4kb/s的顺序发送到scsynth子进程以控制音频 OSC数据包含在每10帧动画的一个包中,并且音频对它接收到的消息中的一些延迟或不规则性是相当宽容的,但不是我所经历的规模 不幸的是,我发现调用socket.send(…)和实际发送的数据之间往往存在很大的延迟。似乎在某些情况下,调度器对实际发送数据的优先级很低,以至于每个新数据包几乎无
dgram
模块将OSC
数据以~4kb/s的顺序发送到scsynth
子进程以控制音频
OSC数据包含在每10帧动画的一个包中,并且音频对它接收到的消息中的一些延迟或不规则性是相当宽容的,但不是我所经历的规模
不幸的是,我发现调用socket.send(…)
和实际发送的数据之间往往存在很大的延迟。似乎在某些情况下,调度器对实际发送数据的优先级很低,以至于每个新数据包几乎无限期地暂停,然后突然释放,导致scsynth
命令队列溢出
我无法将udp代码放入WebWorker,因为node.js
对象在该上下文中不起作用。我正在考虑尝试设置一个单独的窗口(也就是进程),单独负责将通过window.postMessage
接收的数据转发到UDP(反之亦然),但由于postMessage
本身也是异步的,如果不可见,则另一个窗口本身的优先级可能较低,我想知道这是否会带来很多好处
我很确定,主要问题在于Javascript中的工作调度,而不是过程中的任何其他地方;我看不出接收端有什么特别的麻烦,尽管也许可以更仔细地评估一下
下面是一个简短的代码片段,展示如何设置和使用套接字(包括收集发送回调的一些基本统计信息)
为了帮助其他人,我们通过将对requestAnimationFrame的调用替换为超时1ms和requestAnimationFrame的调用来解决这个问题。这允许其他事情(如udp发送/接收处理)在1ms的时间内挤进线程,而不会显著影响总体fps ~~~ p、 美国。 使用NW8.5,我发现使用setTimeout延迟requestAnimationFrame效果最好,典型的OSC往返时间为2ms。延迟进程。setTick给出的OSC往返时间约为20ms。调用requestAnimationFrame直接导致OSC消息几乎完全阻塞 使用nw 12.1没有问题,所有三种变体的行为几乎完全相同,典型往返时间为2ms
我们已经被迫使用nw 8.5有一段时间了,因为我们的webGL代码不适用于ANGLE,而nw的更高版本也不适用于-use gl=desktop。使用最新版本的nw,ANGLE工作得更好,并且-use gl=desktop也再次工作。如果您能提供一个可运行的案例来复制此内容,我将尝试修复它。谢谢。实际的项目是相当大和毛茸茸的,但我可能能够强迫它以更简单的方式复制,这也将有助于消除我一直认为不相关的系统部分。不确定这将需要多长时间,我现在只能求助于实际项目的静态音频文件,但仍然希望让架构正常工作。我曾尝试将网络模块与tcp一起使用,但不起作用;也许是另一个问题的主题。我刚刚意识到我在和你说话,罗杰。再次感谢你主动提供帮助。我关于socket.send的较低级别被认为是低优先级的,因此没有被调度的推理是否正确?我认为它没有被调度为低优先级。顺便说一句,你的操作系统是什么?我遇到的主要问题是Windows 7 64位。关于
process.nextTick()
?正如Peter T所指出的,“其他事情”更具体地说是“节点上下文中排队的事件”。谢谢你的建议,加布里埃尔。我将尝试process.nextTick()。由于我们的应用程序是GPU绑定的,javascript cpu成本相对较低,我怀疑这不会有多大区别,但多学一点总是好的。nextTick现在甚至可以工作了。stackoverflow没有让我编辑完最后的评论。。。nextTick()甚至可能不起作用。文档中说:“在开发API时,这一点很重要,在开发API时,您希望让用户有机会在构建对象之后,但在发生任何I/O之前分配事件处理程序。”设置setTimeout()的原因是确保确实发生I/O。
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));
};