Apa itu desain berorientasi data?


156

Saya sedang membaca artikel ini , dan orang ini terus berbicara tentang bagaimana semua orang dapat memperoleh manfaat besar dari pencampuran dalam desain berorientasi data dengan OOP. Dia tidak menunjukkan contoh kode.

Saya mencari di Google dan tidak dapat menemukan informasi nyata tentang apa ini, apalagi sampel kode. Adakah yang akrab dengan istilah ini dan dapat memberikan contoh? Apakah ini mungkin kata yang berbeda untuk sesuatu yang lain?


7
Artikel yang di pengembang game sekarang tersedia di mudah dibaca dalam bentuk blog: gamesfromwithin.com/data-oriented-design
Edmundito

58
Apakah kalian pernah mencari sesuatu di Google, menemukan pertanyaan SO yang bagus dan ditargetkan, dan kemudian menyadari bahwa Andalah yang menanyakannya bertahun-tahun yang lalu?
ryeguy

1
Berikut ini adalah agregat konten DOD di web
legends2k

14
@ryeguy, saya punya pertanyaan, mencari di Google, menemukan pertanyaan SO yang bagus, dan kemudian menyadari bahwa saya menjawabnya bertahun-tahun yang lalu.
Michael Deardeuff

4
Saya telah mencari sesuatu di Google dan menemukan pertanyaan SO yang bagus dan coba tebak? Bukan aku yang bertanya atau yang menjawab :)
Nadjib Mami

Jawaban:


288

Pertama-tama, jangan bingung dengan desain berbasis data.

Pemahaman saya tentang Desain Berorientasi Data adalah tentang mengatur data Anda untuk pemrosesan yang efisien. Khususnya sehubungan dengan kesalahan cache dll. Disain Data Driven Desain di sisi lain adalah tentang membiarkan data mengontrol banyak perilaku program Anda (dijelaskan dengan sangat baik oleh jawaban Andrew Keith ).

Katakanlah Anda memiliki objek bola dalam aplikasi Anda dengan properti seperti warna, jari-jari, goyang, posisi dll.

Pendekatan Berorientasi Objek

Di OOP Anda akan menggambarkan bola seperti ini:

class Ball {
  Point  position;
  Color  color;
  double radius;

  void draw();
};

Dan kemudian Anda akan membuat koleksi bola seperti ini:

vector<Ball> balls;

Pendekatan Berorientasi Data

Dalam Desain Berorientasi Data, Anda cenderung menulis kode seperti ini:

class Balls {
  vector<Point>  position;
  vector<Color>  color;
  vector<double> radius;

  void draw();
};

Seperti yang Anda lihat tidak ada lagi satu unit yang mewakili satu Bola lagi. Objek bola hanya ada secara implisit.

Ini dapat memiliki banyak keuntungan, kinerja bijaksana. Biasanya kami ingin melakukan operasi pada banyak bola secara bersamaan. Perangkat keras biasanya ingin potongan memori besar terus menerus beroperasi secara efisien.

Kedua, Anda mungkin melakukan operasi yang hanya memengaruhi sebagian dari properti bola. Misalnya, jika Anda menggabungkan warna semua bola dengan berbagai cara, maka Anda ingin cache Anda hanya berisi informasi warna. Namun ketika semua properti bola disimpan dalam satu unit Anda akan menarik semua properti bola lainnya juga. Meskipun Anda tidak membutuhkannya.

Contoh Penggunaan Cache

Katakanlah setiap bola membutuhkan 64 byte dan sebuah Point membutuhkan 4 byte. Slot cache mengambil, katakanlah, 64 byte juga. Jika saya ingin memperbarui posisi 10 bola, saya harus menarik 10 * 64 = 640 byte memori ke dalam cache dan mendapatkan 10 cache misses. Namun jika saya dapat menggunakan posisi bola sebagai unit terpisah, itu hanya akan memakan waktu 4 * 10 = 40 byte. Itu cocok untuk satu cache cache. Jadi kita hanya mendapatkan 1 cache miss untuk memperbarui semua 10 bola. Angka-angka ini sewenang-wenang - Saya menganggap blok cache lebih besar.

Tapi itu menggambarkan bagaimana tata letak memori dapat memiliki efek parah pada hit cache dan dengan demikian kinerja. Ini hanya akan semakin penting karena perbedaan antara kecepatan CPU dan RAM melebar.

Cara tata letak memori

Dalam contoh bola saya, saya banyak menyederhanakan masalah, karena biasanya untuk aplikasi normal apa pun Anda mungkin akan mengakses beberapa variabel secara bersamaan. Misalnya posisi dan jari-jari mungkin akan sering digunakan bersama. Maka struktur Anda harus:

class Body {
  Point  position;
  double radius;
};

class Balls {
  vector<Body>  bodies;
  vector<Color>  color;

  void draw();
};

Alasan Anda harus melakukan ini adalah bahwa jika data yang digunakan bersama ditempatkan dalam array yang terpisah, ada risiko bahwa mereka akan bersaing untuk slot yang sama di cache. Jadi memuat satu akan membuang yang lain.

Jadi dibandingkan dengan pemrograman Berorientasi Objek, kelas yang Anda buat akhirnya tidak terkait dengan entitas dalam model mental masalah Anda. Karena data disatukan berdasarkan penggunaan data, Anda tidak akan selalu memiliki nama yang masuk akal untuk memberikan kelas Anda dalam Desain Berorientasi Data.

Hubungan dengan database relasional

Pemikiran di balik Desain Berorientasi Data sangat mirip dengan bagaimana Anda berpikir tentang database relasional. Mengoptimalkan basis data relasional juga dapat melibatkan penggunaan cache lebih efisien, meskipun dalam hal ini, cache bukan cache CPU tetapi halaman dalam memori. Perancang basis data yang baik juga kemungkinan akan membagi data yang jarang diakses ke dalam tabel terpisah daripada membuat tabel dengan jumlah kolom yang sangat banyak hanya beberapa kolom yang pernah digunakan. Dia mungkin juga memilih untuk mendenormalkan beberapa tabel sehingga data tidak harus diakses dari beberapa lokasi pada disk. Sama seperti dengan Desain Berorientasi Data, pilihan ini dibuat dengan melihat apa pola akses data dan di mana hambatan kinerja.


4
Terima kasih untuk ini, Anda menjelaskannya dengan sangat baik.
ryeguy

4
kata baik; Saya hanya punya satu pertanyaan. Katakanlah kita memiliki struktur struct balls {vector<vec3> pos; vector<vec3> velocity;}, tidak akan memperbarui posisi setiap bola benar-benar menghancurkan cache karena Anda akan bergerak bolak-balik antara vektor kecepatan dan vektor posisi (ya mesin modern dan cache-garis dan semua itu, ini adalah juga hanya ilustrasi)?
falstro

14
Itu mungkin. Tapi ingat seluruh array pos tidak akan ditarik sekaligus. Hanya satu baris cache, dan mungkin beberapa prefetching. Begitu juga dengan kecepatan. Jadi bagi mereka untuk saling membuang satu sama lain masing-masing potongan pos dan vektor harus memetakan ke cacheline yang sama. Itu tentu saja bisa terjadi, itulah sebabnya rekomendasi adalah untuk meletakkan variabel yang digunakan bersama dalam sebuah struct. Jadi mis. Kecepatan dan pos akan berada dalam satu vektor sedangkan warna akan berada di vektor lain.
Erik Engheim

1
@roe Anda harus mengelompokkan properti bersama, yang diakses bersama. Antara properti tidak boleh ada ketergantungan sama sekali. Jadi struktur ini akan lebih baik struct balls { vector<color> colors; vector<body> bodies; /* contains position and velocity */ }.
danijar

2
@danijar Saya memperbarui penjelasan dengan saran Anda. Saya bisa saja mengatakan lebih banyak tentang ini, tetapi itu akan benar-benar berubah menjadi sebuah artikel.
Erik Engheim

18

Mike Acton memberikan ceramah publik tentang desain berorientasi data baru-baru ini:

Ringkasan dasar saya tentang hal itu adalah: jika Anda menginginkan kinerja, maka pikirkan aliran data, temukan lapisan penyimpanan yang kemungkinan besar akan bermasalah dengan Anda dan optimalkan untuk itu dengan keras. Mike berfokus pada kesalahan cache L2, karena dia melakukan realtime, tapi saya membayangkan hal yang sama berlaku untuk database (disk membaca) dan bahkan Web (permintaan HTTP). Ini cara yang berguna untuk melakukan pemrograman sistem, saya pikir.

Perhatikan bahwa itu tidak membebaskan Anda dari memikirkan algoritma dan kompleksitas waktu, itu hanya memusatkan perhatian Anda untuk mencari tahu jenis operasi yang paling mahal yang kemudian harus Anda targetkan dengan keterampilan CS gila Anda.


14

Saya hanya ingin menunjukkan bahwa Noel berbicara secara spesifik tentang beberapa kebutuhan spesifik yang kita hadapi dalam pengembangan game. Saya kira sektor lain yang melakukan simulasi lunak real-time akan mendapat manfaat dari ini, tetapi tidak mungkin menjadi teknik yang akan menunjukkan peningkatan nyata untuk aplikasi bisnis umum. Pengaturan ini adalah untuk memastikan bahwa setiap kinerja terakhir diperas dari perangkat keras yang mendasarinya.


Sepakat. Beberapa area lain di mana desain berorientasi data adalah signifikan adalah: perangkat keras dan firmware untuk perangkat bandwidth tinggi (misalnya jaringan atau penyimpanan); komputasi ilmiah skala besar (misalnya simulasi cuaca, pelipatan protein), pemrosesan sinyal (misalnya audio, gambar, video), kompresi data. Ini jatuh di bawah "Ilmu Komputasi dan Rekayasa" yang kadang-kadang ditawarkan sebagai jurusan terpisah dari Ilmu Komputer yang lebih khas.
rwong

-3

Desain berorientasi data adalah desain di mana logika aplikasi dibangun dari kumpulan data, bukan algoritma prosedural. Sebagai contoh

pendekatan prosedural.

int animation; // this value is the animation index

if(animation == 0)
   PerformMoveForward();
else if(animation == 1)
  PerformMoveBack();
.... // etc

pendekatan desain data

typedef struct
{
   int Index;
   void (*Perform)();
}AnimationIndice;

// build my animation dictionary
AnimationIndice AnimationIndices[] = 
  {
      { 0,PerformMoveForward }
      { 1,PerformMoveBack }
  }

// when its time to run, i use my dictionary to find my logic
int animation; // this value is the animation index
AnimationIndices[animation].Perform();

Desain data seperti ini mempromosikan penggunaan data untuk membangun logika aplikasi. Lebih mudah dikelola terutama dalam video game yang mungkin memiliki ribuan jalur logika berdasarkan animasi atau faktor lainnya.


14
Ini sebenarnya tidak benar. Anda membingungkan desain berorientasi data dengan desain berbasis data. Saya melakukan hal yang sama sampai saya membaca artikel Noel dan menyadari dia berbicara tentang sesuatu yang sama sekali berbeda.
Erik Engheim

12
Juga, Indice bukan kata. Ada "indeks" dan "indeks" dan beberapa bahkan memaafkan "indeks", tetapi "indice" tidak pernah benar.
Baxissimo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.