在线游戏机器人性能

Online game bot performance

我正在为在线动态游戏创建机器人。在这种情况下,动态意味着游戏中的英雄可以四处移动,移动时背景会发生变化。 monsters 等全局变量在移动时也会动态变化。

我的机器人正在使用 puppeteer。因为我需要这个怪物对象,所以我有功能可以每 2 - 3 秒从页面上下文中获取这些怪物(随机化以防检测)。

这个解决方案远非完美。两个主要缺点是:

为了解决第一个问题,我可以执行每次杀死一个怪物后下载怪物的功能。另一方面,第二个缺点会更严重,因为我会执行更多已经很慢的怪物。

这一切都涉及到第二个问题,即性能。你可能会问我怎么知道性能不好?

英雄移动时相对流畅,但在下载怪物时我看到微延迟,比如第二个英雄停止的一部分。这真的可能有 100 毫秒的滞后,但我可以用肉眼看到它,如果我更频繁地执行获取怪物,这个滞后会变得更强(要清楚 - 滞后不会更长但更频繁)。

从全局下载对象 window 很长。原因是游戏维护者开发了它,所以 monsters 在大对象 npc 中,它包含仪表板中的所有内容,甚至包含空元素,所以这个 npc 对象的总量介于100k-200k 元素。我正在做很多过滤器以获得我关心的最终怪物数据。

我会展示我是如何得到这些怪物的。所以我执行了 3 个异步函数:

const allNpc = await getAllNpc(page);
let monsters = await filterMonsters(page, allNpc, monstersToHunt);
monsters.hunt = await deleteAvoidedMonsters(page, monsters.hunt, monstersToOmit);

第一个getAllNpc只得到整个npc对象(我上面提到的这个大的)

return await page.evaluate(() => {
    if(window.g) return g.npc;
});

第二个功能过滤实际怪物和我想从npc杀死的怪物:

return new Promise((resolve, reject) => {
    const validNpc = allNpc.filter(el => !!el);
    const allMonsters = validNpc.filter(e => e.lvl !== 0);

    const names = new Set(monstersNames);
    const huntMonsters = validNpc
        .filter(it => names.has(it.nick))
        .map(({ nick, x, y, grp, id }) => ({ nick, x, y, grp, id }));

    resolve({all: allMonsters, hunt: huntMonsters});
});

我在这里使用 Set 来摆脱 O(n) / O(n^2) 算法,我认为这是我可以用 javascript 实现的最快速度。第三个功能与这个相同,但额外过滤了我想避免的特殊怪物。

现在我的问题是:

一段时间后我意识到 bot 是 "lagging" 因为我将这个巨大的 g.npc 数组作为参数传递给函数。我的意思是我从 getAllNpc 解析它然后将它传递给 filterMonsters.

当我更改它时,我在页面上下文中的评估脚本中执行 .filter in getAllNpc,然后解析和传递具有数亿而不是数百万元素的数组,它更快并且不会造成任何延迟或冻结。