Geçenlerde gerçek zamanlı veri işleyen bir sistem üzerinde çalışıyordum. Her şey güzel giderken, try-catch bloklarının olduğu kritik bir döngüde takılmalar hissetmeye başladım. Profiler'ı açtığımda gördüğüm manzara içler acısıydı. Meğerse exception handling, masum gibi görünüp arka planda koca bir runtime overhead getiriyormuş. Stack unwinding, RTTI (Run-Time Type Information) derken, özellikle sık çalışan kod yollarında maliyet hiç de azımsanacak gibi değil.
Araştırmaya başladım. "Zero-cost exception" diye bir şey varmış ama o da sadece exception atılmadığı zaman sıfır maliyetliymiş. Atıldığı anda yine aynı hikaye. Ben de "Bu iş böyle olmayacak" deyip, projenin CMakeLists.txt dosyasına dalış yaptım. Özellikle gömülü ve performans kritik sistemlerde exception'ları tamamen devre dışı bırakan bir yaklaşım olduğunu gördüm.
C++:
// -fno-exceptions ile geldi bu hata!
// std::vector bile allocate edemiyor artık.
// #include <vector>
// std::vector<int> vec; // Derleme hatası!
GCC ve Clang'de `-fno-exceptions` flag'ini eklediğin anda, dünya başına yıkılıyor. STL bile exception kullandığı için bir sürü şey çalışmaz hale geliyor. `new` operatörü `nullptr` döndürmeye başlıyor. Alternatif error handling metodlarına (return code'lar, optional tipler, outcome library) geçiş yapmak zorunda kalıyorsun.
Nihayetinde, proje ayarlarına `-fno-exceptions`'ı ekledim ve tüm exception mekanizmasını kaldırdım. Evet, kod biraz daha "C tarzı" error checking ile doldu, ama o mikro saniyeleri kazanmak ve deterministik bir performans elde etmek buna değdi. Tabii bu, her proje için doğru bir karar değil. UI uygulaması yazıyorsanız hiç bulaşmayın derim. Ama saniyede milyonlarca işlem yapan, latency'nin altın değerinde olduğu bir sistemde, exception'lardan kurtulmak hayat kurtarıcı olabiliyor.
Siz ne düşünüyorsunuz? Exception'ları tamamen hayatınızdan çıkardığınız oldu mu, yoksa bu maliyeti göze alıp rahatlığına mı devam ediyorsunuz? Gömülücü arkadaşlar, siz nasıl yönetiyorsunuz bu işi?