1 puan yazan GN⁺ 2024-09-02 | 1 yorum | WhatsApp'ta paylaş

{fmt} kütüphanesinde ikili boyut optimizasyonu

  • {fmt} kütüphanesine giriş

    • {fmt}, küçük ikili boyutuyla tanınan bir biçimlendirme kütüphanesidir
    • IOStreams, Boost Format, tinyformat vb. ile karşılaştırıldığında, işlev çağrısı başına kod boyutu çok daha küçüktür
    • Şablon yükünü en aza indirmek için type erasure kullanır
  • Type erasure ile biçimlendirme

    • format işlevi işi vformat işlevine devreder
    • Çıktı yineleyicisi ve diğer çıktı türleri de özel olarak tasarlanmış buffer API'si üzerinden type erasure ile ele alınır
    • Şablon kullanımını en aza indirerek ikili boyutu ve derleme süresini azaltır
  • Örnek kod

    #include <fmt/base.h>
    int main() { fmt::print("The answer is {}.", 42); }
    
    • Yukarıdaki kod, IOStreams kodundan çok daha küçük bir boyutta derlenir
    • printf ile karşılaştırıldığında da boyut benzerdir ve çalışma zamanında tür güvenliği sağlar
  • İkili boyut optimizasyonu

    • 2020'de kütüphane boyutunu 100kB'nin altına indirme çalışması yapıldı
    • Güncel sürümün (11.0.2) ikili boyutu 75kB'dir
    • Yerel ayar desteği devre dışı bırakılırsa boyut 71kB'ye düşürülebilir
  • Bloaty aracıyla analiz

    • Sayı biçimlendirme, özellikle de kayan noktalı sayı biçimlendirme büyük bir pay kaplar
    • Kayan nokta desteğine ihtiyaç yoksa bu destek devre dışı bırakılabilir
  • Türe göre biçimlendirme optimizasyonu

    • FMT_BUILTIN_TYPES makrosu 0 olarak ayarlanarak yalnızca int türü özel olarak işlenir, diğer türler ise genişletme API'si üzerinden işlenir
    • Bu yöntemle ikili boyut 31kB'ye düşürülebilir
  • Yerel ayar artefaktlarını kaldırma

    • FMT_USE_LOCALE makrosu kullanılarak yerel ayar artefaktları kaldırılırsa boyut 27kB'ye düşürülebilir
  • Hız ile boyut arasındaki trade-off

    • FMT_OPTIMIZE_SIZE makrosu ile boyut optimize edildiğinde ikili boyut 23kB'ye düşürülebilir
  • C++ standart kütüphanesi bağımlılığını kaldırma

    • İstisnalar devre dışı bırakılıp -nodefaultlibs seçeneği kullanılarak C++ çalışma zamanı bağımlılığı kaldırılır
    • malloc ve free kullanan özel bir allocator eklenerek ikili boyut 14kB'ye düşürülebilir
  • Sonucun doğrulanması

    • ldd komutuyla C++ çalışma zamanı bağımlılığının kaldırıldığı doğrulanır

GN⁺ özeti

  • {fmt} küçük ikili boyut ve çalışma zamanında tür güvenliği sunan bir biçimlendirme kütüphanesidir
  • Type erasure ve makro ayarlarıyla ikili boyut önemli ölçüde küçültülebilir
  • C++ standart kütüphanesi bağımlılığı kaldırılarak gömülü sistemlerde de verimli şekilde kullanılabilir
  • Benzer işlevler sunan kütüphaneler arasında IOStreams, Boost Format ve tinyformat bulunur

1 yorum

 
GN⁺ 2024-09-02
Hacker News yorumu
  • {fmt} varsayılan olarak locale'den bağımsızdır
  • Kayan nokta biçimlendirme için çok fazla kod gerekir
    • Dragonbox projesi optimize edilmiş koduyla incelenmeye değer
  • C++'ın varsayılan allocator'ı malloc ve free kullanmaz
    • libc++'ın varsayılan allocator'ının neden libc'nin malloc ve free çağrılarını kullanmadığı merak ediliyor
  • printf("Hello, World!\n") ifadesini 1008 baytlık çalıştırılabilir dosya boyutuyla mümkün kılan bir proje var
    • Doğrudan karşılaştırmak zor ama yine de bakmaya değer
  • Boş bir main fonksiyonuna sahip C programının 6kB olduğu bir sistemde {fmt}, ikili dosyaya 10kB'den daha az ekliyor
    • İlginç bir test
  • Küçük bir biçimlendirme kütüphanesinin string ve tamsayıları yazdırmak için yaklaşık 50 bayta ihtiyaç duyacağını düşünmüştüm
    • Stringler yaklaşık 4 komuttan oluşuyor
    • Tamsayılar yaklaşık 20 komuttan oluşuyor
    • Kayan nokta birçok programda kullanılmadığından yalnızca gerektiğinde derlenmeli
    • Mikrodenetleyici kod alanı 2 kilobayt ise 14 kilobaytlık bir string biçimlendirme kütüphanesi eklenmez
  • Bu tür kalıpların dışına çıkan optimizasyonlar çok keyifli
  • "14k" ifadesinin "14kB" anlamına geldiğini fark etmem zaman aldı
  • fmt her zaman sorun çıkarıyor
    • Aynı sorun .NET'te de yaşanıyor
    • Sayı biçimlendirme/ayrıştırma ile çok uğraşınca linker çok sayıda kayan nokta ve BigInt ile ilgili kodu dahil ediyor, bu da ikili dosya boyutunu büyütüyor