Oh ya, sudah biasa. Saya bekerja di bidang pemrosesan paket jaringan. Saya telah berada di dua perusahaan berbeda di mana kami memproses paket jaringan. Jadi, kami beroperasi pada level Ethernet atau IP, bukan pada level di atas TCP.
Menariknya, di kedua perusahaan C dipilih lebih dari C ++. Di salah satu perusahaan, salah satu dari dua produk dibangun di atas kernel Linux, sedangkan produk lainnya dibangun di ruang pengguna Linux. Produk kernel jelas menggunakan C karena kernel Linux diprogram dalam C, tetapi mereka memilih untuk menggunakan C untuk produk userspace juga. Kedua produk dikembangkan mulai dari sekitar tahun 2000 (produk kernel sedikit sebelum tahun 2000 dan produk userspace sedikit setelah tahun 2000).
Di perusahaan tempat saya pergi setelah itu, produk itu dibangun di atas C, bukan di C ++. Ini sebenarnya merupakan kelanjutan dari proyek dari pertengahan 1990-an, meskipun karena tuntutan peningkatan kinerja baru-baru ini, diputuskan bahwa pada dasarnya semuanya akan ditulis ulang. Kami memiliki opsi untuk memilih C ++ karena penulisan ulang ini, tetapi tidak melakukannya.
Di bidang pemrosesan paket jaringan, kinerja sangat penting. Jadi, saya ingin mengimplementasikan tabel hash saya sendiri yang memiliki kinerja lebih tinggi dari tabel hash yang ada. Saya, bukan penulis tabel hash, saya yang memilih fungsi hash apa yang akan digunakan. Mungkin saya ingin kinerja dan menggunakan MurMurHash3 . Mungkin saya menginginkan keamanan dan mencari SipHash . Pengalokasi memori jelas khusus. Faktanya, semua struktur data penting yang kami gunakan telah diimplementasikan secara kustom untuk kinerja setinggi mungkin.
Meskipun tidak ada yang akan mencegah penggunaan C ++, itu biasanya ide yang buruk. Satu pengecualian yang dilemparkan per paket akan menurunkan tingkat pemrosesan paket ke level yang tidak dapat diterima! Jadi, kita tidak bisa menggunakan pengecualian C ++. Terlalu lambat. Kami sudah menggunakan semacam kode berorientasi objek C dengan mengimplementasikan struktur data sebagai struct dan kemudian mengimplementasikan fungsi yang beroperasi pada struct tersebut. C ++ akan memungkinkan memiliki fungsi virtual, tetapi sekali lagi panggilan fungsi virtual akan mematikan kinerja jika digunakan di mana-mana. Jadi, lebih baik untuk menjadi eksplisit dan memiliki pointer fungsi jika panggilan fungsi virtual diperlukan.
C ++ akan melakukan banyak hal di belakang Anda: alokasi memori, dll. Di sisi lain, dalam C yang biasanya tidak terjadi. Anda dapat menulis fungsi yang mengalokasikan memori, tetapi biasanya terlihat dari antarmuka fungsi yang terjadi alokasi.
Sebagai contoh jenis optimasi mikro yang dapat Anda lakukan saat memprogram dalam C, lihat makro container_of di kernel Linux. Tentu, Anda bisa menggunakan container_of dalam kode C ++, tetapi siapa yang melakukannya? Maksud saya, ini sepenuhnya dapat diterima di sebagian besar program C, tetapi umumnya programmer C ++ akan segera mengusulkan sesuatu yang lain, seperti daftar tertaut yang mengalokasikan node tautan sebagai blok terpisah. Kami tidak ingin itu karena setiap blok memori yang dialokasikan buruk untuk kinerja.
Mungkin satu-satunya hal yang akan menguntungkan kita di C ++ adalah bahwa C ++ memungkinkan metaprogramming template, yang berarti Anda kadang-kadang dapat menghindari panggilan fungsi virtual sementara masih memiliki parameter fungsi, dan memungkinkan kompiler untuk inline fungsi. Tetapi metaprogramming template itu rumit, dan kami telah berhasil memenuhi semua persyaratan dalam C, jadi manfaat fitur ini di C ++ tidak terlalu kritis.
Di salah satu perusahaan, kami benar-benar memiliki bahasa yang dikompilasi khusus di mana bagian dari fitur diimplementasikan. Tebak yang merupakan bahasa target dari kompiler? Majelis? Tidak, kami harus mendukung arsitektur 32-bit dan 64-bit. C ++? Tentunya Anda bercanda. Jelas, itu adalah C dengan goto yang dihitung GCC . Jadi, bahasa khusus dikompilasi ke C (atau sebenarnya varian gcc dari C yang mendukung komputasi goto), dan kompiler C menghasilkan perakitan.