Saya membandingkan dua teknologi untuk mencapai rekomendasi yang mana harus digunakan oleh perusahaan. Kode teknologi A ditafsirkan sementara kode teknologi B dikompilasi ke kode mesin. Dalam perbandingan saya, saya menyatakan bahwa teknologi B secara umum akan memiliki kinerja yang lebih baik karena tidak memiliki overhead tambahan dari proses interpretasi. Saya juga menyatakan bahwa karena suatu program dapat ditulis dalam banyak cara, masih mungkin suatu program yang ditulis dalam teknologi A dapat mengungguli yang ditulis dalam teknologi B.
Ketika saya menyerahkan laporan ini untuk ditinjau, peninjau menyatakan bahwa saya tidak memberikan alasan yang jelas mengapa secara umum biaya proses interpretasi akan cukup besar sehingga kita dapat menyimpulkan bahwa kinerja teknologi B akan lebih baik.
Jadi pertanyaan saya adalah bisakah kita mengatakan sesuatu tentang kinerja teknologi yang dikompilasi / ditafsirkan? Jika kita dapat mengatakan bahwa kompilasi umumnya lebih cepat dari yang ditafsirkan, bagaimana saya bisa meyakinkan peninjau poin saya?
Jawaban:
Tidak.
Secara umum, kinerja implementasi bahasa terutama tergantung pada jumlah uang, sumber daya, tenaga kerja, penelitian, teknik, dan pengembangan yang dihabiskan untuk itu.
Dan secara khusus, kinerja program tertentu terutama tergantung pada jumlah pemikiran yang dimasukkan ke dalam algoritma.
Ada beberapa interpreter yang sangat cepat di luar sana, dan beberapa kompiler yang menghasilkan kode sangat lambat .
Sebagai contoh, salah satu alasan Forth masih populer, adalah karena dalam banyak kasus, program Forth yang ditafsirkan lebih cepat daripada program C yang dikompilasi yang setara, sementara pada saat yang sama, program pengguna yang ditulis dalam Forth ditambah juru bahasa Forth ditulis dalam C lebih kecil dari program pengguna yang ditulis dalam C.
sumber
Generalisasi dan skenario spesifik secara harfiah berlawanan.
Anda tampaknya bertentangan dengan diri Anda sendiri. Di satu sisi, Anda ingin membuat pernyataan umum tentang bahasa yang ditafsirkan vs dikompilasi. Tetapi di sisi lain, Anda ingin menerapkan pernyataan umum itu ke skenario konkret yang melibatkan Teknologi A dan Teknologi B.
Setelah Anda menerapkan sesuatu ke skenario konkret, itu tidak digeneralisasi lagi . Jadi, bahkan jika Anda dapat membuat kasus bahwa bahasa yang ditafsirkan lebih lambat secara umum , Anda masih belum menunjukkan maksud Anda. Peninjau Anda tidak peduli dengan generalisasi. Anda sedang melakukan analisis dua teknologi yang sangat spesifik. Itu benar-benar kebalikan dari generalisasi.
sumber
Sebagai aturan praktis, program yang ditafsirkan adalah sekitar 2x-10x lebih lambat daripada menulis program dalam bahasa host interpreter, dengan penerjemah untuk bahasa yang lebih dinamis lebih lambat. Ini karena program yang ditafsirkan harus melakukan semua pekerjaan yang sebenarnya, tetapi juga memiliki overhead interpretasi.
Bergantung pada struktur juru bahasa, mungkin ada perbedaan yang sangat signifikan. Ada dua aliran desain interpreter yang saling bertentangan: Satu mengatakan opcode harus sekecil mungkin sehingga mereka dapat dioptimalkan lebih mudah, yang lain mengatakan opcode harus sebesar mungkin sehingga kami melakukan lebih banyak pekerjaan di dalam interpreter. Ketika struktur program Anda sesuai dengan filosofi penerjemah, biaya overhead menjadi diabaikan.
Misalnya Perl adalah bahasa yang ditafsirkan berorientasi pada manipulasi teks. Program Perl idiomatik yang melakukan manipulasi teks tidak akan jauh lebih lambat daripada program C, dan bahkan mungkin mengungguli program C dalam beberapa kasus (mungkin karena Perl menggunakan representasi string yang berbeda dan memiliki berbagai pengoptimalan terkait teks dan IO yang terkait). Namun, melakukan angka-angka dalam Perl akan menjadi lambat tak tertahankan. Peningkatan
++x
adalah instruksi perakitan tunggal, tetapi melibatkan beberapa pointer pointer dan cabang untuk penerjemah Perl. Saya baru-baru ini mem-porting script Perl yang terikat CPU ke C ++, dan mendapat speedup 7x – 20x, tergantung pada level optimisasi kompiler.Berbicara tentang pengoptimalan adalah penting di sini, karena juru bahasa yang dipoles dan dioptimalkan dapat mengungguli kompiler naif yang tidak mengoptimalkan. Karena membuat kompiler pengoptimalisasi adalah sulit dan membutuhkan banyak usaha, kecil kemungkinan “teknologi B” Anda memiliki tingkat kematangan ini.
(Catatan: situs Game Tingkatan Bahasa Komputer memiliki struktur yang membingungkan, tetapi begitu Anda mencapai tabel pengaturan waktu untuk satu masalah, Anda akan melihat bahwa kinerja berbagai bahasa ada di mana-mana - seringkali, tidak ada batas kinerja yang jelas antara solusi yang dikompilasi dan ditafsirkan. Bagian terpenting dari situs ini bukanlah hasil benchmark, tetapi diskusi tentang betapa sulitnya tolok ukur yang bermakna.)
Saat memilih teknologi, kinerja runtime bahasa itu sendiri sama sekali tidak relevan. Lebih penting untuk menjadi penting bahwa teknologi memenuhi beberapa batasan dasar (anggaran kami adalah $ x, kita harus mampu memberikan sebelum tttt-hh-hh, kita harus memenuhi berbagai persyaratan non-fungsional), dan bahwa ia memiliki total biaya kepemilikan (memperhitungkan faktor produktivitas pengembang, biaya perangkat keras, biaya peluang bisnis, risiko bug dan kendala tak terduga dalam teknologi, biaya pemeliharaan, pelatihan dan biaya perekrutan, ...). Misalnya dalam industri di mana waktu ke pasar adalah faktor yang paling penting, teknologi dengan produktivitas pengembang terbaik akan paling cocok. Untuk organisasi besar, pemeliharaan dan biaya jangka panjang mungkin lebih menarik.
sumber
Anda benar-benar dapat mengatakan sesuatu tentang kinerja teknologi yang dikompilasi / ditafsirkan. Tetapi pertama-tama, Anda harus mendefinisikan "kinerja". Jika Anda sedang membangun sistem embedded yang sederhana secara komputasi, "kinerja" kemungkinan akan condong ke sisi penggunaan memori. Sedangkan sistem komputasional yang beroperasi pada set data besar akan menemukan dirinya mendefinisikan "kinerja" dalam jumlah perhitungan per unit waktu karena overhead memori dari JVM atau .NET akan diabaikan.
Setelah Anda memutuskan apa "kinerja" itu, maka Anda dapat mengatakan sesuatu seperti "kami akan memiliki 50 miliar objek dalam memori pada waktu tertentu dan techA yang ditafsirkan menambahkan 8 byte tambahan ke setiap objek untuk manajemen internal yang setara dengan overhead memori 400GB dibandingkan dengan techB yang tidak menambahkan data ini "
sumber
Ini adalah pertanyaan teknis dan Anda sudah mendapatkan banyak jawaban teknis yang baik, tetapi saya ingin menunjukkan aspek yang sedikit berbeda dari situasi Anda: fakta bahwa Anda tidak bisa hanya mendasarkan keputusan seperti "teknologi A atau teknologi B" murni dengan alasan teknis dan / atau kinerja.
Aspek teknis dari sesuatu seperti ini hanyalah sebagian kecil dari keputusan antara A dan B. Ada lusinan faktor lain yang perlu diingat:
Seperti yang Anda lihat, ada banyak hal yang perlu dipertimbangkan ketika membuat keputusan seperti itu.
Saya tahu ini tidak secara khusus menjawab pertanyaan Anda, tetapi saya pikir ini membawa pandangan yang lebih besar tentang situasi Anda dan kekhususan dari keputusan semacam itu.
sumber
Evaluasi parsial adalah kerangka kerja konseptual yang relevan untuk menghubungkan penerjemah dan penyusun.
Bahasa pemrograman adalah spesifikasi (ditulis dalam beberapa laporan, seperti R5RS atau n1570 ). Mereka bukan perangkat lunak, jadi bahkan tidak masuk akal untuk berbicara tentang kinerja . Tetapi beberapa bahasa pemrograman mungkin memiliki beberapa implementasi, termasuk interpreter dan kompiler .
Bahkan dalam bahasa yang dikompilasi secara tradisional (yaitu, bahasa yang implementasinya sering kompiler) seperti C, beberapa bagian sering ditafsirkan. Sebagai contoh, format kontrol string printf (didefinisikan dalam standar C) sering "ditafsirkan" (oleh pustaka standar C , yang memiliki
printf
fungsi menggunakan teknik argumen variabel) tetapi beberapa kompiler (termasuk GCC ) mampu-dalam spesifik terbatas case-untuk mengoptimalkannya dan "kompilasi" menjadi panggilan tingkat rendah.Dan beberapa implementasi, bahkan di dalam "interpreter", menggunakan teknik kompilasi JIT (sehingga menghasilkan kode mesin saat runtime ). Contoh yang bagus adalah luajit . Implementasi lain (misalnya Python, Ocaml, Java, Parrot, Lua) menerjemahkan kode sumber menjadi bytecode yang kemudian ditafsirkan.
SBCL adalah "kompiler" Common Lisp yang secara dinamis menerjemahkan setiap interaksi REPL (dan panggilan ke
eval
dll ...) ke dalam kode mesin. Jadi Anda merasa itu adalah juru bahasa. Sebagian besar implementasi JavaScript di browser (mis. V8 ) menggunakan teknik kompilasi JIT.Dengan kata lain, perbedaan antara interpreter dan kompiler sangat kabur (sebenarnya ada kontinum di antara keduanya), dan secara praktis, sebagian besar implementasi bahasa pemrograman sering kali memiliki sisi penerjemah dan kompiler (setidaknya untuk kode byte).
Implementasi bisa cepat atau lambat secara independen menggunakan sebagian besar "kompiler" atau "interpreter" seperti teknik.
Beberapa sifat bahasa mendukung pendekatan penafsiran (dan hanya dapat dikompilasi secara efisien melalui seluruh analisis program ).
Untuk beberapa jenis masalah, mendesain perangkat lunak dengan beberapa pendekatan metaprogramming bermanfaat dan memberikan kecepatan penting. Anda dapat membayangkan bahwa dengan beberapa input spesifik, program Anda secara dinamis menghasilkan kode khusus untuk memprosesnya. Ini bahkan dimungkinkan dengan C atau C ++ (baik menggunakan beberapa pustaka JIT, atau menghasilkan beberapa kode C, mengompilasinya sebagai plugin yang secara dinamis dimuat).
Lihat juga pertanyaan terkait ini tentang Python, dan itu
sumber
Untuk kode seperti
A = A + B
, yang dapat dikompilasi ke satu atau dua instruksi mesin, masing-masing mengambil sejumlah siklus. Tidak ada penerjemah yang dapat melakukan hal yang sama dalam jumlah siklus itu karena alasan sederhana.Penerjemah juga mengeksekusi set instruksi sendiri (sebut saja kode-byte, kode-p, bahasa perantara, apa pun). Setiap kali ia melihat kode byte seperti ADD, ia harus mencarinya entah bagaimana dan bercabang ke kode yang melakukan penambahan.
The berikutnya kali melihatnya, ia harus mengulang pencarian itu, kecuali ia memiliki cara untuk mengingat lookup sebelumnya. Jika memang ada cara untuk mengingat pencarian sebelumnya, itu bukan lagi apa yang kita sebut "interpreter", melainkan kompiler just-in-time, atau JITter.
Di samping itu...
Untuk kode seperti
callSomeFunction( ... some args ...)
, berapa banyak siklus yang dihabiskan antara memasukkan kode itu dan meninggalkannya? Itu semua tergantung pada apa yang terjadi di dalamcallSomeFunction
. Bisa jadi beberapa, dan bisa triliunan, bahkan jikacallSomeFunction
itu sendiri dikompilasi. Jika banyak, tidak ada gunanya memperdebatkan biaya interpretasi dari baris kode - uang ada di tempat lain.Ingat, bahasa yang ditafsirkan memiliki nilai sendiri, seperti, tidak perlu dikompilasi. ("Kompilasi" dari sintaks permukaan ke kode byte membutuhkan waktu yang sepele. Ambil R atau MATLAB, misalnya.)
Juga, ada fleksibilitas yang dibutuhkan untuk tingkat pemrograman yang cerdas. Dalam Minsky's Society of Mind , Bab 6.4 B -Brain, ada program A yang berhubungan dengan dunia, dan ada program B yang berhubungan dengan program A, dan bisa ada level lebih lanjut. Program yang menulis dan mengelola program lain dapat lebih mudah dilakukan dalam sistem interpretif.
Di Lisp, Anda dapat menulis
(+ A B)
untuk menambahkan A dan B, tetapi begitu ditulis, Anda hanya memiliki pilihan untuk menjalankannya atau tidak. Anda juga dapat menulis(eval (list '+ 'A 'B))
yang membangun program dan kemudian menjalankannya. Itu bisa membangun sesuatu yang berbeda.Subjek program adalah program lain . Ini lebih mudah untuk ditulis dalam bahasa yang ditafsirkan (meskipun, seperti yang Jorg tunjukkan, versi yang lebih baru dari Lisp, sementara mereka memiliki
eval
, kompilasi-on-the-fly, sehingga mereka tidak memiliki penalti kecepatan menafsirkan).sumber
eval
danapply
fungsi, yang merupakan juru bahasa.eval
tidak ditafsirkan. Dan tidak adaapply
. Tentu saja ada implementasi yang mengandung juru bahasa, tetapi SBCL tidak.eval
tidak diartikan ed . Ini adalah menafsirkan er .Jenis, semacam, itu tergantung tetapi sebagai aturan umum kompilasi - baik itu melalui JIT atau dikompilasi secara statis - lingkungan akan lebih cepat untuk banyak tugas komputasi intensif - dengan asumsi untuk kesederhanaan bahasa yang sama.
Sebagian alasannya adalah bahwa bahasa yang ditafsirkan perlu memiliki interpreter loop - loop yang membaca instruksi, memilih tindakan yang tepat untuk mengambil dan menjalankannya. Dalam kasus terbaik seperti menafsirkan bytecode Python atau Java (seperti yang dilakukan JVM lama ) ia memiliki overhead beberapa instruksi dan bermain malapetaka dengan prediktor cabang - tanpa yang terakhir Anda dapat mengharapkan hukuman besar karena salah duga. Bahkan JIT yang sangat bodoh harus mempercepat ini secara signifikan.
Yang mengatakan bahasa yang ditafsirkan dapat menipu. Misalnya Matlab telah mengoptimalkan rutinitas untuk perkalian matriks dan dengan sedikit perubahan Anda dapat menjalankan kode pada GPU (penafian: Saya bekerja untuk nVidia - pendapat apa pun yang diungkapkan di sini adalah milik saya dan tidak mewakili pandangan atasan saya). Dengan begitu Anda dapat menulis kode tingkat tinggi yang singkat dan kuat tanpa khawatir tentang detail - seseorang benar-benar memperhatikannya dan menghabiskan waktu dan sumber daya untuk mengoptimalkannya dalam bahasa tingkat rendah. Tidak ada yang diwarisi tentang hal itu dan itu tidak mencegah, misalnya, Matlab untuk JIT kode tetapi sering tidak ada alasan karena overhead panggilan rutin tingkat tinggi minimal dibandingkan dengan waktu yang dihabiskan di tingkat rendah.
TL; DR - program yang dikompilasi memiliki manfaat kinerja yang sangat besar dibandingkan yang ditafsirkan (untuk perbandingan apel dengan apel, lihat Kecepatan PyPy ). Namun kecepatan eksekusi hanya merupakan bagian dari masalah dan mungkin tidak berkontribusi banyak terhadap kecepatan keseluruhan (jika sebagian besar waktu dihabiskan di perpustakaan). Juga masalah implementasi.
sumber
Asumsi Anda cukup beralasan, meskipun asumsi.
Saya tidak akan membahas alasan mengapa kode yang dikompilasi harus lebih cepat daripada kode yang ditafsirkan: jika Anda tahu bagaimana komputer bekerja, itu akan jelas. Perbedaannya dapat berupa urutan besarnya untuk jenis masalah tertentu. Jika pengulas Anda dengan serius membantah kasus umum itu, mereka tidak tahu apa yang mereka bicarakan.
Di mana mereka mungkin ada benarnya adalah apakah perbedaannya signifikan dalam jenis aplikasi yang Anda kembangkan. Jika sebagian besar I / O atau kebanyakan memanggil perpustakaan yang dikompilasi dan tidak memiliki banyak perhitungan, overhead proses interpretasi memang mungkin tidak signifikan.
Tetapi inti dari posting saya adalah ini: sebagai seorang ahli IT, Anda akan sering dipanggil untuk mengambil keputusan cepat berdasarkan pengetahuan umum tentang bagaimana segala sesuatu harus bekerja. Melakukan tes tertentu mungkin memberi Anda jawaban yang lebih akurat, tetapi biayanya akan jauh lebih mahal dan Anda tidak akan sampai di sana lebih dulu.
Tapi dari waktu ke waktu Anda memang ketahuan. Itu terjadi pada saya. Anda membuat asumsi yang baik dan kemudian Anda menemukan Anda gagal memperhitungkan kebodohan dunia.
Tapi saya tidak bisa menjelaskan serta kartun Dilbert favorit saya sepanjang masa. Tidak ada yang menunjukkan lebih baik daripada ini bahaya menjadi orang sok pintar.
TL; DR: Anda seharusnya benar, tetapi periksa dunia nyata untuk berjaga-jaga.
sumber
Kecuali jika Anda menggunakan sesuatu yang agak eksotis, masalah Anda tidak akan tentang kinerja tentang bahasa yang ditafsirkan A dan bahasa yang dikompilasi B.
Karena jika Anda / tim Anda tahu A dan bukan B dan jadi tuliskan kode cara yang lebih baik dalam A daripada B Anda dapat memiliki kinerja yang jauh lebih baik di A daripada B. Jika Anda memiliki orang yang berpengalaman dalam satu bahasa dan bahasa / perpustakaan dapat melakukan pekerjaan yang Anda butuhkan, patuhi itu.
Berikut ini tautan tentang regex dalam berbagai bahasa; Anda akan melihat bahwa regex diimplementasikan lebih baik dalam beberapa bahasa meskipun dikompilasi atau tidak: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna
sumber
Saya pikir itu bukan ide yang baik untuk berbicara tentang kinerja dua teknologi hanya berdasarkan fakta bahwa satu dikompilasi dan yang lainnya ditafsirkan. Sebagaimana dinyatakan dalam jawaban lain, itu mungkin tergantung pada area aplikasi (beberapa bahasa dapat dioptimalkan untuk melakukan beberapa operasi dengan sangat cepat dan melakukan hal-hal lain lebih lambat) serta pada pengalaman orang-orang yang akan menggunakan teknologi itu.
Saya tidak berpikir masuk akal untuk mengharapkan bahwa Anda akan mendapatkan peningkatan kinerja jika Anda mengambil beberapa juru bahasa yang diinterpretasikan dengan sangat baik dan memberi mereka beberapa teknologi yang mereka tidak kenal - mungkin dalam teori yang terakhir MUNGKIN menghasilkan kinerja yang lebih baik, tetapi pada kenyataannya, tanpa keahlian dan pengalaman yang diperlukan, Anda tidak akan menggunakan semua peluang optimisasi.
Dari salah satu karyawan perusahaan Silicon Valley yang terkenal, saya juga pernah mendengar bahwa mereka lebih suka bahasa yang lebih mudah digunakan karena lebih mahal dan menyulitkan untuk membayar beberapa pengembang terampil untuk mempertahankan kode yang rumit, tetapi sangat dioptimalkan daripada hanya untuk membeli lebih banyak rig untuk menangani implementasi yang kurang efisien, sehingga juga harus dipertimbangkan saat memilih teknologi.
sumber
Suatu kali saya harus membuat pernyataan yang sama untuk membenarkan keputusan besar.
Pertama, mereka mungkin tidak ingin mempercayai insinyur yang rendah hati, jadi saya menemukan beberapa tes benchmark yang sebanding dan mengutipnya. Ada banyak tentang mereka, dari orang-orang seperti Microsoft, atau universitas terkenal. Dan mereka akan mengatakan hal-hal seperti: Metode A adalah antara 3 dan 10 kali lebih cepat daripada metode B, tergantung pada variabel X dan Y.
Kedua, Anda mungkin ingin menjalankan tolok ukur sendiri, mungkin menggunakan potongan representatif dari kode yang dimaksud, atau sesuatu yang serupa yang sudah Anda miliki. Jalankan 1000 kali dalam semalam sehingga benar-benar ada perbedaan yang bisa diukur.
Pada titik ini perbedaan (atau kekurangannya) antara A dan B harus sangat jelas sehingga Anda hanya perlu mempresentasikannya. Jadi format hasilnya dengan jelas, dengan diagram jika memungkinkan, nyatakan semua asumsi dan tentukan semua data yang digunakan.
sumber
Saya berpendapat bahwa bahasa dinamis apa pun memiliki keunggulan dibandingkan yang dikompilasi secara statis: "Optimalisasi runtime"
Itulah salah satu alasan Java bisa lebih cepat dari C ++
Ya, memuat bahasa yang diketik secara dinamis akan selalu memiliki biaya terjemahan dan menguntungkan. Tetapi begitu dijalankan, interpreter dapat membuat profil dan meningkatkan jalur kode yang sering dengan informasi runtime yang tidak akan pernah dimiliki oleh bahasa statis
CATATAN: Yah, Java adalah bahasa yang ditafsirkan, bukan bahasa yang dinamis. Tetapi ini adalah contoh yang bagus dari apa yang dapat Anda percepat dengan informasi runtime
sumber
Ini akan menjadi pendekatan saya:
Secara umum, penerjemah dikompilasi, sehingga setiap teknologi yang ditafsirkan tidak lain adalah teknologi yang dikompilasi jika dilihat pada tingkat yang rendah. Oleh karena itu, teknologi yang dikompilasi lebih banyak dan dengan lebih banyak kemungkinan Anda tidak akan pernah menjadi lebih buruk jika Anda pintar (yang secara umum Anda). Itu tergantung pada seberapa banyak informasi yang tersedia pada waktu kompilasi dan berapa banyak informasi yang tersedia hanya pada saat runtime dan seberapa bagus kompiler dan interpreternya, tetapi secara teoritis harus selalu memungkinkan untuk setidaknya menyamai kinerja setiap penerjemah dengan kompiler yang sesuai, hanya karena interpreter dibuat oleh kompiler. Itu mungkin, tidak berarti itu adalah kasus untuk teknisi A dan B Anda.
Dalam praktiknya, beri tahu pengulas tentang semua tolok ukur yang tersedia di mana sistem yang dikompilasi dan ditafsirkan dibandingkan. Kemudian minta dia untuk menyarankan penerjemah yang mengalahkan algoritma spesifik kode Majelis yang dioptimalkan.
Orang mungkin harus menambahkan, bahwa pernyataan umum semacam itu sama sekali tidak membantu ketika membandingkan dua teknologi spesifik A dan B. Di sana pilihan A dan B sangat berarti, jauh lebih banyak, daripada jika mereka ditafsirkan atau dikompilasi.
sumber