PC saat ini memiliki RAM fisik dalam jumlah besar tetapi tetap saja, ukuran tumpukan C # hanya 1 MB untuk proses 32-bit dan 4 MB untuk proses 64-bit ( Kapasitas tumpukan dalam C # ).
Mengapa ukuran tumpukan di CLR masih sangat terbatas?
Dan mengapa tepatnya 1 MB (4 MB) (dan bukan 2 MB atau 512 KB)? Mengapa diputuskan untuk menggunakan jumlah ini?
Saya tertarik dengan pertimbangan dan alasan di balik keputusan itu .
c#
stack
clr
stack-size
Nikolay Kostov
sumber
sumber
Thread
konstruktor yang tepat. TAPI, ini menimbulkan pertanyaan, mengapa Anda membutuhkan tumpukan yang lebih besar?1572864
ukuran tumpukan default byte (Diperoleh menggunakan GetCurrentThreadStackLimits Win32 API). Saya bisastackalloc
kira - kira1500000
byte tanpa StackOverflowException.Jawaban:
Anda sedang melihat pria yang membuat pilihan itu. David Cutler dan timnya memilih satu megabyte sebagai ukuran tumpukan default. Tidak ada hubungannya dengan .NET atau C #, ini dipaku ketika mereka membuat Windows NT. Satu megabyte adalah apa yang dipilihnya ketika header EXE dari sebuah program atau panggilan winapi CreateThread () tidak menentukan ukuran tumpukan secara eksplisit. Yang merupakan cara normal, hampir semua programmer membiarkan OS untuk memilih ukurannya.
Pilihan itu mungkin mendahului desain Windows NT, sejarahnya terlalu kabur tentang ini. Alangkah baiknya jika Cutler mau menulis buku tentang itu, tapi dia tidak pernah menjadi penulis. Dia sangat berpengaruh pada cara kerja komputer. Desain OS pertamanya adalah RSX-11M, sistem operasi 16-bit untuk komputer DEC (Digital Equipment Corporation). Ini sangat mempengaruhi CP / M Gary Kildall, OS pertama yang layak untuk mikroprosesor 8-bit. Yang sangat mempengaruhi MS-DOS.
Desain berikutnya adalah VMS, sistem operasi untuk prosesor 32-bit dengan dukungan memori virtual. Sangat sukses. Yang berikutnya dibatalkan oleh DEC sekitar saat perusahaan mulai bubar, tidak mampu bersaing dengan perangkat keras PC murah. Isyarat Microsoft, mereka memberinya tawaran yang tidak bisa dia tolak. Banyak rekan kerjanya juga bergabung. Mereka bekerja pada VMS v2, lebih dikenal sebagai Windows NT. DEC menjadi kesal karenanya, uang berpindah tangan untuk menyelesaikannya. Apakah VMS sudah memilih satu megabyte adalah sesuatu yang saya tidak tahu, saya hanya cukup mengenal RSX-11. Itu tidak mungkin.
Sejarah yang cukup. Satu megabyte itu banyak , utas asli jarang menghabiskan lebih dari beberapa kilobyte. Jadi satu megabyte sebenarnya agak boros. Bagaimanapun juga, jenis pemborosan yang dapat Anda lakukan pada sistem operasi memori virtual dengan halaman permintaan, megabyte itu hanyalah memori virtual . Hanya angka untuk prosesor, masing-masing satu untuk setiap 4096 byte. Anda tidak pernah benar-benar menggunakan memori fisik, RAM di mesin, sampai Anda benar-benar mengatasinya.
Ini lebih berlebihan dalam program .NET karena ukuran satu megabyte awalnya dipilih untuk mengakomodasi program asli. Yang cenderung membuat bingkai tumpukan besar, menyimpan string dan buffer (array) di tumpukan juga. Terkenal sebagai vektor serangan malware, buffer overflow dapat memanipulasi program dengan data. Bukan cara kerja program .NET, string dan array dialokasikan pada heap GC dan pengindeksan diperiksa. Satu-satunya cara untuk mengalokasikan ruang pada stack dengan C # adalah dengan kata kunci stackalloc yang tidak aman .
Satu-satunya penggunaan tumpukan yang tidak sepele di .NET adalah dengan jitter. Ini menggunakan tumpukan utas Anda untuk mengkompilasi MSIL ke kode mesin tepat waktu. Saya belum pernah melihat atau memeriksa berapa banyak ruang yang dibutuhkannya, ini lebih tergantung pada sifat kode dan apakah pengoptimal diaktifkan atau tidak, tetapi beberapa puluh kilobyte adalah tebakan kasar. Begitulah cara situs web ini mendapatkan namanya, tumpukan overflow dalam program .NET cukup fatal. Tidak ada cukup ruang tersisa (kurang dari 3 kilobyte) untuk tetap andal JIT kode apa pun yang mencoba menangkap pengecualian. Kaboom to desktop adalah satu-satunya pilihan.
Last but not least, program .NET melakukan sesuatu yang sangat tidak produktif dengan stack. CLR akan melakukan tumpukan utas. Itu adalah kata yang mahal yang artinya tidak hanya menyimpan ukuran tumpukan, tetapi juga memastikan bahwa ruang dicadangkan dalam file halaman sistem operasi sehingga tumpukan selalu dapat ditukar saat diperlukan. Gagal mengkomit adalah kesalahan fatal dan menghentikan program tanpa syarat. Itu hanya terjadi pada mesin dengan RAM sangat sedikit yang menjalankan terlalu banyak proses, mesin seperti itu akan berubah menjadi molase sebelum program mulai mati. Masalah yang mungkin terjadi 15+ tahun yang lalu, bukan hari ini. Pemrogram yang menyetel program mereka untuk bertindak seperti mobil balap F1 menggunakan
<disableCommitThreadStack>
elemen dalam file .config mereka.Fwiw, Cutler tidak berhenti mendesain sistem operasi. Foto itu dibuat saat dia mengerjakan Azure.
Pembaruan, saya perhatikan bahwa .NET tidak lagi melakukan tumpukan. Tidak yakin kapan atau mengapa ini terjadi, sudah terlalu lama sejak saya memeriksanya. Saya menduga perubahan desain ini terjadi di sekitar .NET 4.5. Perubahan yang cukup masuk akal.
sumber
The only way to allocate space on the stack with C# is with the unsafe stackalloc keyword.
- Apakah variabel lokal misalnya yangint
dideklarasikan di dalam metode tidak disimpan di stack? Saya pikir mereka.maxStackSize
sebuah utas? Saya tidak dapat menemukannya di [MSDN] ( msdn.microsoft.com/en-us/library/5cykbwz4(v=vs.110).aspx ). Berdasarkan komentar Anda, tampaknya penggunaan tumpukan sangat minimum dan saya dapat menggunakan nilai terkecil untuk mengakomodasi utas semaksimal mungkin. Terima kasih.Ukuran tumpukan yang dicadangkan default ditentukan oleh penaut dan dapat diganti oleh pengembang melalui mengubah nilai PE pada waktu penautan atau untuk utas individu dengan menentukan
dwStackSize
parameter untukCreateThread
fungsi WinAPI.Jika Anda membuat utas dengan ukuran tumpukan awal lebih besar dari atau sama dengan ukuran tumpukan default, maka utas tersebut akan dibulatkan ke kelipatan terdekat yaitu 1 MB.
Mengapa nilainya sama dengan 1 MB untuk proses 32-bit dan 4 MB untuk 64-bit? Saya pikir Anda harus bertanya kepada pengembang, yang merancang Windows, atau menunggu sampai seseorang menjawab pertanyaan Anda.
Mungkin Mark Russinovich tahu itu dan Anda bisa menghubunginya . Mungkin Anda dapat menemukan informasi ini di buku-buku Windows Internals-nya sebelum edisi keenam yang menjelaskan lebih sedikit info tentang tumpukan daripada artikelnya . Atau mungkin Raymond Chen tahu alasannya karena dia menulis hal-hal menarik tentang internal Windows dan sejarahnya. Dia dapat menjawab pertanyaan Anda juga, tetapi Anda harus memposting saran ke Kotak Saran .
Tetapi kali ini saya akan mencoba menjelaskan beberapa kemungkinan alasan mengapa Microsoft memilih nilai-nilai ini menggunakan blog MSDN, Mark's dan Raymond.
Defaultnya memiliki nilai ini mungkin karena pada masa awal PC lambat dan mengalokasikan memori pada stack jauh lebih cepat daripada mengalokasikan memori di heap. Dan karena alokasi tumpukan jauh lebih murah, mereka digunakan, tetapi itu membutuhkan ukuran tumpukan yang lebih besar.
Jadi nilainya adalah ukuran tumpukan cadangan optimal untuk sebagian besar aplikasi. Ini optimal karena memungkinkan untuk membuat banyak panggilan bersarang dan mengalokasikan memori pada stack untuk meneruskan struktur ke fungsi panggilan. Pada saat yang sama memungkinkan untuk membuat banyak utas.
Saat ini nilai-nilai ini banyak digunakan untuk kompatibilitas mundur, karena struktur yang diteruskan sebagai parameter ke fungsi WinAPI masih dialokasikan di stack. Tetapi jika Anda tidak menggunakan alokasi tumpukan maka penggunaan tumpukan utas akan jauh lebih kecil dari default 1 MB dan itu sia-sia seperti yang disebutkan Hans Passant. Dan untuk mencegah hal ini, OS hanya melakukan halaman pertama dari tumpukan (4 KB), jika yang lain tidak ditentukan di header PE aplikasi. Halaman lain dialokasikan sesuai permintaan.
Beberapa aplikasi menimpa ruang alamat yang dicadangkan dan awalnya berkomitmen untuk mengoptimalkan penggunaan memori. Sebagai contoh, ukuran tumpukan maksimum utas proses asli IIS adalah 256 KB ( KB932909 ). Dan penurunan nilai default ini direkomendasikan oleh Microsoft:
Sumber:
sumber