Прежде всего, не путайте это с дизайном, управляемым данными.
Я понимаю, что Data Oriented Design - это организация ваших данных для эффективной обработки. Особенно в отношении пропусков кэша и т. Д. С другой стороны, Data Driven Design - это то, что позволяет данным контролировать поведение многих ваших программ (очень хорошо описано в ответе Эндрю Кейта ).
Допустим, в вашем приложении есть объекты-шарики со свойствами, такими как цвет, радиус, упругость, положение и т. Д.
Объектно-ориентированный подход
В ООП вы бы описали шары следующим образом:
class Ball {
Point position;
Color color;
double radius;
void draw();
};
И тогда вы создадите коллекцию шаров, как это:
vector<Ball> balls;
Ориентированный на данные подход
Однако в Data Oriented Design вы с большей вероятностью напишите такой код:
class Balls {
vector<Point> position;
vector<Color> color;
vector<double> radius;
void draw();
};
Как вы можете видеть, больше нет единой единицы, представляющей один шар. Объекты шара существуют только неявно.
Это может иметь много преимуществ с точки зрения производительности. Обычно мы хотим выполнять операции на нескольких шарах одновременно. Аппаратные средства обычно хотят, чтобы большие непрерывные порции памяти работали эффективно.
Во-вторых, вы можете выполнять операции, которые затрагивают только часть свойств шариков. Например, если вы комбинируете цвета всех шаров различными способами, то вы хотите, чтобы ваш кеш содержал только информацию о цвете. Однако, когда все свойства шара сохранены в одной единице, вы также включите все остальные свойства шара. Даже если они вам не нужны.
Пример использования кэша
Скажем, каждый шар занимает 64 байта, а точка занимает 4 байта. Слот для кеша занимает, скажем, 64 байта. Если я хочу обновить позицию 10 шаров, я должен вытянуть 10 * 64 = 640 байт памяти в кеш и получить 10 промахов в кеше. Однако, если я могу работать с позициями шаров как с отдельными единицами, это займет всего 4 * 10 = 40 байт. Это помещается в одну выборку из кэша. Таким образом, мы получаем только 1 промах кэша для обновления всех 10 шаров. Эти числа являются произвольными - я предполагаю, что блок кэша больше.
Но это показывает, как разметка памяти может серьезно повлиять на попадания в кэш и, следовательно, на производительность. Это только увеличится в важности, поскольку разница между скоростью процессора и оперативной памяти увеличивается.
Как расположить память
В моем примере с мячом я сильно упростил проблему, потому что обычно для любого обычного приложения вы, вероятно, будете обращаться к нескольким переменным вместе. Например, положение и радиус, вероятно, будут часто использоваться вместе. Тогда ваша структура должна быть:
class Body {
Point position;
double radius;
};
class Balls {
vector<Body> bodies;
vector<Color> color;
void draw();
};
Причина, по которой вам следует это сделать, заключается в том, что если данные, используемые вместе, помещаются в отдельные массивы, существует риск, что они будут конкурировать за одни и те же слоты в кэше. Таким образом, загрузка одного выбросит другого.
Таким образом, по сравнению с объектно-ориентированным программированием, классы, которые вы в итоге делаете, не связаны с сущностями в вашей ментальной модели проблемы. Поскольку данные объединяются в единое целое на основе использования данных, у вас не всегда будут разумные имена для ваших классов в Data Oriented Design.
Отношение к реляционным базам данных
Концепция Data Oriented Design очень похожа на то, как вы думаете о реляционных базах данных. Оптимизация реляционной базы данных может также включать более эффективное использование кеша, хотя в этом случае кеш - это не кеш процессора, а страницы в памяти. Хороший конструктор баз данных, скорее всего, также разделит редко используемые данные на отдельные таблицы, а не создаст таблицу с огромным количеством столбцов, в которых когда-либо использовались только несколько столбцов. Он также может выбрать денормализацию некоторых таблиц, чтобы к данным не приходилось обращаться из нескольких мест на диске. Как и в случае с Data-Oriented Design, этот выбор делается при рассмотрении того, что такое шаблоны доступа к данным и где узкое место в производительности.