The bool jenis memiliki sejarah kotak-kotak dengan banyak pilihan sesuai antara runtimes bahasa. Ini dimulai dengan pilihan desain historis yang dibuat oleh Dennis Ritchie, orang yang menemukan bahasa C. Itu tidak memiliki tipe bool , alternatifnya adalah int di mana nilai 0 mewakili salah dan nilai lainnya dianggap benar .
Pilihan ini dibawa ke depan di Winapi, alasan utama untuk menggunakan pinvoke, ia memiliki typedef BOOL
yang merupakan alias untuk kata kunci int kompiler C. Jika Anda tidak menerapkan atribut [MarshalAs] eksplisit maka C # bool akan diubah menjadi BOOL, sehingga menghasilkan bidang yang panjangnya 4 byte.
Apa pun yang Anda lakukan, deklarasi struct Anda harus sesuai dengan pilihan waktu proses yang dibuat dalam bahasa yang Anda gunakan. Seperti disebutkan, BOOL untuk winapi tetapi sebagian besar implementasi C ++ memilih byte , sebagian besar interop COM Automation menggunakan VARIANT_BOOL yang merupakan singkatan .
The aktual ukuran C # bool
adalah salah satu byte. Tujuan desain CLR yang kuat adalah bahwa Anda tidak dapat menemukannya. Tata letak adalah detail implementasi yang terlalu bergantung pada prosesor. Prosesor sangat pilih-pilih tentang jenis dan penyelarasan variabel, pilihan yang salah dapat memengaruhi kinerja secara signifikan dan menyebabkan kesalahan waktu proses. Dengan membuat tata letak tidak dapat ditemukan, .NET dapat menyediakan sistem tipe universal yang tidak bergantung pada implementasi runtime yang sebenarnya.
Dengan kata lain, Anda harus selalu menyusun struktur pada waktu proses untuk memastikan tata letaknya. Pada saat konversi dari tata letak internal ke tata letak interop dilakukan. Itu bisa sangat cepat jika tata letaknya identik, lambat ketika bidang perlu diatur ulang karena itu selalu membutuhkan pembuatan salinan struct. Istilah teknis untuk ini adalah blittable , meneruskan struct blittable ke kode native dengan cepat karena marshaller pinvoke dapat dengan mudah meneruskan sebuah pointer.
Kinerja juga merupakan alasan utama mengapa bool tidak sedikit pun. Ada beberapa prosesor yang membuat sedikit dapat langsung dialamatkan, unit terkecil adalah byte. Sebuah tambahan instruksi diperlukan untuk ikan sedikit keluar dari byte, yang tidak datang secara gratis. Dan itu tidak pernah atom.
Kompiler C # tidak malu untuk memberitahu Anda bahwa ini membutuhkan 1 byte, gunakan sizeof(bool)
. Ini masih bukan prediktor yang bagus untuk berapa banyak byte yang dibutuhkan sebuah field saat runtime, CLR juga perlu mengimplementasikan model memori .NET dan menjanjikan bahwa pembaruan variabel sederhana bersifat atomic . Itu membutuhkan variabel untuk diselaraskan dengan benar dalam memori sehingga prosesor dapat memperbaruinya dengan satu siklus bus memori. Cukup sering, bool sebenarnya membutuhkan 4 atau 8 byte dalam memori karena ini. Bantalan ekstra yang ditambahkan untuk memastikan bahwa anggota berikutnya disejajarkan dengan benar.
CLR sebenarnya memanfaatkan tata letak yang tidak dapat ditemukan, ini dapat mengoptimalkan tata letak kelas dan mengatur ulang bidang sehingga padding diminimalkan. Jadi, katakanlah, jika Anda memiliki kelas dengan anggota bool + int + bool maka akan membutuhkan 1 + (3) + 4 + 1 + (3) byte memori, (3) adalah padding, dengan total 12 byte. 50% limbah. Tata letak otomatis diatur ulang menjadi 1 + 1 + (2) + 4 = 8 byte. Hanya kelas yang memiliki tata letak otomatis, struct memiliki tata letak berurutan secara default.
Lebih suram lagi, bool dapat memerlukan sebanyak 32 byte dalam program C ++ yang dikompilasi dengan kompiler C ++ modern yang mendukung set instruksi AVX. Yang memberlakukan persyaratan penyelarasan 32-byte, variabel bool mungkin berakhir dengan padding 31 byte. Juga alasan inti mengapa jitter .NET tidak memancarkan instruksi SIMD, kecuali dibungkus secara eksplisit, itu tidak bisa mendapatkan jaminan penyelarasan.