0

我有一个基于 Node-Webkit 的应用程序,它执行一些繁重的 WebGL 工作(足以强调高端 GPU)、相当大量的 JS 处理,并且我正在OSC以 ~4kb/s 的顺序发送数据节点dgram模块给一个scsynth子进程来控制音频。

OSC 数据每 10 帧动画包含在一个包中,并且音频可以容忍它接收到的消息中的一些延迟或不规则性,但不是我所经历的规模。

socket.send(...)不幸的是,我发现在调用和实际发送数据之间经常有很大的延迟。似乎在某些情况下,调度程序对实际发送数据的优先级很低,以至于每个新数据包几乎无限期地停止,然后突然以大的不受控制的突发释放,溢出scsynth命令队列。

我无法将 udp 代码放入 WebWorker,因为node.js对象在该上下文中不起作用。我正在考虑尝试设置一个单独的窗口(因此,进程)仅负责将通过window.postMessageUDP 接收的数据转发(反之亦然),但由于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));
};
4

1 回答 1

1

如果它对其他人有帮助,我们通过将对 requestAnimationFrame 的调用替换为超时为 1ms 的调用和 requestAnimationFrame 来解决此问题。这允许其他事情(例如 udp 发送/接收处理)在 1 毫秒处理时间内挤入线程,而不会显着影响整体 fps。

~~~

ps 使用 nw 8.5 我发现使用 setTimeout 延迟 requestAnimationFrame 效果最好,典型的 OSC 往返时间为 2 毫秒。使用 process.setTick 推迟 OSC 往返时间约为 20 毫秒。直接调用 requestAnimationFrame 会导致 OSC 消息的几乎完整块。

使用 nw 12.1 没有问题,所有三个变体的行为几乎完全相同,典型的往返时间为 2 毫秒。

一段时间以来,我们一直被限制使用 nw 8.5,因为我们的 webGL 代码无法与 ANGLE 一起使用,并且更高版本的 nw 无法与 -use-gl=desktop 一起使用。使用最新版本的 nw,ANGLE 工作得更好,-use-gl=desktop 也再次工作。

于 2015-05-26T17:23:49.903 回答