1 poin oleh GN⁺ 2024-09-02 | 1 komentar | Bagikan ke WhatsApp

Optimasi ukuran biner library {fmt}

  • Pengenalan library {fmt}

    • {fmt} adalah library formatting yang dikenal memiliki ukuran biner kecil
    • Dibandingkan dengan IOStreams, Boost Format, tinyformat, dan lainnya, ukuran kode per pemanggilan fungsi jauh lebih kecil
    • Beban template diminimalkan melalui type erasure
  • Formatting melalui type erasure

    • Fungsi format mendelegasikan pekerjaannya ke fungsi vformat
    • Iterator output dan tipe output lain juga dihapus tipenya melalui API buffer yang dirancang khusus
    • Penggunaan template diminimalkan untuk mengurangi ukuran biner dan waktu build
  • Contoh kode

    #include <fmt/base.h>
    int main() { fmt::print("The answer is {}.", 42); }
    
    • Kode di atas dikompilasi dengan ukuran yang jauh lebih kecil dibanding kode IOStreams
    • Bahkan dibandingkan dengan printf, ukurannya serupa sambil tetap memberikan type safety saat runtime
  • Optimasi ukuran biner

    • Pada 2020, dilakukan pekerjaan untuk menurunkan ukuran library hingga di bawah 100kB
    • Ukuran biner versi terbaru (11.0.2) adalah 75kB
    • Jika dukungan locale dinonaktifkan, ukurannya bisa diturunkan menjadi 71kB
  • Analisis menggunakan alat Bloaty

    • Formatting angka, terutama formatting angka floating-point, memakan porsi besar
    • Jika dukungan floating-point tidak dibutuhkan, fitur ini bisa dinonaktifkan
  • Optimasi formatting per tipe

    • Setel makro FMT_BUILTIN_TYPES ke 0 agar hanya tipe int yang ditangani secara khusus dan tipe lainnya diproses melalui API ekstensi
    • Dengan cara ini, ukuran biner bisa diturunkan menjadi 31kB
  • Menghapus artefak locale

    • Menggunakan makro FMT_USE_LOCALE untuk menghapus artefak locale dapat menurunkan ukuran menjadi 27kB
  • Trade-off antara kecepatan dan ukuran

    • Menggunakan makro FMT_OPTIMIZE_SIZE untuk mengoptimalkan ukuran dapat menurunkan ukuran biner menjadi 23kB
  • Menghapus dependensi library standar C++

    • Menonaktifkan exception dan menggunakan opsi -nodefaultlibs untuk menghapus dependensi runtime C++
    • Dengan memperkenalkan allocator kustom yang menggunakan malloc dan free, ukuran biner bisa diturunkan menjadi 14kB
  • Verifikasi hasil

    • Menggunakan perintah ldd untuk memastikan bahwa dependensi runtime C++ telah dihapus

Ringkasan GN⁺

  • Library {fmt} adalah library formatting yang menawarkan ukuran biner kecil dan type safety saat runtime
  • Melalui type erasure dan pengaturan makro, ukuran biner dapat dikurangi secara signifikan
  • Dengan menghapus dependensi library standar C++, library ini dapat digunakan secara efisien bahkan pada sistem embedded
  • Library dengan fungsi serupa antara lain IOStreams, Boost Format, dan tinyformat

1 komentar

 
GN⁺ 2024-09-02
Komentar Hacker News
  • {fmt} pada dasarnya independen terhadap locale
  • Pemformatan bilangan floating-point membutuhkan banyak kode
    • Proyek Dragonbox layak dibaca karena kodenya dioptimalkan
  • Alokator default C++ tidak menggunakan malloc dan free
    • Penasaran mengapa alokator default libc++ tidak memanggil malloc dan free milik libc
  • Ada proyek yang memungkinkan printf("Hello, World!\n") dengan ukuran file eksekusi 1008 byte
    • Sulit untuk dibandingkan secara langsung, tetapi layak dijadikan referensi
  • Pada sistem tempat program C dengan fungsi main kosong berukuran 6 kB, {fmt} menambahkan kurang dari 10 kB ke biner
    • Ini pengujian yang menarik
  • Saya sempat berharap pustaka pemformatan kecil hanya memerlukan sekitar 50 byte untuk menampilkan string dan integer
    • String terdiri dari sekitar 4 instruksi
    • Integer terdiri dari sekitar 20 instruksi
    • Floating-point tidak digunakan di banyak program, jadi sebaiknya hanya dikompilasi saat diperlukan
    • Jika ruang kode mikrokontroler hanya 2 kilobyte, Anda tidak akan menyertakan pustaka pemformatan string 14 kilobyte
  • Optimalisasi yang keluar dari kerangka pikir seperti ini sangat menyenangkan
  • Butuh waktu untuk menyadari bahwa "14k" berarti "14kB"
  • fmt selalu menimbulkan masalah
    • Di .NET, masalah yang sama juga terjadi
    • Jika banyak menangani pemformatan/parsing angka, linker akan memasukkan banyak kode terkait floating-point dan BigInt sehingga ukuran biner membesar