DOD/DOP или Data-Oriented Design - это паттерн для хранения/обработки данных вашего приложения. DOD отличается от OOP тем, что вместо создания отдельных объектов, внутри самих объектов используются массивы. Зачем? DOD ускоряет вашу программу! Ниже - пример использования и объяснение.
Давайте посмотрим как располагаются данные в OOP: вот у нас есть класс с полями ABC, если нам был бы нужен массив из 5 этих объектов то в оперативной памяти это бы выглядело так: ABCABCABCABCABC.
Выглядит вполне нормально, но вы представьте: вы готовите пирожки, вам нужно сначала раскатать тесто, потом положить начинку и сформировать их и затем пожарить. Для одного пирожка это конечно то что мы бы сделали, но если нужно сделать 10, а может 100? Очень трудно переключатся между действиями, не проще ли сделать 100 заготовок теста, положить во всех них начинку и пожарить их всех одновременно?
Проще, и очевидно намного быстрее. Так работает DOD, вместо массива объектов у вас, объект массивов, один объект бы выглядел как и в OOP ABC, но когда объектов становится 2 или больше видна разница: AAAAABBBBBCCCCC. Как в аналогии с пирожками видно что память разложена поочередно, а значит процессору не придется работать с разными типами данных на каждой новой задаче.
import random
import time
class Player:
def __init__(self):
self.x = 0
self.y = 0
self.mana = 0
def __repr__(self):
return "x {} y {} mana {}".format(self.x, self.y, self.mana)
def update(self):
self.x += 1
self.y = self.x*2
self.mana = int(random.random()*20)
class Players:
def __init__(self, count):
self.count = count;
self.x = []
self.y = []
self.mana = []
for i in range(count):
self.x.append(0);
self.y.append(0);
self.mana.append(0);
def __repr__(self, n):
return "x {} y {} mana {}".format(self.x[n], self.y[n], self.mana[n])
def update(self):
for i in range(self.count):
self.x[i] += 1
self.y[i] = self.x[i]*2
self.mana[i] = int(random.random()*20)
count = 10000;
playersDOD = Players(count);
playersOOP = []
for i in range(count):
playersOOP.append(Player())
start = time.clock()
playersDOD.update()
print("DOD", time.clock()-start)
start = time.clock()
for i in playersOOP:
i.update()
print("OOP", time.clock()-start)
Результат:
DOD 0.003572999999999993
OOP 0.0043300000000000005
Как мы можем видеть, DOD работает на 33% быстрее!
DOD можно и желательно использовать в высоконагруженных программах: видеоигры, движки и тд. DOD не переключается между типами, а делает все по-очередно, ускоряя весь процесс.