python dod oop

Что такое DOD, и почему он быстрее OOP?

Святослав Чуев

Ст. лейтенант

DOD/DOP или Data-Oriented Design - это паттерн для хранения/обработки данных вашего приложения. DOD отличается от OOP тем, что вместо создания отдельных объектов, внутри самих объектов используются массивы. Зачем? DOD ускоряет вашу программу! Ниже - пример использования и объяснение.


Почему DOD быстрее OOP?

Давайте посмотрим как располагаются данные в 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 не переключается между типами, а делает все по-очередно, ускоряя весь процесс.


1 message

Александр Вититнев

хмм