Об'єкт масивів чи масив об'єктів?


13

Я роблю сим-керуючу гру, щось в руслі американських американських магнетів. Я хочу знати, який найкращий спосіб структурувати свої світові об’єкти - це максимізувати продуктивність.

Скажімо, у мене в грі 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....

Або я повністю відзначився?


Досить цікаве запитання, тим більше, що в 2013 році, через десяток років після появи RCT, ідея створити 5000 видимих, незалежних НПС у світі виявиться абсолютно неможливою (незважаючи на розвиток технологій)
Katana314

Відповіді:


15

Поширена термінологія - це "структура масивів" (SOA) та "масив структур" (AOS), які походять з C і найчастіше їх сприймають з точки зору роботи SIMD.

Зазвичай AOS-підхід швидше, якщо його застосовувати належним чином, але з SOA, як правило, легше працювати (і, отже, оптимізує для більш важливої ​​якості - час розробки).

SOA, особливо на Java, означає, що ваші дані можуть залишатися щільно запакованими в пам'ять. Ви можете переглядати властивості та очікувати, що кеш процесора і таке залишаться щасливими. З AOS, особливо на Java, кожен об'єкт в кінцевому підсумку виділяється "десь" в пам'яті. Ітерація над об'єктами потенційно може зірвати кеш вашого процесора.

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


1
У третьому абзаці ви маєте на увазі посилання на AOS двічі? Зауваження здаються суперечливими ...
ali_goes_oosh

Вибачте, виправили це.
Шон Міддлічч

4

Немає причини, щоб у вас не було обох, використовуючи шаблон "Фасад" для перекладу з одного інтерфейсу на інший базове представлення. Наприклад, використовуючи терміни 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().


-1

Створіть об’єкти та зберігайте їх у масиві! Створення масивів голоду та спраги може заощадити трохи місця та працювати швидше в деяких простих ситуаціях, але це не є OOP. Java та OOP зроблять багато для вас, якщо ви дасте їм шанс. Для дійсно простої гри ваш другий приклад може спрацювати чудово, але навіть тоді ви повинні практикувати свої навички ОО. Ваш перший підхід буде добре працювати для вас незалежно від того, наскільки велика, складна та волохата ваша програма.

Подумайте про всі часи, коли буде корисно повернути Personоб’єкт із запиту. Хто надіслав це повідомлення? наприклад. Дуже багато методів, які ви пишете, хочуть знати, з ким вони мають справу. І у вас буде маса методів, які непогано впишуться у належний Personклас. Якщо Personстатичний або одинарний, куди ви ставите методи, які діють на окремих людей?

Якщо ви коли-небудь будете робити багатопотоковість - і з 5000 користувачами вас можуть підштовхнути - ви знайдете екземпляр батьків для кожного користувача набагато більш практичним.

(І цей масив людей: дотримуйтесь цього, але в якийсь момент ви захочете інших пристроїв зберігання даних. Карточка якась, щоб ви могли знайти людей по імені. І, можливо, кілька списків з різними клавішами, і, ймовірно, грона списки кожного короткого, щоб бути масивами чи пов'язаними списками.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.