【问题标题】:Running several physics worlds on Node.js, not getting most out of server在 Node.js 上运行多个物理世界,而不是充分利用服务器
【发布时间】:2019-08-18 11:52:02
【问题描述】:

我正在使用 Node.js 在 AWS 上托管我自己的多人游戏世界。游戏是基于物理的(使用 p2.js),所以我的物理步速相当高,每秒 200 步。

每个游戏都有自己的世界,每个世界需要每 5ms 步进一次。每个游戏只有大约 6-8 名玩家,所以我一次只能在服务器上托管大约 60 名玩家。我想改进这一点,但我不确定如何。

现在,我正在使用 nanotimer setInterval 并按顺序遍历每个物理世界。

const stepsPerSecond = 200;
// Number of games the server can manage.
const numSlots = 10;
// Evaluates to 500 microseconds (.5ms)
const timePerStep = parseInt(1000 * (1000 / stepsPerSecond) / numSlots);
const timeLabel = `${timePerStep}u`;

this.timer.setInterval(() => {
  const slotIndex = this.currIndex++;
  // Go back to beginning of slots if end.
  if (this.currIndex == this.numSlots) {
    this.currIndex = 0;
  }
  const game = this.slots[slotIndex];
  game.physics.update();
}, '', timePerStep);

这实际上效果很好,因为物理通常非常流畅,但问题是当它达到容量时,我认为线程中的计算量过多会出现很多卡顿。

平均每个世界步骤大约需要 0.2 毫秒,每秒 200 步,或每步之间 5 毫秒,理论上有 25 场游戏的空间。

有没有更好的方法来做到这一点?我觉得我没有充分利用我的服务器的潜力。也许旋转子进程?我曾尝试在同一台机器上同时运行第二台服务器,但它们最终会互相破坏并使所有世界都变得非常滞后。

编辑:添加更多关于物理世界的细节: 每个世界大约有 60 个物体,其中大部分是静态墙。一般有 7 个运动体,有几个传感器用于检测“目标”。

物理世界参数:

world.setGlobalStiffness(1e8);
// Default is 4, but the puck sometimes warps through the sticks
// with this any lower, even with CCD enabled.
world.setGlobalRelaxation(10);

maxSubSteps = 4;

【问题讨论】:

  • Node.js 擅长异步操作,。但是物理学本质上实际上并不是异步的。我要做的就是把你的物理计算放到另一个过程中。你可以试试 -> npmjs.com/package/thread 实际上避免使用那个 npm,现在有一段时间没有更新了。我最近用的一个很好用。我去找找吧。
  • 我明白了,你是在建议每个世界在自己的进程中,然后从计时器发送消息进行计算?
  • 不确定我现在用的是什么包!!,我想可能是这个npmjs.com/package/worker-threads-pool,或者我什至可能直接去了node.js工作线程nodejs.org/api/worker_threads.html。但是在节点中有一些东西我不得不做一些繁重的计算,我这样做了。 :) 你可以在自己的进程中完成每个世界,是的,这样可以让事情变得简单而美好。然后这让你的主要 node.js 进程做它擅长的事情。
  • 您能否添加您在 p2 上所做的与性能相关的设置,包括时间步进、求解器、broadphase 等?有多少个身体/形状,有哪些类型?
  • @schteppe 当然,刚刚添加了上面的内容。

标签: javascript node.js p2 cannon.js


【解决方案1】:

要充分利用 p2.js,您应该查看文档并关闭不需要的内容。例如:

world.defaultContactMaterial.friction=0; // if you don’t need contact friction on a ContactMaterial
world.narrowphase.enableFriction=false; // if you never need friction for anything in your World
world.applySpringForces=false; //if you don’t use springs
world.applyGravity=false; // if you don’t need gravity along x or y axis 
world.applyDamping=false; // not sure if you need this?
world.islandSplit=false; // since you have a top-down type of game with few contacts, this might save you a run of the UnionFind algorithm
world.emitImpactEvent=false; // unless you use it
world.broadphase.sortAxis=0; // 0 means x and 1 means y. Choose the axis on which your bodies are more spread out along.
world.solver.iterations=3; // this is default 10, you might want to decrease it. Just check if your collisions work OK after you change it.

如果您想充分利用您的服务器,您还应该考虑您使用的技术堆栈。运行 JavaScript 物理引擎的 Node.js 将使用大量 RAM 并在垃圾收集上浪费 CPU 周期。例如,如果您将切换到 C/C++ 中的 Box2d,并且可能直接使用 libuv 而不是使用 Node.js,那么您可以将性能提高一个很好的因素。

【讨论】:

  • 谢谢!今晚晚些时候我会试试这个。感谢您的帮助,感谢您提供的出色引擎!我想避免使用 Box2d,但我想我们会看到的。
猜你喜欢
  • 1970-01-01
  • 2017-10-03
  • 2018-05-12
  • 1970-01-01
  • 2013-10-18
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多