Apa yang mengatur "kecepatan" bahasa pemrograman?
Tidak ada yang namanya "kecepatan" dari bahasa pemrograman. Hanya ada kecepatan program tertentu yang ditulis oleh progammer tertentu yang dieksekusi oleh versi tertentu dari implementasi tertentu dari mesin eksekusi tertentu yang berjalan dalam lingkungan tertentu.
Mungkin ada perbedaan kinerja yang sangat besar dalam menjalankan kode yang sama yang ditulis dalam bahasa yang sama pada mesin yang sama menggunakan implementasi yang berbeda. Atau bahkan menggunakan versi berbeda dari implementasi yang sama. Misalnya, menjalankan benchmark ECMAScript yang sama persis pada mesin yang sama persis menggunakan versi SpiderMonkey dari 10 tahun yang lalu vs versi dari tahun ini mungkin akan menghasilkan peningkatan kinerja di mana saja antara 2 × –5 ×, bahkan mungkin 10 ×. Apakah itu berarti ECMAScript 2x lebih cepat dari ECMAScript, karena menjalankan program yang sama pada mesin yang sama 2x lebih cepat dengan implementasi yang lebih baru? Itu tidak masuk akal.
Apakah ini ada hubungannya dengan manajemen memori?
Tidak juga.
Mengapa ini terjadi?
Sumber daya. Uang. Microsoft mungkin mempekerjakan lebih banyak orang membuat kopi untuk programmer kompiler mereka daripada seluruh komunitas PHP, Ruby, dan Python digabungkan memiliki orang yang bekerja pada VM mereka.
Untuk lebih atau kurang fitur apa saja dari bahasa pemrograman yang memengaruhi kinerja dalam beberapa cara, ada juga solusinya. Misalnya, C (saya menggunakan C di sini sebagai pengganti untuk kelas bahasa yang serupa, beberapa di antaranya bahkan ada sebelum C) tidak aman untuk memori, sehingga beberapa program C yang berjalan pada saat yang sama dapat menginjak-injak memori masing-masing. Jadi, kami menciptakan memori virtual, dan membuat semua program C melewati lapisan tipuan sehingga mereka dapat berpura-pura mereka adalah satu-satunya yang berjalan pada mesin. Namun, itu lambat, dan karenanya, kami menciptakan MMU, dan mengimplementasikan memori virtual dalam perangkat keras untuk mempercepatnya.
Tapi! Bahasa memori-aman tidak membutuhkan semua itu! Memiliki memori virtual tidak membantu mereka sedikit pun. Sebenarnya, ini lebih buruk: tidak hanya memori virtual tidak membantu bahasa yang aman-memori, memori virtual, bahkan ketika diimplementasikan dalam perangkat keras, masih berdampak pada kinerja. Hal ini dapat sangat merusak kinerja pengumpul sampah (yang merupakan jumlah signifikan dari implementasi bahasa yang menggunakan memori aman).
Contoh lain: CPU modern mainstream umum menggunakan trik canggih untuk mengurangi frekuensi cache yang hilang. Banyak dari trik-trik itu sama dengan mencoba memprediksi kode apa yang akan dieksekusi dan memori apa yang akan dibutuhkan di masa depan. Namun, untuk bahasa dengan tingkat polimorfisme runtime yang tinggi (misalnya bahasa OO), sangat sulit untuk memprediksi pola akses tersebut.
Tapi, ada cara lain: total biaya kesalahan cache adalah jumlah kesalahan cache dikalikan dengan biaya miss cache individu. CPU arus utama mencoba untuk mengurangi jumlah kesalahan, tetapi bagaimana jika Anda dapat mengurangi biaya kehilangan individu?
CPU Azul Vega-3 dirancang khusus untuk menjalankan JVM tervirtualisasi, dan memiliki MMU yang sangat kuat dengan beberapa instruksi khusus untuk membantu pengumpulan sampah dan lolos dari deteksi (ekuivalen dinamis dengan analisis pelarian statis) dan pengontrol memori yang kuat, dan seluruh sistem masih bisa membuat kemajuan dengan lebih dari 20000 cache cache yang beredar dalam penerbangan. Sayangnya, seperti kebanyakan CPU khusus bahasa, desainnya hanya menghabiskan dan memaksa oleh "raksasa" Intel, AMD, IBM, dan sejenisnya.
Arsitektur CPU hanyalah salah satu contoh yang berdampak pada seberapa mudah atau sulitnya untuk memiliki implementasi bahasa yang berkinerja tinggi. Bahasa seperti C, C ++, D, Rust yang cocok untuk model pemrograman CPU arus utama modern akan lebih mudah dibuat lebih cepat daripada bahasa yang harus "berkelahi" dan mengelak dari CPU, seperti Java, ECMAScript, Python, Ruby , PHP.
Sungguh, itu semua masalah uang. Jika Anda menghabiskan jumlah uang yang sama untuk mengembangkan algoritme kinerja tinggi dalam ECMAScript, implementasi ECMAScript kinerja tinggi, sistem operasi berkinerja tinggi yang dirancang untuk ECMAScript, CPU berkinerja tinggi yang dirancang untuk ECMAScript sebagaimana telah dihabiskan selama yang terakhir beberapa dekade untuk membuat bahasa mirip-C berjalan cepat, maka Anda mungkin akan melihat kinerja yang sama. Hanya saja, pada saat ini, lebih banyak uang telah dihabiskan untuk membuat bahasa seperti C lebih cepat daripada membuat bahasa seperti ECMAScript, dan asumsi bahasa seperti C dimasukkan ke dalam seluruh tumpukan mulai dari MMU dan CPU hingga sistem operasi dan sistem memori virtual hingga pustaka dan kerangka kerja.
Secara pribadi, saya paling akrab dengan Ruby (yang umumnya dianggap sebagai "bahasa lambat"), jadi saya akan memberikan dua contoh: Hash
kelas (salah satu struktur data pusat di Ruby, kamus kunci-nilai) di Rubinius Implementasi Ruby ditulis dalam 100% Ruby murni, dan memiliki kinerja yang hampir sama denganHash
kelas di YARV (implementasi yang paling banyak digunakan), yang ditulis dalam C. Dan ada perpustakaan manipulasi gambar yang ditulis sebagai ekstensi C untuk YARV, yang juga memiliki Ruby (versi fallback) "lambat" murni untuk implementasi yang tidak dapat mendukung C yang menggunakan banyak trik Ruby yang sangat dinamis dan reflektif; cabang eksperimental JRuby, memanfaatkan kerangka kerja juru bahasa Truffle AST dan kerangka kerja kompilasi Graal JIT oleh Oracle Labs, dapat mengeksekusi Ruby murni "versi mundur" secepat YARV dapat menjalankan versi C yang dioptimalkan dengan sangat tinggi. Ini hanya (well, apapun kecuali) dicapai oleh beberapa orang yang sangat pintar melakukan hal-hal yang sangat pintar dengan optimasi runtime dinamis, kompilasi JIT, dan evaluasi parsial.