Artikel ini adalah artikel cermin dari terjemahan mesin, silakan klik di sini untuk melompat ke artikel aslinya.

Melihat: 6846|Jawab: 2

[Sumber] [Berputar]. Pengoptimalan Performa .NET - Collections.Pooled direkomendasikan

[Salin tautan]
Dipaparkan pada 2022-5-29 13:45:22 | | | |
Pengantar singkat

Pengoptimalan kinerja adalah bagaimana memastikan bahwa jumlah permintaan yang sama diproses dengan sumber daya yang lebih sedikit, yang umumnya CPU atau memori, dan tentu saja, pegangan IO sistem operasi, lalu lintas jaringan, penggunaan disk, dll. Tetapi sebagian besar waktu, kami mengurangi penggunaan CPU dan memori.
Konten yang dibagikan sebelumnya memiliki beberapa keterbatasan, sulit untuk diubah secara langsung, hari ini saya ingin berbagi dengan Anda metode sederhana, hanya perlu mengganti beberapa jenis koleksi, untuk mencapai efek meningkatkan kinerja dan mengurangi jejak memori.
Hari ini saya ingin berbagi dengan Anda perpustakaan kelas, iniPustaka kelas disebut Collections.Pooled, Seperti yang dapat dilihat dari namanya, melalui memori gabungan untuk mencapai tujuan mengurangi jejak memori dan GC, dan kami akan langsung melihat bagaimana kinerjanya, dan kami juga akan membawa Anda untuk melihat kode sumbernya, mengapa ia membawa peningkatan kinerja ini.

Koleksi.Dikumpulkan

Tautan proyek:Login hyperlink terlihat.

Pustaka ini didasarkan pada kelas di System.Collections.Generic, yang telah dimodifikasi untuk memanfaatkan pustaka kelas System.Span <T>dan System.Buffers.ArrayPool baru <T>untuk tujuan mengurangi alokasi memori, meningkatkan performa, dan memungkinkan interoperabilitas yang lebih besar dengan API modern.
Collections.Pooled mendukung .NET Standnd 2.0 (.NET Framework 4.6.1+), serta dukungan untuk . INTI BERSIH 2.1+. Serangkaian pengujian unit dan tolok ukur yang ekstensif telah di-porting dari CoreFX.

Jumlah total tes: 27501. Melalui: 27501. Kegagalan: 0. Lewati: 0.
Uji coba berhasil.
Waktu eksekusi pengujian: 9.9019 detik

Cara penggunaan

Anda dapat dengan mudah menginstal perpustakaan ini melalui Nuget, Versi NuGet.

Dalam pustaka Collections.Pooled, ini mengimplementasikan versi yang dikumpulkan untuk jenis koleksi yang biasa kita gunakan, seperti yang ditunjukkan dalam perbandingan dengan jenis asli .NET.

. .NET asliKoleksi.DikumpulkanPernyataan
Daftar<T>Daftar <T>TerkumpulKelas koleksi generik
Kamus<TKey, TValue>PooledDictionary<TKey, TValue>Kelas kamus generik
Set <T>HashKumpulan<T>Kelas koleksi hash generik
Susun<T>Susun<T>Tumpukan generik
Antre<T>Antrean <T>TerkumpulKohort generik

Saat menggunakan, kita hanya perlu menambahkan . Versi asli .NET dengan versi Collections.Pooled, seperti yang ditunjukkan dalam kode di bawah ini:

Namun, kita perlu mencatat bahwa jenis Pooled mengimplementasikan antarmuka IDispose, yang mengembalikan memori yang digunakan ke kumpulan melalui metode Dispose(), jadi kita perlu memanggil metode Dispose() setelah menggunakan objek koleksi Pooled. Atau Anda dapat menggunakan kata kunci var secara langsung.

Catatan: Gunakan objek koleksi di dalam Collections.PooledYang terbaik adalah perlu melepaskannya secara manual, tetapi tidak masalah jika Anda tidak merilisnya, GC pada akhirnya akan mendaur ulangnya, tetapi tidak dapat dikembalikan ke pool, dan tidak akan mencapai efek menghemat memori.
Karena menggunakan kembali ruang memori, saat mengembalikan ruang memori ke kumpulan, ia perlu memproses elemen dalam koleksi, dan menyediakan pencacahan yang disebut ClearMode untuk digunakan, yang didefinisikan sebagai berikut:




Secara default, Anda dapat menggunakan nilai default Otomatis, dan jika ada persyaratan performa khusus, Anda dapat menggunakan Tidak pernah setelah mengetahui risikonya.
Untuk jenis referensi dan tipe nilai yang berisi tipe referensi, kita harus mengosongkan referensi array saat mengembalikan ruang memori ke pool, jika tidak dihapus, GC tidak akan dapat mengosongkan bagian ruang memori ini (karena referensi elemen selalu dipegang oleh pool), jika itu adalah tipe nilai murni, maka tidak dapat dikosongkan, dalam artikel ini saya menjelaskan perbedaan penyimpanan antara jenis referensi dan array struct (tipe nilai), jenis nilai murni tidak memiliki daur ulang header objek dan tidak memerlukan intervensi GC.


. Pengoptimalan Performa .NET - Gunakan kelas alternatif struct:Login hyperlink terlihat.

Perbandingan kinerja

Saya tidak melakukan Benchmark sendirian, dan hasil skor berjalan dari proyek open source yang saya gunakan langsung adalah 0 untuk penggunaan memori banyak proyek, yang karena memori gabungan yang digunakan tidak memiliki alokasi tambahan.

Daftar <T>Terkumpul

Ulangi elemen 2048 yang ditambahkan ke set di Benchmark, . Daftar asli .NET <T>membutuhkan 110us (menurut hasil benchmark aktual, milidetik dalam gambar harus berupa kesalahan administrasi) dan memori 263KB, sedangkan PooledList <T>hanya membutuhkan memori 36us dan 0KB.




PooledDictionary<TKey, TValue>

Tambahkan 10_0000 elemen ke kamus dalam perulangan di Benchmark, . Kamus asli .NET<TKey, TValue> membutuhkan memori 11 ms dan 13 MB, sedangkan PooledDictionary<TKey, TValue> hanya membutuhkan memori 7 ms dan 0 MB.




Kumpulan<T>

Ulangi koleksi hash di Benchmark tambahkan 10_0000 elemen, . HashSet asli .NET <T>membutuhkan 5348 ms dan 2 MB, sedangkan PooledSet <T>hanya membutuhkan memori 4723 ms dan 0 MB.




TumpukanTerkumpul<T>

Ulangi tumpukan di Benchmark untuk menambahkan 10_0000 elemen, . PooledStack asli .NET <T>membutuhkan 1079 ms dan 2 MB, sedangkan PooledStack <T>hanya memerlukan memori 633 ms dan 0 MB.




Antrean <T>Terkumpul

Ulangi loop di Benchmark untuk menambahkan 10_0000 elemen ke antrean, . <T>PooledQueue asli .NET membutuhkan 681 ms dan 1 MB, sedangkan PooledQueue <T>hanya memerlukan memori 408 ms dan 0 MB.




Adegan tidak dirilis secara manual

Selain itu, kami menyebutkan di atas bahwa jenis koleksi yang dikumpulkan perlu dirilis, tetapi tidak masalah jika tidak dirilis, karena GC akan didaur ulang.


Hasil Benchmark adalah sebagai berikut:



Kesimpulan dapat ditarik dari hasil Benchmark di atas.

Melepaskan koleksi tipe Pooled tepat waktu hampir tidak memicu GC dan mengalokasikan memori, dari grafik di atas hanya mengalokasikan memori 56Byte.
Bahkan jika koleksi jenis Pooled tidak dirilis, karena mengalokasikan memori dari kumpulan, koleksi tersebut akan tetap menggunakan kembali memori selama operasi ekspansi ReSize, dan melewati langkah inisialisasi memori alokasi GC, yang relatif cepat.
Yang paling lambat adalah menggunakan jenis koleksi normal, setiap operasi ekspansi ReSize perlu diterapkan untuk ruang memori baru, dan GC juga perlu merebut kembali ruang memori sebelumnya.


Analisis prinsip

Jika Anda telah membaca posting blog saya sebelumnya, Anda harus mengatur ukuran awal untuk jenis koleksi dan menganalisis prinsip implementasi Kamus C#, Anda dapat mengetahui bahwa pengembang .NET BCL menggunakan struktur data yang mendasari jenis koleksi dasar ini untuk menjadi array untuk akses acak berperforma tinggi, mari kita ambil List <T>sebagai contoh.

Buat array baru untuk menyimpan elemen yang ditambahkan.
Jika tidak ada cukup ruang dalam array, operasi ekspansi dipicu untuk meminta dua kali ukuran ruang.
Kode konstruktor adalah sebagai berikut, dan Anda dapat melihat bahwa itu adalah array generik yang dibuat secara langsung:


Jadi jika Anda ingin mengumpulkan memori, Anda hanya perlu mengubah tempat di mana aplikasi kata kunci baru digunakan di pustaka kelas untuk menggunakan aplikasi yang dikumpulkan. Di sini saya membagikannya dengan Anda. NET BCL adalah jenis yang disebut ArrayPool, yang menyediakan kumpulan sumber daya array dari instans generik yang dapat digunakan kembali, yang dapat digunakan untuk mengurangi tekanan pada GC dan meningkatkan performa dalam kasus pembuatan dan penghancuran array yang sering.

Lapisan yang mendasari jenis Pooled kami adalah menggunakan ArrayPool untuk berbagi kumpulan sumber daya, dan dari konstruktornya, kami dapat melihat bahwa ArrayPool menggunakan secara default<T>. Dibagikan untuk menetapkan objek array, dan tentu saja Anda juga dapat membuat ArrayPool Anda sendiri untuk menggunakannya.


Selain itu, saat melakukan operasi penyesuaian kapasitas (ekspansi), array lama dikembalikan ke kumpulan utas, dan array baru juga diperoleh dari kumpulan.

Selain itu, penulis menggunakan Span untuk mengoptimalkan API seperti Add dan Insert untuk memberi mereka performa akses acak yang lebih baik. Selain itu, API seri TryXXX telah ditambahkan, sehingga Anda dapat menggunakannya dengan cara yang lebih nyaman. Misalnya, <T>kelas List <T>memiliki hingga 170 modifikasi dibandingkan dengan PooledList.



ringkasan

Dalam penggunaan online kita yang sebenarnya, kita dapat mengganti jenis koleksi asli dengan jenis koleksi yang disediakan oleh Pooled, yang sangat membantu dalam mengurangi penggunaan memori dan latensi P95.
Selain itu, bahkan jika Anda lupa merilisnya, kinerjanya tidak akan jauh lebih buruk daripada menggunakan jenis koleksi asli. Tentu saja, kebiasaan terbaik adalah melepaskannya tepat waktu.


Asli:Login hyperlink terlihat.




Mantan:RecyclableMemoryStream menyediakan streaming .NET berperforma tinggi
Depan:[Pertempuran praktis] Server membangun LibreSpeed untuk menguji kecepatan jaringan
Dipaparkan pada 2022-5-29 17:12:36 |
Belajar
Dipaparkan pada 2022-6-20 09:09:22 |
Pelajari campurannya
Sanggahan:
Semua perangkat lunak, materi pemrograman, atau artikel yang diterbitkan oleh Code Farmer Network hanya untuk tujuan pembelajaran dan penelitian; Konten di atas tidak boleh digunakan untuk tujuan komersial atau ilegal, jika tidak, pengguna akan menanggung semua konsekuensi. Informasi di situs ini berasal dari Internet, dan sengketa hak cipta tidak ada hubungannya dengan situs ini. Anda harus sepenuhnya menghapus konten di atas dari komputer Anda dalam waktu 24 jam setelah pengunduhan. Jika Anda menyukai program ini, harap dukung perangkat lunak asli, pembelian pendaftaran, dan dapatkan layanan asli yang lebih baik. Jika ada pelanggaran, silakan hubungi kami melalui email.

Mail To:help@itsvse.com