Apakah ada cara yang lebih baik untuk membuat sistem acara?

9

Sistem Acara luar biasa, mereka membuat kode sangat jinak dan benar-benar memungkinkan terciptanya permainan yang dinamis melalui komunikasi objek dan loop game yang mudah. Saya mengalami kesulitan dengan efisiensi implementasi saya saat ini. Saat ini sedikit optimisasi saya memisahkan daftar objek ke dalam peristiwa yang mereka respon telah melakukan keajaiban, tetapi harus ada lebih banyak yang bisa saya lakukan.

Saat ini saya memiliki dua metode:

  1. Sederhana: semua objek ditambahkan ke vektor ketika suatu peristiwa dikirim semua objek dikirimi peristiwa melalui metode handle_event ()

  2. Lebih kompleks: Saya memiliki peta dengan string sebagai kunci dan int sebagai nilainya. Ketika suatu jenis peristiwa ditambahkan, itu ditambahkan ke peta ini, dengan int hanya ditambahkan (harus ada cara yang lebih baik)
    vektor vektor objek kemudian mendorong kembali vektor baru untuk menangani jenis peristiwa tersebut.
    Ketika suatu peristiwa dipanggil, panggil saja int yang terkait dalam map eventTypes ke jenis di dalam vektor vektor objek dan kirimkan peristiwa itu ke setiap objek yang menangani jenis peristiwa itu.

Metode pertama ini cukup lambat (jelas) untuk banyak objek, tetapi cukup cepat untuk sangat sedikit objek. Sedangkan metode kedua cukup cepat dengan objek besar yang ingin menangani berbagai jenis peristiwa, tetapi lebih lambat dari metode pertama per objek dengan objek yang menangani jenis peristiwa yang sama.

Apakah ada cara yang lebih cepat (lebih hemat waktu)? Apakah ada cara yang lebih cepat untuk mencari int dari tipe string? (Awalnya saya punya enum, tetapi tidak mengizinkan jenis kustom, yang diperlukan karena tingkat dinamisme yang diinginkan.)

ultifinitus
sumber
1
Ini adalah jenis dari apa yang digunakan untuk Hash Maps (atau Hash Table), string akan dikomputasi ke nomor hash yang kemudian digunakan untuk mencari langsung dalam sebuah array. en.wikipedia.org/wiki/Hash_table
Patrick Hughes
Pertanyaan yang bagus adalah: apakah ini benar-benar hambatan kinerja, atau apakah Anda hanya khawatir sebelum waktunya?
Jari Komppa
Ini sudah diimplementasikan, dan ada hambatan, ketika banyak objek digunakan. Komentar saya sebelumnya tentang kurangnya bottleneck tidak ada dalam aplikasi itu sendiri tetapi sebenarnya perbedaan kecepatan antara dua implementasi di atas di mana jumlah objek yang sama sebenarnya ditangani. Saya berharap untuk metode lain untuk menciptakan sistem acara ... Namun beberapa ide di utas ini akan meningkatkan kecepatan sedikit, terutama dalam pemuatan sistem acara (waktu muat 11-25 detik penuh dengan 100.000 objek)
ultifinitus
100K objek terdengar sangat tinggi hanya untuk permainan. Apakah ini server atau aplikasi klien pengguna akhir?
Patrick Hughes
Ini mesin saya, jadi saya benar-benar mencari fleksibilitas. Ini akan digunakan dalam aplikasi server dan aplikasi pengguna akhir (jarang yang pertama, optimasi)
ultifinitus

Jawaban:

5

Sepertinya Anda mengatakan bottleneck kinerja besar mencari ID peristiwa (bilangan bulat) dari nama string mereka. Anda bisa memproses data game Anda untuk mengonversi semua nama acara menjadi bilangan bulat sebelum menjalankan game, atau mungkin saat memuat level; maka Anda tidak perlu melakukan konversi apa pun selama bermain game.

Jika objek sering dibuat dan dihancurkan, mungkin ada banyak churn di vektor objek. Dalam hal ini Anda bisa mendapat manfaat dengan menggunakan daftar tertaut alih-alih vektor; mereka lebih cepat untuk penyisipan dan penghapusan.

Nathan Reed
sumber
Kemacetan tidak besar (untuk 100.000 objek kehilangan 0,0000076 ms / objek) tapi saya pikir ide Anda adalah ide bagus! Saya pikir saya benar-benar akan melakukan pencarian ID satu kali, dan memiliki eventID disimpan sebagai int daripada data string asli. Dan saya sebenarnya belum memikirkan daftar yang terhubung, ide bagus.
ultifinitus
1
+1 Untuk memproses ID sebelumnya. Anda juga bisa melakukannya dengan malas dengan memiliki tipe EventType yang dapat diperoleh setiap modul melalui sesuatu seperti EventType takeDamageEvent = EventSystem::CacheEventType("takeDamageEvent");. Jadikan anggota kelas statis dan Anda hanya akan memiliki satu salinan yang beredar di setiap kelas yang membutuhkannya.
michael.bartnett
2
Perhatikan bahwa menyimpan id bukan string akan membuat proses debug agak sulit. Itu selalu berguna untuk dapat melihat beberapa teks menentukan dari mana suatu objek berasal. Anda bisa setengah jalan dengan menyimpan id dan string, yang Anda simpan untuk keperluan debugging (mungkin bahkan dihapus dalam rilis rilis).
Nicol Bolas
2

Baiklah, mari kita dapatkan hal-hal sederhana terlebih dahulu. Anda memiliki ini di mapantara string (nama acara, mungkin) dan bilangan bulat (indeks pendengar acara terdaftar).

Waktu pencarian dalam mapdidasarkan pada dua hal: jumlah item di peta, dan waktu yang diperlukan untuk melakukan perbandingan antara dua kunci (mengabaikan masalah cache). Jika waktu pencarian adalah masalah, salah satu cara untuk mengatasinya adalah mengubah fungsi perbandingan dengan mengubah tipe string.

Mari kita asumsikan Anda menggunakan std::stringdan operator<untuk perbandingan. Ini sangat tidak efisien; itu perbandingan byte-bijaksana. Anda tidak peduli dengan string asli yang kurang dibandingkan; Anda hanya perlu semacam perbandingan yang memberikan urutan ketat-lemah (karena maptidak berfungsi sebaliknya).

Jadi Anda harus menggunakan string dengan panjang tetap 32 byte std::string. Saya menggunakan ini untuk pengidentifikasi. Tes perbandingan untuk string tetap ini tidak melakukan perbandingan byte-bijaksana; mereka melakukan perbandingan 32-bit (atau 64-bit) sebagai gantinya. Dibutuhkan setiap 4 byte sebagai integer yang tidak ditandatangani dan membandingkannya dengan 4 byte yang sesuai dari string lainnya. Dengan begitu, perbandingan hanya membutuhkan paling banyak 8 perbandingan. Ini memastikan pemesanan yang sangat lemah, meskipun pemesanan tidak ada hubungannya dengan data sebagai karakter.

Menyimpan string yang lebih panjang dari 31 byte (perlu karakter NULL) memotong string (tetapi dari tengah, bukan dari ujung. Saya menemukan bahwa entropi cenderung lebih besar di awal dan akhir). Dan string lebih pendek dari pad dengan karakter yang tersisa \0.

Sekarang, Anda bisa membuang mapseluruhnya dan menggunakan tabel hash. Jika Anda benar-benar memiliki lebih dari 100.000 jenis acara, ini bisa menjadi ide yang bagus. Tapi saya tidak tahu permainan di mana itu akan menjadi hal yang masuk akal.

Nicol Bolas
sumber
Jadi, Anda harus menggunakan string tetap-panjang 32-byte alih-alih std :: string. Fantastis! Saya tidak berpikir untuk mengubah tipe string.
ultifinitus
0

Untuk menjawab pertanyaan umum:

Cara Yang Lebih Baik Untuk Mengatur Sistem Acara

Tidak ada. Yang dapat Anda lakukan adalah mengidentifikasi kebutuhan spesifik yang Anda miliki untuk sistem acara Anda (mungkin ada beberapa yang berbeda) dan kemudian menggunakan alat yang tepat untuk pekerjaan yang tepat.

Saya telah menerapkan dan mencoba menyamaratakan banyak sistem acara dan saya sampai pada kesimpulan ini. Karena pengorbanan sangat berbeda jika Anda membuatnya waktu kompilasi atau waktu berjalan, jika Anda menggunakan hierarki objek atau papan tulis dll.

Cara terbaik adalah mempelajari berbagai jenis sistem acara dan kemudian Anda akan memiliki petunjuk tentang yang mana yang akan digunakan dalam hal ini.

Sekarang, jika Anda menginginkan sistem yang benar-benar paling fleksibel, terapkan sistem papan tulis (runtime) dengan properti acara yang dinamis dan Anda akan memiliki sesuatu yang sangat fleksibel tetapi mungkin sangat lambat.

Klaim
sumber