Объект из массивов или массив объектов?

13

Я делаю симулятор управления, что-то вроде Roller Coaster Tycoon. Я хочу знать, как лучше всего структурировать объекты моего мира, чтобы максимизировать производительность.

Допустим, в моей игре 5000 человек, которых я мог бы:

Создайте объект и сохраните его в массиве так;

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....

Или я полностью не в курсе?

ali_goes_oosh
источник
Довольно интересный вопрос, особенно с учетом того, что в 2013 году, спустя более десятка лет после появления RCT, идея иметь 5000 видимых независимых NPC в мире казалось бы совершенно невозможной (несмотря на достижения в области технологий)
Katana314

Ответы:

15

Общая терминология - это «структура массивов» (SOA) и «массив структур» (AOS), которые берутся из C и чаще всего рассматриваются в терминах работы SIMD.

Как правило, подход AOS является более быстрым, если используется надлежащим образом, но с SOA обычно легче работать (и, следовательно, оптимизируется для более важного качества - времени разработки).

SOA, особенно в Java, означает, что ваши данные могут оставаться плотно упакованными в памяти. Вы можете перебирать свойства и ожидать, что кэш процессора и тому подобное останутся довольными. В AOS, особенно в Java, каждый объект размещается «где-то» в памяти. Итерирование по объектам может сильно перегрузить кэш вашего процессора.

В конце концов, я бы выбрал тот подход, который вы найдете проще всего. Ваше время разработки гораздо более ценно, чем то, поддерживает ли ваша игра 10-летние ПК или только 9-летние ПК (маловероятно, что вы будете делать что-либо, требующее новейшего оборудования).

Шон Миддледич
источник
1
В третьем абзаце вы имеете в виду сослаться на AOS дважды? Комментарии кажутся противоречивыми ...
ali_goes_oosh
Извините, исправил это.
Шон Мидлдич
4

Нет никакой причины, по которой вы не можете использовать оба, используя шаблон Facade для перевода из одного интерфейса в другое базовое представление. Например, используя термины Шона 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]; }
}

Таким образом, вы можете свободно выбирать между формой, которую вам удобно использовать , в качестве интерфейса разработчика, по сравнению с любой лучшей реализацией по любой причине, включая соображения эффективности / кэширования.

Еще одним преимуществом для фасада является то, что он очень естественно ведет к шаблону Flyweight , где вы используете интерфейс для представления гораздо большего количества людей, чем на самом деле в памяти. Например, возможно, у вас есть роботы-покровители, которые никогда не хотят пить; тогда вы можете поместить этот особый случай в свой 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().

congusbongus
источник
-1

Создавайте объекты и храните их в массиве! Создание массивов для голода и жажды может сэкономить немного места и работать быстрее в некоторых простых ситуациях, но это не ООП. Java и ООП сделают много для вас, если вы дадите им шанс. Для действительно простой игры ваш второй пример может работать хорошо, но даже тогда вы должны практиковать свои навыки ОО. Ваш первый подход будет работать хорошо для вас, независимо от того, насколько масштабной, сложной и сложной будет ваша программа.

Подумайте, сколько раз будет полезно вернуть Personобъект из запроса. Кто отправил это сообщение? например. Многие методы, которые вы пишете, захотят узнать, с кем они имеют дело. И у вас будет много методов, которые будут хорошо вписываться в правильный Personкласс. Если Personстатический или одиночный, где вы размещаете методы, которые воздействуют на отдельных людей?

Если вы когда-либо выполняете многопоточность - и с 5000 пользователей вы можете быть втянуты в нее - вы найдете экземпляр Parent для каждого пользователя гораздо более практичным.

(И этот массив людей: придерживайтесь его сейчас, но в какой-то момент вам понадобятся другие устройства хранения. Карта какого-то рода, чтобы вы могли найти людей по имени. И, возможно, несколько списков с разными ключами, и, вероятно, связки перечисляет каждый достаточно короткий, чтобы быть массивами или связанными списками.)

RalphChapin
источник