Saya sudah membaca di banyak tempat (heck, saya sudah bahkan ditulis jadi diri sendiri) bahwa pengumpulan sampah bisa (secara teoritis) lebih cepat dari manajemen memori manual.
Namun, menunjukkan jauh lebih sulit didapat daripada memberi tahu.
Saya belum pernah benar - benar melihat potongan kode yang menunjukkan efek ini dalam tindakan.
Adakah yang punya (atau tahu di mana saya bisa menemukan) kode yang menunjukkan keunggulan kinerja ini?
memory
garbage-collection
Mehrdad
sumber
sumber
Jawaban:
Lihat http://blogs.msdn.com/b/ricom/archive/2005/05/10/416151.aspx dan ikuti semua tautan untuk melihat Rico Mariani vs Raymond Chen (keduanya pemrogram yang sangat kompeten di Microsoft) untuk menyelesaikannya . Raymond akan meningkatkan satu unmanaged, Rico akan menanggapi dengan mengoptimalkan hal yang sama di yang dikelola.
Dengan dasarnya nol upaya optimasi, versi berhasil dimulai berkali-kali lebih cepat dari manual. Akhirnya beat manual berhasil, tetapi hanya dengan mengoptimalkan ke tingkat yang kebanyakan programmer tidak ingin pergi ke. Dalam semua versi, penggunaan memori manual signifikan lebih baik daripada dikelola.
sumber
swap
) tidak sulit, dan mungkin akan membawa Anda ke sana dengan mudah berdasarkan kinerja ...Aturan praktisnya adalah tidak ada makan siang gratis.
GC menghilangkan sakit kepala manajemen memori manual dan mengurangi kemungkinan membuat kesalahan. Ada beberapa situasi di mana beberapa strategi GC tertentu adalah solusi optimal untuk masalah tersebut, dalam hal ini Anda tidak akan membayar penalti untuk menggunakannya. Tetapi ada yang lain di mana solusi lain akan lebih cepat. Karena Anda selalu dapat mensimulasikan abstraksi yang lebih tinggi dari tingkat yang lebih rendah tetapi tidak sebaliknya Anda dapat secara efektif membuktikan bahwa tidak ada cara abstraksi yang lebih tinggi bisa lebih cepat daripada yang lebih rendah dalam kasus umum.
GC adalah kasus khusus manajemen memori manual
Mungkin banyak pekerjaan atau lebih banyak kesalahan cenderung untuk mendapatkan kinerja yang lebih baik secara manual tapi itu cerita yang berbeda.
sumber
Sangat mudah untuk membangun situasi buatan di mana GC jauh lebih efisien daripada metode manual - hanya mengatur bahwa hanya ada satu "root" untuk pengumpul sampah, dan bahwa semuanya adalah sampah, sehingga langkah GC langsung selesai.
Jika Anda memikirkannya, itulah model yang digunakan saat sampah mengumpulkan memori yang dialokasikan untuk suatu proses. Prosesnya mati, semua ingatannya adalah sampah, kita sudah selesai. Bahkan secara praktis, proses yang dimulai, berjalan, dan mati tanpa meninggalkan jejak mungkin lebih efisien daripada yang dimulai dan berjalan selamanya.
Untuk program praktis, ditulis dalam bahasa dengan pengumpulan sampah, keuntungan dari pengumpulan sampah bukanlah kecepatan tetapi kebenaran, dan kesederhanaan.
sumber
abort()
C ++ sebelum program keluar. Ini perbandingan yang tidak berarti; Anda bahkan tidak mengumpulkan sampah, Anda hanya membiarkan memori bocor. Anda tidak bisa mengatakan pengumpulan sampah lebih cepat (atau lebih lambat) jika Anda tidak memulai pengumpulan sampah ...Harus dipertimbangkan bahwa GC bukan hanya strategi manajemen memori; itu juga membuat tuntutan pada seluruh desain bahasa dan lingkungan runtime, yang membebankan biaya (dan manfaat). Sebagai contoh, bahasa yang mendukung GC harus dikompilasi ke dalam bentuk di mana pointer tidak dapat disembunyikan dari pengumpul sampah, dan umumnya di mana mereka tidak dapat dibangun kecuali dengan primitif sistem yang dikelola dengan hati-hati. Pertimbangan lainnya adalah sulitnya mempertahankan jaminan waktu respons, karena GC menerapkan beberapa langkah yang harus dibiarkan berjalan hingga selesai.
Akibatnya, jika Anda memiliki bahasa yang mengumpulkan sampah, dan membandingkan kecepatan dengan memori yang dikelola secara manual di sistem yang sama, Anda masih harus membayar biaya overhead untuk mendukung pengumpulan sampah bahkan jika Anda tidak menggunakannya.
sumber
Lebih cepat meragukan. Namun, itu bisa sangat cepat, tidak terlihat, atau lebih cepat jika perangkat kerasnya didukung. Ada desain seperti itu untuk mesin LISP sejak lama. Seseorang membangun GC ke dalam subsistem memori perangkat keras sehingga CPU utama tidak tahu ada di sana. Seperti banyak desain selanjutnya, GC berjalan bersamaan dengan prosesor utama dengan sedikit atau tanpa perlu jeda. Desain yang lebih modern adalah mesin-mesin Azul Systems Vega 3 yang menjalankan kode Java lebih cepat daripada JVM yang menggunakan prosesor yang dibuat khusus dan sebuah GC yang tidak ada jeda. Google mereka jika Anda ingin tahu seberapa cepat GC (atau Java) dapat.
sumber
Saya telah melakukan sedikit pekerjaan dalam hal ini dan menjelaskan beberapa di sini . Saya membandingkan Boehm GC dalam C ++, mengalokasikan menggunakan
malloc
tetapi tidak membebaskan, mengalokasikan dan membebaskan menggunakanfree
dan mark-region GC yang dibuat khusus ditulis dalam C ++ all vs OCaml's stock GC menjalankan pemecah n-queens berbasis daftar. GC OCaml lebih cepat dalam semua kasus. Program C ++ dan OCaml sengaja ditulis untuk melakukan alokasi yang sama dalam urutan yang sama.Anda dapat, tentu saja, menulis ulang program untuk memecahkan masalah hanya menggunakan integer 64-bit dan tidak ada alokasi. Meskipun lebih cepat itu akan mengalahkan titik latihan (yang adalah untuk memprediksi kinerja algoritma GC baru saya sedang mengerjakan menggunakan prototipe yang dibangun di C ++).
Saya telah menghabiskan bertahun-tahun di industri porting kode C ++ nyata ke bahasa yang dikelola. Di hampir setiap kasus saya mengamati peningkatan kinerja yang substansial, banyak di antaranya mungkin disebabkan oleh manajemen memori manual yang lebih baik. Keterbatasan praktis bukanlah apa yang dapat dicapai dalam microbenchmark tetapi apa yang dapat dicapai sebelum batas waktu dan bahasa berbasis GC menawarkan peningkatan produktivitas yang sangat besar sehingga saya tidak pernah melihat ke belakang. Saya masih menggunakan C dan C ++ pada perangkat yang disematkan (mikrokontroler) tetapi bahkan itu sedang berubah sekarang.
sumber
List.filter
seperti halnya C ++. Tapi, ya, Anda tentu benar bahwa beberapa operasi RC dapat dielakkan. Namun, masalah terbesar yang saya lihat di alam liar adalah bahwa orang tidak punya waktu untuk melakukan optimasi seperti itu dengan tangan pada basis kode industri yang besar.shared_ptr
hanya untuk memperbaiki bug konkurensi. Kode jauh lebih lambat tetapi, hei, sekarang berfungsi.Contoh seperti itu tentu saja memiliki skema alokasi memori manual yang buruk.
Asumsikan pengumpul sampah terbaik
GC
. Secara internal ia memiliki metode untuk mengalokasikan memori, menentukan memori apa yang dapat dibebaskan, dan metode untuk akhirnya membebaskannya. Bersama-sama ini membutuhkan waktu kurang dari semuaGC
; beberapa waktu dihabiskan dalam metode lainGC
.Sekarang pertimbangkan pengalokasi manual yang menggunakan mekanisme alokasi yang sama
GC
, dan yangfree()
panggilannya hanya menyisihkan memori untuk dibebaskan dengan metode yang sama sepertiGC
. Itu tidak memiliki fase pemindaian, juga tidak memiliki metode lain. Itu tentu membutuhkan waktu lebih sedikit.sumber
free
juga bisa mengumpulkan batch. (Dan tentu saja menghapus semua item yang memenuhi kriteria masih O (N), jika hanya karena daftar traversal itu sendiri)free
dapat beroperasi dalam mode pengumpulan-kumpulan jika setiap item memori memiliki flag yang terkait dengannya, meskipun GC masih dapat unggul dalam beberapa situasi. Jika seseorang memiliki referensi M yang mengidentifikasi L item yang berbeda dari satu set N hal, waktu untuk menghapus setiap referensi yang tidak ada referensi dan menggabungkan sisanya adalah O (M) daripada O (N). Jika seseorang memiliki ruang ekstra M yang tersedia, konstanta penskalaan bisa sangat kecil. Selanjutnya, pemadatan dalam sistem GC non-pemindaian membutuhkan ...