7 poin oleh GN⁺ 2025-12-24 | 2 komentar | Bagikan ke WhatsApp
  • MicroQuickJS (MQuickJS) adalah engine JavaScript ultra-ringan yang dirancang untuk sistem embedded, dan dapat berjalan hanya dengan sekitar 10kB RAM dan 100kB ROM
  • Untuk mempertahankan kecepatan yang mirip dengan QuickJS sambil mengurangi penggunaan memori, engine ini mengadopsi tracing garbage collector dan penyimpanan string UTF-8
  • Bahasa yang didukung adalah subhimpunan JavaScript terbatas yang mendekati ES5, dan hanya mengizinkan strict mode yang melarang sintaks yang rawan kesalahan
  • Melalui alat REPL mqjs, pengguna dapat menjalankan skrip, menyimpan bytecode, dan menetapkan batas memori; bytecode yang dihasilkan juga dapat dijalankan langsung dari ROM
  • Seluruh engine dan standard library tinggal di ROM untuk mewujudkan inisialisasi cepat dan konsumsi memori rendah, sehingga meningkatkan efisiensi eksekusi JavaScript di lingkungan embedded

Pengenalan

  • MicroQuickJS (MQuickJS) adalah engine JavaScript yang menargetkan sistem embedded, dan berjalan dengan 10kB RAM serta 100kB ROM (termasuk kode ARM Thumb-2)
    • Kecepatannya mirip dengan QuickJS
  • Hanya mendukung subhimpunan yang mendekati ES5, dan hanya berjalan dalam strict mode yang melarang sintaks yang tidak efisien atau rawan kesalahan
  • Meskipun berbagi sebagian kode dengan QuickJS, struktur internalnya dirancang sepenuhnya berbeda untuk menghemat memori
    • Menggunakan tracing garbage collector, tanpa memakai stack CPU, dan penyimpanan string UTF-8

REPL

  • Perintah REPL adalah mqjs, dan mendukung eksekusi skrip, evaluasi, mode interaktif, pengaturan batas memori, serta penyimpanan bytecode
    • Contoh: ./mqjs --memory-limit 10k tests/mandelbrot.js
  • Dengan opsi -o, bytecode hasil kompilasi dapat disimpan ke file
    • Bytecode yang disimpan dapat dijalankan dengan ./mqjs mandelbrot.bin
    Iklan
  • Bytecode berbeda tergantung endianness dan panjang word CPU (32/64-bit), dan opsi -m32 dapat digunakan untuk membuat bytecode 32-bit
  • Dengan opsi --no-column, nomor kolom pada informasi debug dapat dihapus

Strict mode

  • Hanya strict mode yang diizinkan; penggunaan kata kunci with tidak didukung, dan variabel global wajib dideklarasikan dengan var
  • Hole pada array tidak diizinkan
    • Contoh: a[10] = 2 akan menimbulkan TypeError
    • Jika membutuhkan array dengan hole, gunakan objek biasa
  • Hanya global eval yang didukung, tanpa akses ke variabel lokal
  • Value boxing tidak didukung (new Number(1) dan sejenisnya)

Subhimpunan JavaScript

  • Berbasis strict mode, dengan fokus pada kompatibilitas ES5
  • Objek Array tidak memiliki hole, dan akses indeks di luar rentang akan menghasilkan error
  • for in hanya mengiterasi properti milik objek itu sendiri, sedangkan for of hanya didukung untuk array
  • Global object ada, tetapi getter/setter tidak didukung, dan properti yang dibuat langsung tidak diekspos sebagai variabel global
  • Regular expression (Regexp) hanya membedakan huruf besar/kecil untuk ASCII, dan /./ mencocokkan berdasarkan code point Unicode, bukan UTF-16
  • Fungsi string hanya memproses ASCII (toLowerCase, toUpperCase)
  • Date hanya mendukung Date.now()
  • Fitur tambahan yang didukung:
    • for of, Typed arrays, literal string \u{hex}
    • Fungsi Math: imul, clz32, fround, trunc, log2, log10
    • operator eksponen, flag Regexp (s, y, u), fungsi string (replaceAll, trimStart, trimEnd), globalThis
Iklan

C API

  • Ketergantungan pada library C diminimalkan, tanpa penggunaan malloc, free, atau printf
  • Buffer memori harus disediakan secara langsung, dan engine hanya mengalokasikan memori di dalam buffer tersebut
    • Contoh: ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)
  • Karena mekanisme garbage collection yang digunakan, pemanggilan JS_FreeValue() tidak diperlukan
  • Karena alamat objek dapat berpindah setiap kali alokasi, penggunaan pointer JSValue direkomendasikan
    • JS_PushGCRef() / JS_PopGCRef() untuk manajemen referensi yang aman
  • Standard library dikompilasi sebagai struktur C yang dapat disimpan di ROM, sehingga mencapai inisialisasi cepat dan penggunaan RAM rendah
  • Eksekusi bytecode dapat dilakukan dari ROM, lalu direlokasi dengan JS_RelocateBytecode() dan dijalankan dengan JS_LoadBytecode() serta JS_Run()
  • Library matematika (libm.c) dan emulator floating-point disertakan

Struktur internal dan perbandingan dengan QuickJS

  • Garbage collection: menggunakan tracing GC terkompresi alih-alih reference counting
    • Mencegah fragmentasi memori dan mengecilkan ukuran objek
  • Representasi nilai: dirancang sesuai ukuran word CPU (32/64-bit)
    • Dapat menyimpan integer 31-bit, code point Unicode, floating-point, dan pointer blok memori
  • String disimpan dalam UTF-8, lebih efisien dibanding pendekatan array 8/16-bit milik QuickJS
  • Fungsi C dapat disimpan sebagai nilai tunggal, tetapi tidak bisa ditambahi properti
  • Standard library tinggal di ROM, dan objek RAM diminimalkan untuk memungkinkan inisialisasi engine yang cepat
  • Bytecode berbasis stack, dan diperlakukan read-only melalui tabel referensi tidak langsung
    • Nomor baris dan kolom dikompresi dengan kode Golomb
    Iklan
  • Compiler mirip dengan QuickJS tetapi menggunakan parser non-rekursif untuk membatasi penggunaan stack C
    • Menghasilkan bytecode dalam single pass tanpa parse tree

Pengujian dan benchmark

  • Pengujian dasar: make test
  • Microbenchmark QuickJS: make microbench
  • Benchmark Octane (versi modifikasi untuk strict mode) dapat diunduh terpisah
    • Jalankan: make octane

Lisensi

  • Didistribusikan di bawah lisensi MIT
  • Hak cipta source code dimiliki oleh Fabrice Bellard dan Charlie Gordon

2 komentar

 
GN⁺ 2025-12-24
Komentar Hacker News
  • Kalau ada ini pada 2010, sepertinya bahasa scripting Redis akan jadi JavaScript, bukan Lua
    Lua dipilih bukan karena alasan kebahasaan, melainkan karena keterbatasan implementasi (kecil, cepat, dan berbasis ANSI-C)
    Beberapa ide di Lua memang bagus, tetapi secara pribadi saya merasa penyimpangannya dari sintaks keluarga Algol itu tidak perlu
    Kebingungan yang muncul karena harus mempelajari konsep abstraksi baru seperti di SmallTalk atau FORTH memang sepadan, tetapi menurut saya perubahan di Lua tidak punya alasan sekuat itu

    • Saya juga tidak terlalu suka sintaks Lua, tetapi saya rasa alasan para pengembang memilihnya cukup masuk akal
      Lua adalah satu-satunya bahasa ringan yang mendukung tail call optimization (TCO), sehingga program bisa ditulis murni rekursif tanpa loop
      JavaScript tidak punya optimisasi ini, jadi pendekatan seperti itu tidak memungkinkan
      Lua juga sangat cocok untuk penulisan compiler. Alasannya karena strukturnya banyak yang rekursif
      Untuk scripting Redis, JS mungkin memang lebih cocok, tetapi sayang kalau Lua diremehkan
    • Mengingat Lua pertama kali muncul pada 1993, sintaksnya sebenarnya cukup tradisional untuk zamannya
      Di Brasil, Pascal dan Ada lebih umum dipakai daripada C, jadi pengaruhnya datang dari sana
      Ruby dan Perl juga muncul pada era serupa, tetapi mencoba perubahan sintaks yang jauh lebih radikal
    • Awalnya saya mau bilang bahwa saya belajar Lua dengan mudah saat umur 13 tahun, lalu berhenti ketika sadar bahwa penulis komentar itu ternyata antirez sendiri
    • Mungkin ini tidak menyelesaikan masalah sintaks, tetapi konsep “language skins” terasa menarik
      Hampir tidak ada yang mencoba memisahkan parser dan lexer sambil menukar token seperti {} dengan then/end
      Diskusi terkait: thread HN, diskusi Reddit
    • Saya penasaran apakah Tcl pernah dipertimbangkan sebagai bahasa scripting Redis. Soalnya itu bahasa embedded yang asli
  • Engine ini membatasi JS dengan cara yang dulu saya inginkan saat mengerjakan JSC
    Di web, pembatasan seperti ini tidak mungkin dilakukan karena kompatibilitas, tetapi di lingkungan embedded justru bisa jadi desain yang menyenangkan

    • Kita sebenarnya sudah punya engine JS yang tidak punya pembatasan seperti ini
    • Saya penasaran bagaimana nasib pekerjaan multithreading di JSC. Apakah berhenti setelah Anda meninggalkan Apple, atau kodenya masih ada?
  • Saya membuat playground untuk langsung menjalankan MicroQuickJS di browser
    Versi WebAssembly MicroQuickJS
    Sebagai referensi, ada juga versi QuickJS asli
    QuickJS berukuran 2.28MB, sedangkan MicroQuickJS hanya 303KB, jadi jauh lebih ringan

    • Sepertinya ukurannya membesar karena build menyertakan informasi nama dan semacamnya
      Opsi emcc -O3 atau tambahan --closure 1 sepertinya bisa mengecilkannya lagi
      QuickJS sudah dioptimalkan, dan hanya MicroQuickJS yang masih punya ruang untuk diperbaiki
  • Seperti kutipan terkenal Jeff Atwood, “setiap aplikasi yang bisa ditulis dengan JavaScript pada akhirnya akan ditulis dengan JavaScript
    Sekarang tampaknya itu juga berlaku untuk sistem embedded
    Wiki Jeff Atwood

  • Sayang sekali proyek ini diunggah tanpa riwayat commit
    Saya ingin melihat seberapa cepat pengembang level ini bisa menyelesaikan proyek
    Toh karena basisnya QuickJS, perbandingan seperti itu mungkin juga tidak terlalu berarti

    • Ungkapan “public repository of…” memberi kesan bahwa riwayat kerja yang sebenarnya mungkin ada di repositori privat
    • Mungkin saja dia memang langsung menuntaskannya sekali jadi
  • Saya penasaran apakah ini bisa jadi cara paling ringan untuk menyelesaikan tantangan JS YouTube di yt-dlp
    Lihat dokumentasi EJS yt-dlp
    QuickJS sudah didukung

    • Kemungkinannya kecil. Soalnya ini hanya mendukung implementasi parsial setingkat ES5
      Teka-teki JS dari YouTube terlalu rumit, sampai emulator JS yang dibuat dengan Python saja akhirnya menyerah
    • Karena baru mengimplementasikan ES5, rasanya sulit dipakai secara realistis
  • Saya tidak terlalu paham sistem embedded, tetapi saya penasaran apakah engine seperti ini bisa memungkinkan ESP32 atau Arduino diprogram dengan JavaScript
    Seperti MicroPython

    • Sudah ada beberapa proyek serupa
    • Engine XS dari Moddable/Kinoma mendukung ES6 ke atas
      MicroQuickJS hanya mengimplementasikan sebagian ES5 dan tidak menyediakan binding lingkungan
    • Dulu ada board pemrograman JS bernama Tessel
      Ia menjalankan kode JS dengan mengubahnya menjadi bytecode VM Lua, dan itu pendekatan yang cukup cerdas
      Belakangan saya sempat menulis ulang CLI Node 0.8 lama itu dalam Rust, tetapi akhirnya perangkatnya kembali masuk laci
    • Intinya adalah arsitektur tanpa malloc(). Itu yang membuka kemungkinan ini
  • Timing memang sangat penting. Waktu diposting tadi malam, tidak ada reaksi sama sekali

    • Mungkin memang cuma soal keberuntungan
    • Orang lain juga sempat mencoba tetapi tetap tidak ada respons
      Ada strategi untuk memposting ulang pada jam pagi di AS, atau memposting ulang secara berkala
  • Fabrice Bellard adalah salah satu programmer paling produktif dan paling serbabisa yang masih hidup
    Karya terkenalnya: FFmpeg, QEMU, JSLinux, TCC, QuickJS
    Sosok yang legendaris

    • Di balik tingginya penghargaan terhadap dirinya, justru tidak banyak yang tertarik pada cara dia mengembangkan software
      Pendekatannya dalam membuat program lengkap dengan dependensi dan alat seminimal mungkin terasa sangat mengesankan
    • Kadang saya berpikir dia itu bukan satu orang, melainkan codename untuk sekelompok hacker berpengalaman
      Soalnya kalau benar satu orang, dia pasti perlu tidur juga
    • Dia juga mengembangkan sendiri engine inferensi LLM dan merawatnya sejak era GPT-2
      ts_server, TextSynth
    • Hal yang menarik, sebagian besar program buatannya tidak berurusan dengan antarmuka pengguna yang berpusat pada GUI
      Sepertinya dia lebih suka struktur di mana pengguna mengatur parameter lalu program berjalan tuntas dengan sendirinya
    • Ia juga pernah 3 kali menjuarai International Obfuscated C Code Contest (IOCCC)
      Daftar pemenang IOCCC
  • Sangat mengesankan bahwa “JS bisa dikompilasi dan dijalankan bahkan di RAM 10kB”
    Ini terasa pas sekali untuk masa sekarang, ketika RAM kembali mahal
    Saya penasaran apakah ini bisa dimasukkan ke Chromium atau Electron

    • Karena kompatibilitas web, sepertinya sulit, tetapi penghematan memori di Chromium pun mungkin tidak akan terlalu besar anyway
 
xguru 2025-12-24

Untuk pengenalan tentang Fabrice Bellard, silakan lihat yang dulu pernah saya tulis di komentar. Orang ini benar-benar konsisten sekaligus monster yang mengagumkan..
https://id.news.hada.io/topic?id=59#cid51