Mengapa Farseer 2.x menyimpan temporaries sebagai anggota dan tidak di tumpukan? (.BERSIH)

10

UPDATE: Pertanyaan ini mengacu pada Farseer 2.x. 3.x yang lebih baru tampaknya tidak melakukan ini.

Saya menggunakan Farseer Physics Engine cukup luas saat ini, dan saya perhatikan bahwa tampaknya menyimpan banyak tipe nilai sementara sebagai anggota kelas, dan tidak di tumpukan seperti yang diharapkan.

Ini adalah contoh dari Bodykelas:

private Vector2 _worldPositionTemp = Vector2.Zero;

private Matrix _bodyMatrixTemp = Matrix.Identity;
private Matrix _rotationMatrixTemp = Matrix.Identity;
private Matrix _translationMatrixTemp = Matrix.Identity;

public void GetBodyMatrix(out Matrix bodyMatrix)
{
    Matrix.CreateTranslation(position.X, position.Y, 0, out _translationMatrixTemp);
    Matrix.CreateRotationZ(rotation, out _rotationMatrixTemp);
    Matrix.Multiply(ref _rotationMatrixTemp, ref _translationMatrixTemp, out bodyMatrix);
}

public Vector2 GetWorldPosition(Vector2 localPosition)
{
    GetBodyMatrix(out _bodyMatrixTemp);
    Vector2.Transform(ref localPosition, ref _bodyMatrixTemp, out _worldPositionTemp);
    return _worldPositionTemp;
}

Sepertinya ini adalah optimasi kinerja dengan tangan. Tetapi saya tidak melihat bagaimana ini bisa membantu kinerja? (Jika ada yang saya pikir itu akan sakit dengan membuat benda lebih besar).

Andrew Russell
sumber

Jawaban:

6

Meskipun dalam tipe nilai .NET disimpan di tumpukan, menghasilkan biaya alokasi minimal, namun tidak menghilangkan biaya inisialisasi.

Dalam hal ini kami memiliki serangkaian fungsi menggunakan satu atau dua matriks sementara, yang akan menghasilkan inisialisasi 16-32 float per panggilan. Meskipun ini mungkin tampak tidak signifikan, jika metode yang digunakan cukup sering (katakanlah, ribuan dan ribuan kali per frame), total overhead dapat memiliki dampak yang berarti. Jika teknik seperti itu digunakan secara sistematis di semua metode seperti itu, biaya overhead yang dihilangkan bisa cukup besar.

Sementara penggunaan teknik semacam itu menghilangkan kemampuan untuk memberikan keamanan benang pada level per objek, pada umumnya tidak bijaksana untuk memberikan jaminan tersebut pada level granular seperti itu.

Jason Kozak
sumber
Apa kamu yakin akan hal itu? Satu pemikiran yang saya miliki adalah mungkin untuk menghindari memanggil konstruktor. Tetapi untuk tipe nilai Anda tidak perlu memanggil konstruktor - termasuk konstruktor tanpa parameter default - jika Anda akan mengatur semua anggota (atau meneruskannya sebagai outparameter). Saya cukup yakin seluruh poin dari aturan ini adalah agar kompiler dapat melewatkan zeroing memori itu - kan? (Apakah benar - benar lambat untuk memindahkan penunjuk tumpukan?)
Andrew Russell
Mengejutkan, bukan? Sayangnya, jika Anda memeriksa IL yang dihasilkan, matriks sementara diinisialisasi. Beberapa tes cepat menunjukkan versi temp-member ~ 10-15% lebih cepat.
Jason Kozak
1
Saya terpana . Dalam "Memahami Kinerja Kerangka XNA" (GDC2008) Shawn Hargreaves mengatakan tentang struct: "[JIT] biasanya akan mencari tahu: 'pada baris berikutnya ia segera menetapkan ketiga bidang [dari Vector3], jadi saya bahkan tidak perlu untuk menginisialisasi ke nol '" . Dari situlah info saya berasal. Tetapi saat mendengarkan lagi sekarang, dia hanya mengatakan "biasanya". Poin langsung berikutnya dalam presentasi adalah bahwa JIT berperilaku berbeda dengan debugger terpasang, mempengaruhi kinerja (bagaimana Anda menguji?). Juga: dia berbicara tentang JIT di sini, jadi mungkin IL tetap "baik" (dapat diverifikasi?).
Andrew Russell
IL diperiksa melalui Reflektor, dan tes dijalankan di luar IDE yang dibangun di Release (pada Windows, saya tidak lagi memiliki keanggotaan CC untuk diuji)
Jason Kozak
1
Berdasarkan ini - saya bertanya-tanya apakah akan lebih baik (dan seberapa jauh akan lebih baik) untuk membuat anggota-temporal tersebut static(dan / atau lebih agresif menggunakannya kembali). Seperti itu, misalnya, Bodykelas di Farseer memiliki sekitar 73 mengapung anggota yang "tidak perlu".
Andrew Russell
-1

Pertanyaan bagus. Saya seorang pria C # /. NET yang cukup tajam dan sedikit kacang kinerja, dan ini sepertinya keputusan desain yang agak aneh bagi saya. Hal pertama yang melompat pada saya adalah bahwa kode ini sama sekali tidak aman. Saya tidak tahu apakah itu masalah dalam sistem Fisika, tetapi menyimpan data sementara di luar ruang lingkup metode sering kali merupakan resep untuk bencana.

Jujur, jika saya secara teratur menemukan kode semacam ini dalam kerangka kerja pihak ketiga, saya mungkin akan mencoba menemukan kerangka kerja lain.

Mike Strobel
sumber
3
Tidak benar-benar menjawab pertanyaan itu.
Brian Ortiz
Ya, yang terbaik yang bisa saya lakukan adalah mengonfirmasi bahwa dia tidak gila, dan sepertinya tidak ada manfaat nyata jika diberi kode seperti itu. Satu-satunya mengetahui niat sebenarnya adalah bertanya kepada orang yang menulis kode :).
Mike Strobel
Terima kasih, Mike. Saya mulai curiga bahwa pengembang asli adalah yang gila, bukan saya. Tapi itu selalu membantu untuk memeriksa;)
Andrew Russell
Keamanan utas terkadang dapat menjadi jaminan mahal untuk disediakan, terutama saat menulis pustaka berat perhitungan FP untuk platform yang tidak menggunakan instruksi SIMD.
Jason Kozak
-1

GC pada 360 pada dasarnya hanya melakukan koleksi GEN 2, yang mahal, sehingga variabel sementara yang dibuat dan dihapus setiap frame (seperti objek temp) menyebabkan seluruh koleksi berjalan, yang akan mematikan kinerja sangat cepat.

Saya curiga mereka melakukannya dengan cara ini untuk menggunakan kembali objek itu dan tidak mengumpulkannya.

Steven Evers
sumber
1
Ini juga terjadi pada saya, tetapi anggota sementara tampaknya merupakan tipe nilai, jadi mereka tidak akan dialokasikan pada tumpukan yang dikelola.
Mike Strobel
2
Benar, tetapi hanya jika mereka adalah anggota kelas. Jika mereka adalah penduduk lokal (metode-lingkup), mereka akan dialokasikan pada tumpukan. Pertanyaannya adalah mengapa mereka tidak hanya menempuh rute itu.
Mike Strobel
1
@ Blair - Menurut MSDN ( msdn.microsoft.com/en-us/library/bb203912.aspx ) Xbox360 menggunakan .NET Compact Framework. Tampaknya perbedaan dalam GC terkait dengan itu, jadi saya akan mengejar itu untuk penelitian lebih lanjut tentang masalah ini.
Logan Kincaid
1
@ Blair: @Logan Kincaid benar. Pengumpul Sampah CF berperilaku berbeda dari kerangka kerja biasa. Ada pembicaraan yang baik tentang masalah ini di XNA Game Studio 3.0 Unleashed - namun buku itu akan segera usang dengan rilis 4.0.
Steven Evers
1
@ Blair: Karena lingkungan memori terbatas 360 (dan sebagian besar perangkat ditargetkan melalui CF), Mark & ​​Sweep GC digunakan. Akibatnya, banyak alokasi kecil akan memicu koleksi, dan waktu pengumpulan relatif terhadap # referensi. Banyak detail di sini: download.microsoft.com/.../Mobility/…
Jason Kozak