数组对象还是对象数组?


13

我正在制作一个管理模拟游戏,类似过山车大亨。我想知道构造我的世界对象的最佳方法是什么,以便最大化性能。

假设我的游戏中有5,000人,我可以:

创建一个对象并将其存储在数组中,如下所示:

class person() {
    this.x = 0;
    this.y = 0;
    this.thirst = 15;
    this.hunger = 15;
    // etc.. add methods:
    public findPath(int destX, int destY) {
    // and so on
    }

    people = new person[5000];

for (int = 0; i < 5000; i++) {
    people[i] = new person;
    }

还是应该使人的对象包含很多表示人的属性的字节数组,如下所示:

class people() {
    this.hunger = new byte[5000]
    this.thirst = new byte[5000]

    getThirst(int i) {
        return this.thirst[i]
        }

 // and so on....

还是我完全不合时宜?


非常有趣的问题,尤其是自2013年以来,在RCT诞生十多年之后,在世界上拥有5000个可见的独立NPC的想法似乎是完全不可能的(尽管技术进步)
Katana314 2013年

Answers:


15

通用术语是“数组的结构”(SOA)和“结构的数组”(AOS),它们来自C,在SIMD工作中最为常见。

通常,如果使用得当,AOS方法会更快,但是SOA往往更易于使用(因此针对更重要的质量-开发时间进行了优化)。

SOA,尤其是在Java中,意味着您的数据可以紧密地存储在内存中。您可以遍历属性,并期望CPU高速缓存保持满意。使用AOS,尤其是在Java中,每个对象最终都会在内存中的“某处”分配。遍历对象可能会严重破坏CPU缓存。

最后,我将采用您认为最容易使用的任何方法。您的开发时间比您的游戏支持10年的PC或仅9年的PC有价值得多(您几乎不可能做任何需要最新硬件的事情)。


1
在您的第三段中,您是指两次提及AOS吗?评论似乎矛盾……
ali_goes_oosh 2013年

抱歉,将其修复。
肖恩·米德迪奇

4

使用Facade模式将一个接口转换为另一种底层表示形式,没有理由您不能同时拥有这两者。例如,使用Sean的SOA / AOS术语:

SOA外观

class PeopleFacade {
    Person persons[5000];
    getThirst(int i) { return persons[i].thirst; }
}

AOS门面

class People { int thirsts[5000]; } people;
class PersonFacade {
    int i;
    getThirst() { return people.thirsts[i]; }
}

通过这种方式,您可以自由选择自己喜欢使用的表单(作为开发者界面),还是出于各种原因(包括效率/缓存原因)而最好的实现方式。

外墙的另一个优点是,它非常自然地导致了“ 举重”模式,您可以在其中使用一个界面来表示比实际内存中更多的人。例如,也许您有从来不渴的机器人顾客。那么您可以将这种特殊情况放入您的中PersonFacade,该界面的用户就不必了解机器人了:

class People { int nonRobotThirsts[1000]; } people;
class PersonFacade {
    int i;
    bool isRobot;
    getThirst() {
        if (isRobot)
            return 0;
        else
            return people.nonRobotThirsts[i];
    }
}

...或使用更多的面向对象方法,您将拥有一个单独的Robot类,其行为与完全相同,Person除了getThirst()


-1

创建对象并将它们存储在数组中!饥饿口渴而制作数组可以节省一些空间,并且在某些简单情况下可以更快地运行,但这不是OOP。如果有机会,Java和OOP将为您做很多事情。对于一个非常简单的游戏,您的第二个示例可能很好用,但是即使那样,您也应该练习OO技能。无论您的程序有多大,复杂和繁琐,第一种方法都将对您有效。

想想所有的时间,Person从查询取回对象将很方便。 发送了此消息?例如。您编写的许多方法都想知道他们正在与打交道。而且您将拥有许多非常适合于适当Person类的方法。如果Person是静态的还是单例的,您在哪里放置对单个人起作用的方法?

如果你曾经做多线程-与5000级的用户,你可能会被推到它-你会发现每个用户父实例很多更实用。

(还有很多人:现在就坚持使用它,但是在某些时候,您将需要其他存储设备。某种地图,以便您可以按名称查找人。也许还有几个具有不同键的列表,也许是一堆列出每个足够短的数组或链表。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.