【问题标题】:Performance - should I use both Arrays and Objects for huge list?性能 - 我应该同时使用数组和对象来获得巨大的列表吗?
【发布时间】:2017-06-12 04:48:57
【问题描述】:

到目前为止,我的服务器已经处理了大量的实体数组

主要是在entities上执行一个for循环每秒x次,检查一个实体是否在另一个实体的范围内(每个实体都有一个数组entitiesInScope)通过执行entitiesInScope.indexOf(entity),这是我程序的最大成本。

for (var i = 0; i < entities.length; i++) {
    var entity = entities[i];
    for (var j = 0; j < entities.length; j++) {
        var checkEntity = entities[j];
        var idx = entity.entitiesInScope.indexOf(checkEntity);
        if (idx >= 0) {
            if (!check(checkEntity.state, entity.state)) {
                entity.removeEntityInScope(idx);
                //... remove: send checkEntity.id
            } 
        } else {
            if (check(checkEntity.state, entity.state)) {
                entity.addEntityInScope(checkEntity);
                //... add: send checkEntity.id, checkEntity.state
            }
        }
    }
}

(我通过不对所有实体进行第二次循环来优化它,但这不是重点)

但是,我发现 Object 的 hasOwnPropertymuch faster 而不是 indexOf。另一方面,我也做了很多推和拼接。所以如果我添加一个实体对象,我也应该使用 delete (perf?)。

我应该:

-添加一个id为实体键的对象,使用hasOwnProperty(entity.id),如果为真则允许使用indexOf?

-添加一个带有实体键的对象,以使用hasOwnProperty(entity.id)(内存浪费)?

-继续数组

【问题讨论】:

  • 为什么不直接遍历entitiesInScope 数组而不是第二个循环?
  • @juvian 实际上,有一个物理循环更新实体的状态(位置,...),还有一个广播循环(以前的代码),其中 entityInScope 被更新(添加/remove) 对每个实体进行一些检查。
  • @Miyud 在这种情况下使用对象而不是数组并使用 hasOwnProperty + delete 会更有效。但是仅遍历entitiesInScope 会更好...(您需要向后遍历它才能删除而不会弄乱索引)

标签: javascript arrays performance object


【解决方案1】:

我建议迭代 entityInScope 以更新或删除那里的实体,因为您已经知道这种方式的索引,如果您向后遍历它,您可以删除项目而不会弄乱索引。

至于添加缺少的实体,我会在对象中标记已经在实体范围内的实体以便快速查找,然后遍历实体并添加缺少的实体。代码将与此类似:

for (var i = 0; i < entities.length; i++) {
    var entity = entities[i];
    var alreadyInScope = {}

    for (var j = entity.entitiesInScope.length - 1; j >= 0; j--) {
        var checkEntity = entity.entitiesInScope[j];

        if (!check(checkEntity.state, entity.state)) {
           var id = entity.entitiesInScope.splice(j, 1).id
        } else {
            alreadyInScope[checkEntity.id] = true;
        }
    }

    for (var j = 0; j < entities.length; j++) {
        if (alreadyInScope.hasOwnProperty(entities[j].id) == false) {
            entity.entitiesInScope.push(entities[j])
        }
    }

}

【讨论】:

  • 谢谢。我认为您的意思是 splice(-1,1) 删除最后一个元素。顺便说一句,前向拼接(j,1)是否存在性能差异,或者只是为了用户方便?
  • @Miyud 我的错,splice(j, 1) 是正确的选择
  • @Miyud 如果您在 alreadyInScope 中有许多实体并且您通常删除超过 10 个,将不会删除的实体添加到临时数组并在末尾可能会更有效循环用临时数组替换 alreadyInScope
猜你喜欢
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2012-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
相关资源
最近更新 更多