2 poin oleh GN⁺ 2024-11-30 | Belum ada komentar. | Bagikan ke WhatsApp
  • Ini adalah benchmark yang membandingkan penggunaan memori untuk tugas serentak dari 1 hingga 1 juta berdasarkan bahasa dan runtime terbaru pada akhir 2024, dan disebutkan bahwa hasil terbaru dapat dilihat di halaman Take 2 terpisah
  • Semua pengujian diseragamkan dengan struktur yang sama: setiap tugas menunggu selama 10 detik lalu program menunggu hingga seluruh tugas selesai, untuk membandingkan karakteristik memori coroutine, tugas asinkron, goroutine, dan virtual thread alih-alih banyak thread
  • Objek perbandingan mencakup Rust tokio·async_std, C# dan NativeAOT, NodeJS, Python asyncio, Go goroutine, Java virtual thread, serta Java GraalVM native image, dan seluruh kode dipublikasikan di GitHub
  • Seiring jumlah tugas bertambah, besarnya kenaikan memori sangat berbeda antar-runtime, dan pada 1 juta tugas C# menunjukkan penggunaan memori paling rendah, sementara Rust juga tetap efisien
  • .NET terbaru menunjukkan peningkatan besar dan NativeAOT bersaing dengan Rust, tetapi Go goroutine menggunakan memori lebih dari 13 kali hasil terbaik pada 1 juta tugas, dan lebih dari 2 kali dibanding Java

Metode benchmark dan materi publik

  • Ini adalah hasil pengulangan perbandingan konsumsi memori pemrograman asinkron 2023 menggunakan versi bahasa terbaru per akhir 2024
  • Di bagian atas ada petunjuk untuk melihat hasil terbaru di How Much Memory Do You Need in 2024 to Run 1 Million Concurrent Tasks? - Take 2
  • Program pengujian membuat N tugas serentak yang diterima lewat argumen command line, lalu setiap tugas menunggu selama 10 detik dan program berakhir setelah semua tugas selesai
  • Fokus perbandingan ada pada model konkurensi berbasis coroutine, bukan banyak thread
  • Seluruh kode benchmark dipublikasikan di async-runtimes-benchmarks-2024

Bahasa dan runtime yang dibandingkan

  • Rust dibandingkan dengan dua runtime asinkron: tokio dan async_std
    • Keduanya adalah runtime asinkron yang banyak digunakan di Rust
  • C# mendukung async/await secara langsung, dan menjalankan tugas dengan Task.Delay serta Task.WhenAll
    • NativeAOT yang disediakan mulai .NET 7 juga ikut dibandingkan
    • NativeAOT mengompilasi langsung ke biner final agar kode terkelola dapat berjalan tanpa VM
  • NodeJS membungkus setTimeout dengan util.promisify, lalu menunggu menggunakan Promise.all
  • Python menggunakan asyncio.sleep dan asyncio.gather
  • Go menggunakan goroutine sebagai komponen konkurensi, dan menunggu semua tugas selesai dengan WaitGroup alih-alih await individual
  • Java menggunakan virtual thread yang tersedia mulai JDK 21
    • native image dari GraalVM juga ikut dibandingkan
    • GraalVM native image dimasukkan sebagai konsep yang mirip dengan .NET NativeAOT

Lingkungan pengujian

  • Perangkat keras: 13th Gen Intel Core i7-13700K
  • Sistem operasi: Debian GNU/Linux 12(bookworm)
  • Rust: 1.82.0
  • .NET: 9.0.100
  • Go: 1.23.3
  • Java: openjdk 23.0.1 build 23.0.1+11-39
  • Java(GraalVM): java 23.0.1 build 23.0.1+11-jvmci-b01
  • NodeJS: v23.2.0
  • Python: 3.13.0
  • Jika memungkinkan, semua program dijalankan dalam release mode
  • Karena tidak ada libicu di lingkungan pengujian, dukungan internasionalisasi dan globalisasi dinonaktifkan

Perubahan memori saat jumlah tugas bertambah

  • Jejak minimum: 1 tugas

    • Untuk melihat memori yang dibutuhkan runtime itu sendiri, pengujian dimulai dengan hanya 1 tugas
    • Rust, C# NativeAOT, dan Go dikompilasi secara statis menjadi biner native sehingga menggunakan memori sangat sedikit dan menunjukkan hasil yang mirip
    • Java GraalVM native image juga memberikan hasil yang baik, tetapi menggunakan memori sedikit lebih banyak daripada target kompilasi statis lainnya
    • Program yang berjalan di atas platform terkelola atau interpreter mengonsumsi lebih banyak memori
    • Pada bagian ini, Go menunjukkan jejak paling kecil
    • Java GraalVM menggunakan memori jauh lebih banyak daripada OpenJDK Java, meski ini mungkin bisa disetel lewat konfigurasi
  • 10 ribu tugas

    • Dua benchmark Rust tidak menunjukkan peningkatan besar dari jejak minimum bahkan pada 10 ribu tugas, dan tetap mempertahankan penggunaan memori yang sangat rendah
    • C# NativeAOT juga hanya menggunakan sekitar 10MB memori dan mengikuti Rust dari dekat
    • Penggunaan memori Go meningkat tajam pada rentang ini
    • virtual thread Java GraalVM native image tampak lebih ringan daripada Go goroutine
    • Go dan Java GraalVM native image dikompilasi secara statis menjadi biner native, tetapi tetap menggunakan RAM lebih banyak daripada C# yang berjalan di atas VM
  • 100 ribu tugas

    • Saat jumlah tugas naik menjadi 100 ribu, konsumsi memori semua bahasa mulai meningkat tajam
    • Rust dan C# tetap menunjukkan hasil yang baik pada rentang ini
    • C# NativeAOT menggunakan RAM lebih sedikit daripada Rust dan memimpin semua bahasa
    • Program Go pada titik ini tertinggal bukan hanya dari Rust, tetapi juga dari Java, C#, dan NodeJS
    • Satu pengecualian adalah Java yang dijalankan di GraalVM, yang tidak termasuk di antara yang mengalahkan Go
  • 1 juta tugas

    • Pada 1 juta tugas, C# jelas unggul atas semua bahasa lain
    • Rust, seperti yang diperkirakan, terus menunjukkan hasil baik dari sisi efisiensi memori
    • Kesenjangan antara Go dan runtime lain makin besar
    • Go menggunakan memori lebih dari 13 kali hasil terbaik
    • Bahkan dibanding Java, Go memakai memori lebih dari 2 kali lebih banyak, memperlihatkan hasil yang berbeda dari anggapan umum bahwa JVM boros memori dan Go itu ringan

Pengamatan akhir

  • Jika jumlah tugas serentak sangat banyak, meski tiap tugas tidak melakukan komputasi yang rumit, totalnya tetap bisa menggunakan memori yang besar
  • Trade-off tiap runtime bahasa muncul dengan cara yang berbeda
    • Pada jumlah tugas sedikit, ia bisa ringan dan efisien
    • Saat diskalakan ke ratusan ribu tugas, lonjakan memori bisa menjadi besar
  • Berdasarkan compiler dan runtime terbaru, .NET menunjukkan peningkatan besar
  • .NET NativeAOT memberikan hasil yang kompetitif dengan Rust
  • GraalVM native image milik Java juga menunjukkan hasil baik dalam efisiensi memori
  • Go goroutine terus menunjukkan hasil yang tidak efisien dari sisi konsumsi sumber daya

Belum ada komentar.

Belum ada komentar.