Kapasitas memori yang dibutuhkan untuk menjalankan 1 juta tugas serentak pada 2024
(hez2010.github.io)- 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, Pythonasyncio, 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
Ntugas 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:
tokiodanasync_std- Keduanya adalah runtime asinkron yang banyak digunakan di Rust
- C# mendukung
async/awaitsecara langsung, dan menjalankan tugas denganTask.DelaysertaTask.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
setTimeoutdenganutil.promisify, lalu menunggu menggunakanPromise.all - Python menggunakan
asyncio.sleepdanasyncio.gather - Go menggunakan goroutine sebagai komponen konkurensi, dan menunggu semua tugas selesai dengan
WaitGroupalih-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
libicudi 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.