1 poin oleh GN⁺ 2 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • zig build kini secara internal dipisah menjadi proses configurer dan maker, dan graf build yang dibuat oleh build.zig diserialisasi menjadi file konfigurasi biner
  • Proses induk menyimpan file konfigurasi ke cache dan mengompilasi maker secara asinkron dalam mode Release; maker hanya perlu dikompilasi sekali ke cache global untuk tiap versi Zig
  • Saat pengguna mengubah build.zig, seluruh sistem build tidak lagi ikut dikompilasi, sehingga beban waktu untuk menambahkan fitur seperti --watch, --fuzz, dan --webui berkurang
  • Waktu eksekusi rata-rata zig build --help turun dari 150ms menjadi 14.3ms, dan siklus CPU, jumlah instruksi, serta referensi cache juga turun 94~96%
  • Sebagian besar API tetap kompatibel, tetapi pengamatan langsung terhadap b.args digantikan oleh addPassthruArgs(), dan Zig 0.17.0 dijadwalkan hadir dalam beberapa minggu

Perubahan struktur sistem build

  • Branch besar telah di-merge, dan internal zig build dipisah menjadi proses configurer dan proses maker
  • Pada struktur lama, file build.zig dan seluruh implementasi sistem build dikompilasi sebagai satu proses besar mode Debug, lalu build.zig membangun graf build di memori dan “build runner” mengeksekusinya
  • Pada struktur baru, build.zig dikompilasi sebagai proses configurer mode Debug yang kecil, dan graf build diserialisasi menjadi file konfigurasi biner
  • Proses induk zig build mendeteksi file konfigurasi, menyimpannya ke cache untuk eksekusi berikutnya, dan mengompilasi maker yang bertugas mengeksekusi graf build secara asinkron dalam mode Release
  • Setelah file konfigurasi dan kompilasi maker siap, maker dijalankan dengan menerima file konfigurasi tersebut; berkat cache global, maker hanya perlu dikompilasi sekali untuk tiap zig version

Dampak peningkatan kecepatan

  • Tujuan utamanya adalah meningkatkan kecepatan zig build, dan saat pengguna mengubah build.zig, seluruh sistem build tidak lagi ikut dikompilasi
  • Ini makin penting agar waktu zig build tidak ikut bertambah meskipun fitur sistem build bertambah dengan hadirnya --watch, --fuzz, dan --webui
  • Jika dinilai tidak ada perubahan, logika build.zig tidak perlu dijalankan ulang dan konfigurasi sebelumnya bisa dipakai kembali
  • Misalnya, walaupun -freference-trace ditambahkan ke baris perintah zig build, logika build.zig tidak akan dijalankan ulang tanpa perlu
  • Karena proses yang benar-benar mengeksekusi graf build dikompilasi dengan optimisasi aktif, tahap eksekusinya juga menjadi lebih cepat

Hasil benchmark

  • Waktu eksekusi rata-rata zig build --help turun dari 150ms pada struktur lama menjadi 14.3ms pada struktur baru
  • Waktu wall-clock turun 90.4% dari 150ms ke 14.3ms, dan siklus CPU turun 95.9% dari 593M ke 24.1M
  • Jumlah instruksi turun 95.6% dari 995M ke 43.7M, dan referensi cache turun 94.3% dari 25.8M ke 1.46M
  • RSS puncak turun 7.4% dari 84.8MB ke 78.5MB
  • Perbedaan terbesar berasal dari perubahan pendekatan: sebelumnya logika build.zig dijalankan pada setiap perintah zig build, sekarang konfigurasi serial hasil cache bisa digunakan kembali

Dampak pada alat dan kompatibilitas

  • Alat pihak ketiga seperti ZLS bisa mendapat manfaat dengan mengonsumsi file konfigurasi yang telah diserialisasi, alih-alih mem-fork dan memelihara build runner
  • Mekanisme internal berubah besar, tetapi dari sudut pandang API sebagian besar tetap kompatibel
  • Pengecualian dirangkum dalam perubahan yang dicatat pada PR yang di-merge

Perubahan breaking utama

  • Perubahan yang kemungkinan paling sering ditemui banyak pengguna adalah dihapusnya pola yang mengamati b.args secara langsung
  • Kode lama:
if (b.args) |args| {
    run_cmd.addArgs(args);
}
  • Kode baru:
run_cmd.addPassthruArgs();
  • Dengan perubahan ini, skrip build tidak lagi bisa mengamati argumen tersebut, sehingga satu kemampuan dihapus
  • Sebagai gantinya, perubahan pada argumen itu tidak lagi mengharuskan skrip build dibangun ulang dari sumber

Pengujian dan jadwal rilis

  • Pengguna yang ingin memengaruhi arah Zig dapat menaikkan proyek mereka ke versi pengembangan untuk mencoba perubahan baru dan memberi masukan
  • Zig 0.17.0 dijadwalkan rilis dalam beberapa minggu
  • Karena belum sempat diuji lebih awal, sekalipun build rusak di 0.17.0, masih ada cukup kesempatan agar perbaikannya masuk ke tag 0.17.1

1 komentar

 
GN⁺ 2 jam lalu
Komentar Hacker News
  • Saya sempat memigrasikan sebagian kode ke Zig 0.16.0, dan hasilnya cukup memuaskan
    Bagian yang terdampak memang cukup banyak, tetapi perubahannya sendiri bagus dan tampak mengarah ke masa depan bahasa yang lebih cerah
    Khususnya, mekanisme I/O baru memungkinkan kode yang efisien dengan bentuk yang rapi, baik untuk implementasi single-thread, multi-thread, maupun event loop
    Kalau belum mencoba Zig lagi sejak 0.16.0, saya sangat menyarankan untuk melihatnya. Catatan rilis kali ini sangat panjang
    https://ziglang.org/download/0.16.0/release-notes.html

    • Saya rasa ini masih belum bisa disebut “sangat efisien”. I/O masih tetap dynamic dispatch dan ada beberapa lapis indireksi
      Setahu saya malah lebih lambat dibanding sebelumnya
      Saya berharap di rilis-rilis berikutnya masalah “target dispatch diketahui saat compile time tapi tetap dinamis” bisa diperbaiki sehingga kehilangan efisiensi berkurang
    • Saya agak kesulitan memahami bagaimana mekanisme I/O baru bekerja, terutama async/await
      Saya berasumsi bahwa saat io.async dipanggil pada implementasi I/O berbasis event loop, itu secara internal memulai sesuatu seperti “task”, dan future adalah handle-nya
      Bagian yang tidak saya pahami adalah saat future.await(io) dipanggil. Apakah implementasi I/O entah bagaimana menangguhkan fungsi saat ini lalu melanjutkannya kembali ketika future selesai? Kalau begitu, apakah itu berarti semua fungsi di Zig adalah stackless coroutine?
    • Suatu saat saya mungkin akan bisa memakai fitur-fitur baru seperti ini, tetapi karena stabilitas dan target yang belum terlalu teruji, saya akhirnya memakai .use_llvm = true di build Zig
  • Setelah memakai Zig selama beberapa bulan, saya jadi yakin ini adalah bahasa yang hebat untuk membuat tool
    Enak dipakai saat ingin bebas mengutak-atik ide secara kasar, dan di setiap titik macet biasanya sudah ada solusi nyaman yang dipikirkan oleh para pembuatnya
    Tapi tetap tidak memaksa cara penggunaan bahasa yang “benar”
    Sekarang ini jadi bahasa default saya untuk “ngoprek di garasi”

    • Kalau dibilang tidak memaksakan cara pakai yang “benar”, rasanya kurang tepat, karena variabel yang tidak dipakai tidak diizinkan dan juga tidak ada komentar multi-baris
      Buat saya itu masalah produktivitas yang cukup besar
    • Memangnya sebagus itu?
      Bahasa default saya untuk “ngoprek di garasi” adalah Python. Sintaksnya ringan, enak dipakai tanpa banyak gangguan, standard library-nya kaya, dan kalau kurang biasanya ada paketnya
      Apa kelebihan Zig?
    • Hambatan utama saya di sini adalah, bagi saya Mojo tampaknya akan jadi bahasa default untuk eksperimen
    • Memang jelas ini bahasa yang bagus untuk bereksperimen, tetapi tim dan komunitas Zig punya preferensi yang sangat kuat soal cara memakai bahasa ini dengan “benar”
  • Setelah menonton video wawancara Andrew Kelley, saya jadi ingin belajar Zig: https://www.youtube.com/watch?v=iqddnwKF8HQ

    • Saya sangat menghormati Andrew dan juga senang memakai Zig, tetapi wawancara itu buruk sekali
      Jawaban Andrew bagus, tetapi suasana keseluruhannya terasa terlalu menjilat
  • Saya ingin mencoba Zig, tetapi bahasanya masih berubah terlalu cepat
    Karena setiap rilis mematahkan API, sulit untuk sekaligus mengikuti proses belajar bahasa, debugging build system, dan mengimplementasikan hal yang benar-benar ingin dibuat
    Setelah melihat wawancara JetBrains, saya memang ingin mencoba lagi, tetapi mungkin saya akan menunggu sampai 1.0 keluar

  • Sudah lama saya memikirkan ide yang saya sebut pemrograman ganda
    Maksudnya, stack hanya terdiri dari dua bahasa: satu bahasa tingkat tinggi dan satu bahasa tingkat rendah
    Struktur kerjanya adalah menulis sebanyak mungkin dengan bahasa tingkat tinggi, lalu turun ke bahasa tingkat rendah hanya saat perlu
    Masalahnya, kalau Anda belum benar-benar sangat mahir dengan bahasa tingkat rendah itu, besar kemungkinan Anda harus membiasakan diri lagi dengannya sebelum bisa mengerjakan bagian low-level
    Karena itu C++ atau Rust jadi lebih sulit dipakai daripada C, sehingga bagi saya C menjadi pilihan default. Tapi C juga punya masalah-masalah yang sudah terkenal
    Zig tampaknya bisa mengisi titik yang pas itu karena cukup sederhana untuk mudah dipakai lagi setelah jeda panjang, sambil tetap punya alat modern yang mempermudah pemrograman

    • Idenya menarik, tetapi saya justru berpikir sebaliknya
      Sebisa mungkin kerjakan sebanyak mungkin di bahasa tingkat rendah, lalu naik ke bahasa tingkat tinggi hanya saat kenyamanannya memang sepadan dengan biayanya
      Roc memungkinkan hal ini. Semua program memiliki platform yang ditulis dalam bahasa tingkat rendah, dan program Roc menggunakan API yang diekspos oleh platform tersebut
      https://www.roc-lang.org/
      Tentu saja, bagaimana menyeimbangkan high-level dan low-level itu pilihan masing-masing
    • Setahu saya SpaCy dikembangkan dengan cara seperti itu
      Modelnya diimplementasikan dengan Cython, sementara API untuk pengguna diberikan dalam Python
    • C# cukup dekat dengan tujuan itu
    • Atau cukup pakai satu bahasa yang bagus untuk pemrograman tingkat tinggi dan rendah sekaligus, seperti Rust
      Sekarang saya melakukan semuanya dengan Rust, dan terutama berkat type system-nya yang mirip OCaml, saya belum menemukan hal yang tidak bisa saya lakukan
    • Kombinasi seperti ini dulu umum dengan C dan Lua
      Lua memang dirancang sebagai bahasa embedded, jadi bagus untuk interoperabilitas, dan sekaligus cukup high-level sehingga mudah dipakai
      Ada alasan mengapa Factorio memakai Lua sebagai bahasa scripting
  • Salah satu hal yang saya suka dari pengembangan Zig adalah mereka mencurahkan upaya yang luar biasa besar pada tooling dan feedback loop pengembang, alih-alih sekadar menambah fitur bahasa
    Bahasa baru masih bisa bertahan walau untuk sementara belum punya satu fitur tertentu
    Tetapi jauh lebih sulit bertahan kalau compile, link, dan pembaruan dependensi terasa lambat setiap saat
    Fokus untuk membuat siklus pengembangan berada di level milidetik, bukan detik, tampak seperti taruhan jangka panjang yang bagus

  • Saya kaget melihat kalimat “berencana merilis 0.17.0 dalam beberapa minggu”
    Bukankah 0.16 memakan waktu lebih dari setahun?
    Saya tidak menyangka rilis 0.17 akan secepat ini, jadi sangat senang mengetahuinya hari ini

  • Kedengarannya seperti kabar baik. Waktu kompilasi Zig sudah sangat bagus, dan perubahan ini sepertinya akan membuatnya lebih baik lagi

    • Menurut pengalaman saya, pernyataan itu saat ini masih lebih dekat ke target daripada kenyataan.
      Ini jelas target yang penting, dan milestone untuk mencapainya juga sudah jelas, tetapi dalam praktiknya sulit menyebut waktu tunggu yang menyakitkan saat kompilasi pertama proyek kosong atau saat ZLS dibangun ulang setelah direnv allow sebagai sesuatu yang “sangat bagus”
    • Bahkan kalau saya membuat satu file dengan tes dummy lalu menjalankan zig test file.zig -OReleaseSafe, di komputer saya tetap butuh beberapa detik.
      Setiap kali file diubah, waktu yang sama terus dibutuhkan. Saya memakai 0.16 atau master, jadi bukan karena toolchain yang usang, dan ini juga di lingkungan Linux.
      Bahasa Zig sendiri benar-benar menyenangkan untuk ditulis, tetapi menurut saya kompiler dan standard library-nya belum dikembangkan dengan pendekatan yang cukup konservatif.
      Saat mulai dari hello world, mungkin masalah seperti ini tidak terasa, tetapi kalau ingin melakukan fuzz testing atau benchmark, kita jadi ingin menjalankan binary yang dioptimalkan.
      Lalu kompilasi kode yang relatif kecil pun terasa sangat menjengkelkan.
      Sebagai perbandingan, saya menganggap Zig jauh lebih baik sebagai bahasa dibanding Rust/C++/C, tetapi masalah seperti ini pada praktiknya hampir tidak pernah muncul di Rust/C++/C. Untuk C/C++, asumsinya memakai clang/gcc/ninja dan sejenisnya.
      Di komputer yang sama, dengan Ninja/Python/clang saya bisa menyiapkan, membangun (-O2 atau -O3), dan menguji proyek C++ sekitar 10 ribu baris hanya dalam 200ms
    • Untungnya, kecepatan kompilasi ala 90-an perlahan mulai kembali
  • Akan sangat bagus kalau Zig punya mekanisme resmi untuk mengekspor stub library Linux.
    Kemampuan cross-compilation Zig dan kemampuannya menargetkan versi glibc sesuka hati itu benar-benar seperti sihir.
    Saya memanfaatkan “sihir” ini dalam build system C++ terpisah, tetapi untuk mendapatkan stub library itu dari Zig saya harus mencari jalan memutar.
    Akan bagus kalau ini tersedia sebagai output resmi

  • Memangnya apa alasan sampai ingin memakai ini alih-alih Node.js dan TypeScript?

    • Saya iri dengan cara berpikir seperti itu. Kalau saya juga begitu, rasanya saya sudah punya jauh lebih banyak aplikasi yang dirilis
    • Saya sarankan coba pakai Ghostty yang ditulis dengan Zig sebentar, lalu bandingkan dengan terminal seperti Hyper yang ditulis dengan JavaScript
    • Bukannya keduanya memang untuk ranah yang benar-benar berbeda?
    • Kalau pekerjaan yang dilakukan memang cocok untuk Node dan TypeScript, menurut saya tidak ada alasan memakai Zig selain untuk belajar atau karena penasaran.
      Kalau tidak butuh tetes terakhir dari performa serta tata letak dan kontrol memori, memakai Zig justru punya lebih banyak kekurangan.
      Untuk pekerjaan CRUD, tugas “enterprise”, atau website, keunggulan Zig hampir tidak terasa
    • Di sistem embedded, memorinya terlalu terbatas sehingga Node tidak bisa dijalankan.
      Program Zig yang sudah dikompilasi bisa hanya berukuran beberapa KB tanpa dependensi.
      Akses array yang ditulis dalam bahasa level rendah bisa dioptimalkan dengan SIMD dan paralelisasi, dan untuk pekerjaan yang sama bisa beberapa orde magnitudo lebih cepat daripada JavaScript.
      Perbedaannya besar untuk pemrosesan teks, manipulasi gambar, pemrosesan video, hashing, dan sebagainya.
      Alasan untuk tidak memakai JavaScript pada dasarnya nyaris tak terbatas