Dalam mendengarkan podcast StackOverflow, jab terus muncul sehingga "programmer nyata" menulis dalam C, dan bahwa C jauh lebih cepat karena "dekat dengan mesin." Meninggalkan pernyataan sebelumnya untuk pos lain, apa yang istimewa tentang C yang membuatnya lebih cepat daripada bahasa lain? Atau dengan kata lain: apa yang membuat bahasa lain tidak bisa dikompilasi menjadi biner yang berjalan setiap bit secepat C?
c
performance
Mike C.
sumber
sumber
Jawaban:
Tidak banyak yang spesial tentang C. Itu salah satu alasan mengapa itu cepat.
Bahasa yang lebih baru yang memiliki dukungan untuk pengumpulan sampah , pengetikan dinamis , dan fasilitas lainnya yang memudahkan programmer untuk menulis program.
Tangkapannya adalah, ada overhead pemrosesan tambahan yang akan menurunkan kinerja aplikasi. C tidak memiliki semua itu, yang berarti bahwa tidak ada overhead, tetapi itu berarti bahwa programmer harus dapat mengalokasikan memori dan membebaskan mereka untuk mencegah kebocoran memori , dan harus berurusan dengan pengetikan variabel statis.
Yang mengatakan, banyak bahasa dan platform, seperti Java (dengan Java Virtual Machine ) dan .NET (dengan Common Language Runtime) telah meningkatkan kinerja selama bertahun-tahun dengan kemajuan seperti kompilasi just-in-time yang menghasilkan kode mesin asli dari bytecode untuk mencapai kinerja yang lebih tinggi.
sumber
Ada trade off yang telah dibuat oleh desainer C. Itu artinya, mereka membuat keputusan untuk menempatkan kecepatan di atas keselamatan. C tidak akan
Ketika Anda mengindeks ke dalam array, di Jawa dibutuhkan beberapa panggilan metode di mesin virtual, memeriksa terikat dan cek kewarasan lainnya. Itu valid dan benar-benar baik-baik saja , karena menambah keamanan di mana itu karena. Tetapi dalam C, bahkan hal-hal sepele yang cantik tidak dimasukkan ke dalam keamanan. Sebagai contoh, C tidak memerlukan memcpy untuk memeriksa apakah wilayah untuk menyalin tumpang tindih. Ini tidak dirancang sebagai bahasa untuk memprogram aplikasi bisnis besar.
Tapi keputusan desain ini tidak bug dalam bahasa C . Mereka dirancang, karena memungkinkan kompiler dan penulis perpustakaan untuk mendapatkan setiap bit kinerja dari komputer. Inilah semangat C bagaimana dokumen C Rationale menjelaskannya:
sumber
Jika Anda menghabiskan satu bulan untuk membangun sesuatu dalam C yang berjalan dalam 0,05 detik, dan saya menghabiskan sehari menulis hal yang sama di Jawa, dan itu berjalan dalam 0,10 detik, lalu apakah C benar-benar lebih cepat?
Tetapi untuk menjawab pertanyaan Anda, kode C yang ditulis dengan baik umumnya akan berjalan lebih cepat daripada kode yang ditulis dengan baik dalam bahasa lain karena bagian dari penulisan kode C "baik" termasuk melakukan optimasi manual pada tingkat yang dekat dengan mesin.
Meskipun kompiler memang sangat pintar, mereka belum dapat secara kreatif menghasilkan kode yang bersaing dengan algoritma pijatan tangan (dengan asumsi "tangan" milik programmer C yang baik ).
Edit:
Banyak komentar di sepanjang baris "Saya menulis dalam C dan saya tidak berpikir tentang optimasi."
Tetapi untuk mengambil contoh spesifik dari pos ini :
Dalam Delphi saya bisa menulis ini:
dan di CI tulis ini:
Tetapi berapa banyak optimasi yang ada dalam versi C? Kami membuat banyak keputusan tentang implementasi yang tidak saya pikirkan dalam versi Delphi. Bagaimana string diimplementasikan? Dalam Delphi saya tidak melihatnya. Dalam C, saya telah memutuskan itu akan menjadi pointer ke array bilangan bulat ASCII, yang kita sebut karakter. Di C, kami menguji keberadaan karakter satu per satu. Di Delphi, saya menggunakan Pos.
Dan ini hanyalah contoh kecil. Dalam sebuah program besar, seorang programmer C harus membuat keputusan tingkat rendah dengan setiap baris kode. Ini menambah hingga dapat dieksekusi, dioptimalkan dengan tangan.
sumber
Aku tidak melihatnya sudah, jadi saya akan mengatakannya: C cenderung lebih cepat karena hampir segala sesuatu yang lain ditulis dalam C .
Java dibangun di atas C, Python dibangun di atas C (atau Java, atau .NET, dll.), Perl adalah, dll. OS ditulis dalam C, mesin virtual ditulis dalam C, kompiler ditulis dalam C, penafsir ditulis dalam C. Beberapa hal masih ditulis dalam bahasa Majelis, yang cenderung lebih cepat. Semakin banyak hal yang ditulis dalam sesuatu yang lain, yang dengan sendirinya ditulis dalam C.
Setiap pernyataan yang Anda tulis dalam bahasa lain (bukan Majelis) biasanya diterapkan di bawahnya sebagai beberapa pernyataan dalam C, yang dikompilasi ke kode mesin asli. Karena bahasa-bahasa lain cenderung ada untuk mendapatkan tingkat abstraksi yang lebih tinggi daripada bahasa C, pernyataan tambahan yang dibutuhkan dalam bahasa C cenderung berfokus pada menambah keamanan, menambah kompleksitas, dan menyediakan penanganan kesalahan. Itu sering kali merupakan hal yang baik, tetapi harganya mahal , dan namanya cepat dan besar .
Secara pribadi, saya telah menulis dalam lusinan bahasa yang mencakup sebagian besar spektrum yang tersedia, dan saya pribadi telah mencari keajaiban yang Anda isyaratkan:
Setelah beberapa tahun penelitian, jawaban saya adalah Python (pada C). Anda mungkin ingin melihatnya. Omong-omong, Anda juga dapat drop-down ke Assembly dari Python, juga (dengan bantuan kecil dari perpustakaan khusus).
Di sisi lain, kode yang buruk dapat ditulis dalam bahasa apa pun . Karenanya, kode C (atau Majelis) tidak otomatis lebih cepat. Demikian juga, beberapa trik pengoptimalan dapat membawa bagian dari kode bahasa tingkat yang lebih tinggi mendekati tingkat kinerja C. mentah. Tetapi, untuk sebagian besar aplikasi, program Anda menghabiskan sebagian besar waktunya menunggu orang atau perangkat keras, sehingga perbedaannya benar-benar tidak masalah.
Nikmati.
sumber
Ada banyak pertanyaan di sana - kebanyakan yang saya tidak memenuhi syarat untuk menjawab. Tetapi untuk yang terakhir ini:
Dalam satu kata, Abstraksi.
C hanya satu atau 2 level abstraksi dari bahasa mesin. Bahasa Java dan .Net berada pada minimal 3 level abstraksi dari assembler. Saya tidak yakin tentang Python dan Ruby.
Biasanya, semakin banyak mainan programmer (tipe data kompleks, dll.), Semakin jauh Anda dari bahasa mesin dan semakin banyak terjemahan yang harus dilakukan.
Saya ke sana-sini tapi itulah intinya.
Perbarui ------- Ada beberapa komentar bagus pada posting ini dengan detail lebih lanjut.
sumber
Tidak terlalu cepat C karena model biaya C transparan . Jika program C lambat, lambat dalam cara yang jelas: dengan mengeksekusi banyak pernyataan. Dibandingkan dengan biaya operasi dalam C, operasi tingkat tinggi pada objek (terutama refleksi) atau string dapat memiliki biaya yang tidak jelas.
Dua bahasa yang umumnya dikompilasi ke binari yang secepat C adalah Standar ML (menggunakan kompiler MLton ) dan Objective Caml . Jika Anda memeriksa permainan benchmark, Anda akan menemukan bahwa untuk beberapa benchmark, seperti pohon biner, versi OCaml lebih cepat dari C. (Saya tidak menemukan entri MLton.) Tetapi jangan menganggap baku tembak terlalu serius; itu adalah, seperti yang dikatakan, permainan, hasilnya sering kali mencerminkan berapa banyak upaya yang dilakukan orang dalam menyetel kode.
sumber
C tidak selalu lebih cepat.
C lebih lambat daripada, misalnya Modern Fortran.
C sering lebih lambat dari Jawa untuk beberapa hal. (Terutama setelah kompiler JIT mencoba kode Anda)
C memungkinkan pointer aliasing terjadi, yang berarti beberapa optimasi yang baik tidak dimungkinkan. Khususnya ketika Anda memiliki beberapa unit eksekusi, ini menyebabkan data mengambil warung. Ow
Asumsi bahwa pointer berfungsi aritmatika benar-benar menyebabkan kinerja kembung lambat pada beberapa keluarga CPU (PIC khususnya!) Ini digunakan untuk menyedot yang besar pada x86 tersegmentasi.
Pada dasarnya, ketika Anda mendapatkan unit vektor, atau kompilator paralelisasi, C bau dan Fortran modern berjalan lebih cepat.
Trik programmer C seperti thunking (memodifikasi executable on the fly) menyebabkan CPU prefetch warung.
Anda mengerti maksudnya?
Dan teman baik kita, x86, mengeksekusi set instruksi yang saat ini tidak banyak berhubungan dengan arsitektur CPU yang sebenarnya. Register shadow, pengoptimal load-store, semuanya dalam CPU. Jadi C kemudian dekat dengan logam virtual. Logam asli, Intel jangan biarkan Anda melihat. (Secara historis VLIW CPU sedikit payah jadi, mungkin itu tidak terlalu buruk.)
Jika Anda memprogram dalam C pada DSP kinerja tinggi (mungkin TI DSP?), Kompiler harus melakukan beberapa hal rumit untuk membuka gulungan C di beberapa unit eksekusi paralel. Jadi dalam hal ini C tidak dekat dengan logam, tetapi dekat dengan kompiler, yang akan melakukan optimasi seluruh program. Aneh.
Dan akhirnya, beberapa CPU (www.ajile.com) menjalankan bytecodes Java di perangkat keras. C akan PITA untuk digunakan pada CPU itu.
sumber
Tidak ada. Bahasa modern seperti Java atau. NET lebih berorientasi pada produktivitas programmer daripada kinerja. Perangkat keras sudah murah sekarang. Juga kompilasi ke representasi perantara memberikan banyak bonus seperti keamanan, portabilitas dll. NET CLR dapat mengambil keuntungan dari perangkat keras yang berbeda - misalnya Anda tidak perlu mengoptimalkan / mengkompilasi ulang program secara manual untuk menggunakan set instruksi SSE.
sumber
Faktor utama adalah bahasa yang diketik secara statis dan dikompilasi dengan kode mesin. Juga, karena ini adalah bahasa tingkat rendah, umumnya tidak melakukan apa pun yang Anda tidak menyuruhnya.
Ini adalah beberapa faktor lain yang muncul di pikiran.
Sebagian besar bahasa yang diketik statis dapat dikompilasi sama cepat atau lebih cepat dari C, terutama jika mereka dapat membuat asumsi bahwa C tidak bisa karena aliasing pointer, dll.
sumber
Saya kira Anda lupa bahwa bahasa Assembly juga bahasa :)
Tetapi serius, program C lebih cepat hanya ketika programmer tahu apa yang dia lakukan. Anda dapat dengan mudah menulis program C yang berjalan lebih lambat daripada program yang ditulis dalam bahasa lain yang melakukan pekerjaan yang sama.
Alasan mengapa C lebih cepat adalah karena ia dirancang dengan cara ini. Ini memungkinkan Anda melakukan banyak hal "level bawah" yang membantu kompiler mengoptimalkan kode. Atau, haruskah kita katakan, Anda programmer bertanggung jawab untuk mengoptimalkan kode. Namun seringkali cukup rumit dan rawan kesalahan.
Bahasa lain, seperti yang lain telah disebutkan, lebih fokus pada produktivitas programmer. Secara umum diyakini bahwa waktu programmer jauh lebih mahal daripada waktu mesin (bahkan di masa lalu). Jadi sangat masuk akal untuk meminimalkan waktu yang dihabiskan programmer untuk menulis dan men-debug program alih-alih waktu menjalankan program. Untuk melakukan itu, Anda akan sedikit mengorbankan apa yang dapat Anda lakukan untuk membuat program lebih cepat karena banyak hal yang otomatis.
sumber
Sebagian besar, setiap instruksi C sesuai dengan instruksi assembler yang sangat sedikit. Anda pada dasarnya menulis kode mesin tingkat yang lebih tinggi, sehingga Anda memiliki kendali atas hampir semua yang dilakukan prosesor. Banyak bahasa yang dikompilasi lainnya, seperti C ++, memiliki banyak instruksi yang tampak sederhana yang dapat berubah menjadi lebih banyak kode daripada yang Anda pikirkan (fungsi virtual, copy constructor, dll.) Dan bahasa yang ditafsirkan seperti Java atau Ruby memiliki lapisan lain dari instruksi yang tidak pernah Anda lihat - Mesin Virtual atau Interpreter.
sumber
Saya tahu banyak orang mengatakannya dengan cara yang panjang lebar, tetapi:
sumber
C ++ lebih cepat rata-rata (seperti awalnya, sebagian besar superset dari C, meskipun ada beberapa perbedaan). Namun, untuk tolok ukur tertentu, seringkali ada bahasa lain yang lebih cepat.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/
fannjuch-redux
tercepat di Scalan-body
danfasta
lebih cepat di Ada.spectral-norm
tercepat di Fortran.reverse-complement
,mandelbrot
danpidigits
tercepat di ATS.regex-dna
tercepat di JavaScript.chameneou-redux
paling cepat adalah Java 7.thread-ring
tercepat di Haskell.Sisa tolok ukur tercepat di C atau C ++.
sumber
extern "C"
tidak ada hubungannya dengan C ++ menjadi superset dari C.system("bash script.sh");
bekerja untuk skrip bash, dan karenanya C adalah superset dari bash.extern "C"
menyediakan tautan C dalam C ++ karena namanya mangling. Sedangkan memanggil X sebagai superset dari Y berarti segala sesuatu yang dapat dilakukan dalam Y juga dapat dilakukan dalam X, yang tidak berlaku untuk C ++. Ada beberapa konstruksi bahasa yang valid dalam C tetapi tidak dalam C ++.bash
adalah program baris perintah yang tersedia. Jika ya dan menyertakan versi / spesifikasi bash apa yang perlu didukung, saya akan menganggapnya superset.struct foo { int: this; }; typedef float foo;
Banyak dari jawaban ini memberikan alasan yang valid mengapa C adalah, atau tidak, lebih cepat (baik dalam skenario umum atau khusus). Tidak dapat dipungkiri bahwa:
Meskipun demikian, ada hal lain yang saya perhatikan bahwa, saya pikir, mempengaruhi kinerja komparatif C vs banyak bahasa lain lebih besar daripada faktor lainnya. Yakni:
Bahasa lain sering membuatnya lebih mudah untuk menulis kode yang dieksekusi lebih lambat. Seringkali, itu bahkan didorong oleh filosofi desain bahasa. Konsekuensi: seorang programmer C lebih cenderung menulis kode yang tidak melakukan operasi yang tidak perlu.
Sebagai contoh, pertimbangkan program Windows sederhana di mana satu jendela utama dibuat. Versi AC akan mengisi
WNDCLASS[EX]
struktur yang akan diteruskanRegisterClass[Ex]
, lalu memanggilCreateWindow[Ex]
dan memasukkan loop pesan. Kode yang sangat disederhanakan dan disingkat mengikuti:Program yang setara dalam C # bisa jadi hanya satu baris kode:
Satu baris kode ini menyediakan semua fungsi yang dilakukan hampir 20 baris kode C, dan menambahkan beberapa hal yang kami tinggalkan, seperti pengecekan kesalahan. Pustaka yang lebih kaya dan lebih lengkap (dibandingkan dengan yang digunakan dalam proyek C khas) melakukan banyak pekerjaan bagi kami, membebaskan waktu kami untuk menulis lebih banyak potongan kode yang terlihat pendek bagi kami tetapi melibatkan banyak langkah di belakang layar.
Tapi perpustakaan yang kaya memungkinkan kode mudah dan cepat mengasapi bukan maksud saya. Maksud saya lebih jelas ketika Anda mulai memeriksa apa yang sebenarnya terjadi ketika one-liner kecil kami benar-benar dieksekusi. Untuk bersenang-senang kadang-kadang, aktifkan akses sumber .NET di Visual Studio 2008 atau lebih tinggi, dan masuk ke baris-sederhana di atas. Salah satu permata kecil yang menyenangkan yang akan Anda temui adalah komentar ini di pengambil untuk
Control.CreateParams
:Sepuluh kali . Informasi yang kira-kira setara dengan jumlah dari apa yang disimpan dalam suatu
WNDCLASSEX
struktur dan apa yang diteruskanCreateWindowEx
diambil dariControl
kelas sepuluh kali sebelum disimpan dalam suatuWNDCLASSEX
struktur dan diteruskan keRegisterClassEx
danCreateWindowEx
.Secara keseluruhan, jumlah instruksi yang dieksekusi untuk melakukan tugas yang sangat mendasar ini adalah 2-3 kali lipat lebih banyak di C # daripada di C. Bagian dari ini adalah karena penggunaan perpustakaan kaya fitur, yang perlu digeneralisasi, dibandingkan kode C sederhana yang melakukan persis apa yang kita butuhkan dan tidak lebih. Tetapi bagian dari itu adalah karena fakta bahwa sifat kerangka kerja .NET yang termodulasiasikan dan berorientasi objek, cocok untuk banyak pengulangan eksekusi yang sering dihindari oleh pendekatan prosedural.
Saya tidak mencoba untuk memilih C # atau framework .NET. Saya juga tidak mengatakan bahwa modularisasi, generalisasi, fitur perpustakaan / bahasa, OOP, dll. Adalah hal-hal buruk . Saya biasa melakukan sebagian besar pengembangan saya di C, kemudian di C ++, dan paling akhir di C #. Demikian pula, sebelum C, saya menggunakan kebanyakan perakitan. Dan dengan setiap langkah "lebih tinggi" bahasa saya berjalan, saya menulis program yang lebih baik, lebih dapat dikelola, lebih kuat dalam waktu yang lebih singkat. Namun, mereka cenderung melakukan sedikit lebih lambat.
sumber
Saya tidak berpikir ada orang yang menyebutkan fakta bahwa lebih banyak upaya telah dimasukkan ke dalam kompiler C daripada kompiler lain, dengan pengecualian Jawa.
C sangat mampu mengoptimalkan karena banyak alasan yang telah dinyatakan - lebih dari hampir semua bahasa lain. Jadi jika jumlah upaya yang sama dimasukkan ke kompiler bahasa lain, C mungkin masih akan keluar di atas.
Saya pikir setidaknya ada satu bahasa kandidat yang dengan usaha dapat dioptimalkan lebih baik daripada C dan dengan demikian kita bisa melihat implementasi yang menghasilkan biner lebih cepat. Saya sedang memikirkan digital mars D karena pembuatnya berhati-hati untuk membangun bahasa yang berpotensi dioptimalkan lebih baik daripada C. Mungkin ada bahasa lain yang memiliki kemungkinan ini. Namun saya tidak dapat membayangkan bahwa bahasa apa pun akan memiliki kompiler lebih dari hanya beberapa persen lebih cepat daripada kompiler C terbaik. Saya ingin salah.
Saya pikir "buah tergantung rendah" sebenarnya akan dalam bahasa yang dirancang untuk MUDAH bagi manusia untuk dioptimalkan. Seorang programmer yang terampil dapat membuat bahasa apa pun berjalan lebih cepat - tetapi kadang-kadang Anda harus melakukan hal-hal konyol atau menggunakan konstruksi yang tidak alami untuk mewujudkannya. Meskipun akan selalu membutuhkan upaya, bahasa yang baik harus menghasilkan kode yang relatif cepat tanpa harus terobsesi dengan cara penulisan program.
Penting juga (setidaknya bagi saya) bahwa kode kasus terburuk cenderung cepat. Ada banyak "bukti" di web bahwa Java sama cepat atau lebih cepat dari C, tetapi itu didasarkan pada contoh memetik ceri. Saya bukan penggemar C, tapi saya tahu bahwa APA SAJA yang saya tulis dalam C akan berjalan dengan baik. Dengan Java, "mungkin" akan berjalan dalam 15% dari kecepatan, biasanya dalam 25% tetapi dalam beberapa kasus bisa jauh lebih buruk. Setiap kasus di mana itu sama cepat atau dalam beberapa persen biasanya karena sebagian besar waktu dihabiskan dalam kode perpustakaan yang sangat dioptimalkan C pula.
sumber
Ini sebenarnya sedikit kepalsuan yang diabadikan. Memang benar bahwa program C sering kali lebih cepat, hal ini tidak selalu terjadi, terutama jika programmer C tidak pandai melakukannya.
Satu lubang mencolok yang cenderung dilupakan orang adalah ketika program harus memblokir semacam IO, seperti input pengguna dalam program GUI apa pun. Dalam kasus ini, tidak masalah bahasa apa yang Anda gunakan karena Anda dibatasi oleh kecepatan data bisa masuk, bukan seberapa cepat Anda bisa memprosesnya. Dalam hal ini, tidak masalah jika Anda menggunakan C, Java, C # atau bahkan Perl; Anda tidak bisa berjalan lebih cepat daripada data bisa masuk.
Hal utama lainnya adalah bahwa menggunakan pengumpulan sampah dan tidak menggunakan pointer yang tepat memungkinkan mesin virtual untuk membuat sejumlah optimasi tidak tersedia dalam bahasa lain. Misalnya, JVM mampu memindahkan objek di heap untuk mendefrag itu. Ini membuat alokasi di masa depan jauh lebih cepat karena indeks berikutnya hanya dapat digunakan daripada mencarinya di tabel. JVM modern juga tidak harus benar-benar mengalokasikan memori; sebagai gantinya, mereka hanya memindahkan objek hidup di sekitar ketika mereka GC dan memori yang dihabiskan dari objek mati dipulihkan pada dasarnya gratis.
Ini juga memunculkan poin menarik tentang C dan bahkan lebih lagi di C ++. Ada semacam filosofi desain "Jika Anda tidak membutuhkannya, Anda tidak membayarnya." Masalahnya adalah bahwa jika Anda menginginkannya, Anda harus membayar mahal untuk itu. Sebagai contoh, implementasi vtable di Java cenderung jauh lebih baik daripada implementasi C ++, jadi panggilan fungsi virtual jauh lebih cepat. Di sisi lain, Anda tidak punya pilihan selain menggunakan fungsi virtual di Jawa dan mereka masih membutuhkan biaya, tetapi dalam program yang menggunakan banyak fungsi virtual, biaya yang berkurang bertambah.
sumber
Ini bukan tentang bahasa sebagai alat dan perpustakaan. Pustaka dan kompiler yang tersedia untuk C jauh lebih tua daripada untuk bahasa yang lebih baru. Anda mungkin berpikir ini akan membuat mereka lebih lambat, tetapi au contraire.
Perpustakaan-perpustakaan ini ditulis pada saat pemrosesan daya dan memori berada pada premium. Mereka harus ditulis dengan sangat efisien agar dapat bekerja sama sekali. Pengembang kompiler C juga telah lama bekerja dalam semua jenis optimisasi pintar untuk prosesor yang berbeda. Kedewasaan C dan adopsi yang luas menjadikan keuntungan yang signifikan di atas bahasa lain pada usia yang sama. Ini juga memberi C keunggulan kecepatan dibandingkan alat yang lebih baru yang tidak menekankan kinerja mentah sebanyak yang harus dilakukan C.
sumber
Kurangnya abstraksi adalah apa yang membuat C lebih cepat. Jika Anda menulis pernyataan keluaran, Anda tahu persis apa yang terjadi. Jika Anda menulis pernyataan keluaran dalam java, file tersebut dikompilasi ke file kelas yang kemudian dijalankan pada mesin virtual yang memperkenalkan lapisan abstraksi. Kurangnya fitur berorientasi objek sebagai bagian dari bahasa juga meningkatkan kecepatannya untuk mengurangi kode yang dihasilkan. Jika Anda menggunakan C sebagai bahasa berorientasi objek maka Anda melakukan semua pengkodean untuk hal-hal seperti kelas, inharitence, dll. Ini berarti daripada membuat sesuatu yang cukup umum untuk semua orang dengan jumlah kode dan kinerja yang mengharuskan Anda hanya menulis apa yang Anda butuhkan untuk menyelesaikan pekerjaan.
sumber
Luar biasa melihat "C / C ++ lama harus lebih cepat dari Jawa karena Java ditafsirkan" mitos masih hidup dan menendang. Ada artikel yang akan kembali beberapa tahun , dan juga yang lebih baru , yang menjelaskan dengan konsep atau pengukuran mengapa ini tidak selalu terjadi .
Implementasi mesin virtual saat ini (dan bukan hanya JVM, omong-omong) dapat mengambil keuntungan dari informasi yang dikumpulkan selama eksekusi program untuk secara dinamis menyempurnakan kode saat dijalankan, menggunakan berbagai teknik:
dan berbagai penyesuaian lainnya berdasarkan pada mengetahui apa yang sebenarnya dilakukan kode, dan pada karakteristik aktual dari lingkungan tempat kode itu dijalankan.
sumber
Kode yang paling cepat dijalankan adalah kode mesin yang dibuat dengan tangan. Assembler akan hampir sama baiknya. Keduanya level sangat rendah dan dibutuhkan banyak kode penulisan untuk melakukan sesuatu. C adalah assembler kecil di atas. Anda masih memiliki kemampuan untuk mengontrol hal-hal pada tingkat yang sangat rendah di mesin yang sebenarnya, tetapi ada abstraksi yang cukup membuat penulisan lebih cepat dan lebih mudah daripada assembler. Bahasa lain seperti C # dan JAVA bahkan lebih abstrak. Sementara Assembler dan kode mesin disebut bahasa tingkat rendah, C # dan JAVA (dan banyak lainnya) disebut bahasa tingkat tinggi. C kadang-kadang disebut bahasa tingkat menengah.
sumber
Jangan mengambil kata seseorang untuk itu, lihat pembongkaran untuk C dan bahasa pilihan Anda dalam setiap bagian penting kinerja kode Anda. Saya pikir Anda bisa melihat di jendela pembongkaran saat runtime di Visual Studio untuk melihat. Net dibongkar. Seharusnya mungkin jika rumit untuk Java menggunakan windbg, meskipun jika Anda melakukannya dengan. Net banyak masalah akan sama.
Saya tidak suka menulis dalam C jika saya tidak perlu, tetapi saya pikir banyak dari klaim yang dibuat dalam jawaban ini bahwa menggembar-gemborkan kecepatan bahasa selain C dapat dikesampingkan dengan hanya membongkar rutinitas yang sama di C dan dalam bahasa pilihan tingkat tinggi Anda, terutama jika banyak data terlibat seperti yang umum dalam aplikasi penting kinerja. Fortran mungkin pengecualian dalam bidang keahliannya, tidak tahu. Apakah levelnya lebih tinggi dari C?
Pertama kali saya membandingkan kode JITed dengan kode asli diselesaikan setiap dan semua pertanyaan apakah. Kode bersih dapat berjalan sebanding dengan kode C. Level ekstra abstraksi dan semua pemeriksaan keselamatan datang dengan biaya yang signifikan. Biaya yang sama mungkin akan berlaku untuk Java, tetapi jangan mengambil kata saya untuk itu, cobalah pada sesuatu di mana kinerja sangat penting. (Adakah yang cukup tahu tentang Java JITed untuk menemukan prosedur yang dikompilasi dalam memori? Ini tentunya harus dimungkinkan)
sumber
1) Seperti yang orang lain katakan, C tidak terlalu banyak untuk Anda. Tidak ada variabel inisialisasi, tidak ada batas array memeriksa, tidak ada manajemen memori, dll. Fitur-fitur dalam bahasa lain biaya memori dan siklus CPU yang tidak menghabiskan C.
2) Jawaban yang mengatakan bahwa C kurang abstrak dan karena itu lebih cepat hanya setengah benar saya pikir. Secara teknis, jika Anda memiliki "kompiler yang cukup maju" untuk bahasa X, maka bahasa X dapat mendekati atau menyamai kecepatan C. Perbedaannya dengan C adalah karena ia memetakan dengan sangat jelas (jika Anda telah mengambil kursus arsitektur) dan langsung ke bahasa assembly yang bahkan kompiler naif dapat melakukan pekerjaan yang layak. Untuk sesuatu seperti Python, Anda memerlukan kompiler yang sangat canggih untuk memprediksi kemungkinan jenis objek dan menghasilkan kode mesin dengan cepat - semantik C cukup sederhana sehingga kompiler sederhana dapat melakukannya dengan baik.
sumber
Kembali ke masa lalu, hanya ada dua jenis bahasa: dikompilasi dan ditafsirkan.
Bahasa yang dikompilasi menggunakan "kompiler" untuk membaca sintaksis bahasa dan mengkonversinya menjadi kode bahasa assembly yang identik, yang dapat dari sekadar langsung pada CPU. Bahasa yang ditafsirkan menggunakan beberapa skema yang berbeda, tetapi pada dasarnya sintaksis bahasa diubah menjadi bentuk peralihan, dan kemudian dijalankan dalam "penerjemah", lingkungan untuk mengeksekusi kode.
Jadi, dalam arti tertentu, ada "lapisan" lain - penerjemah - antara kode dan mesin. Dan, seperti yang selalu terjadi di komputer, lebih banyak berarti lebih banyak sumber daya digunakan. Penerjemah lebih lambat, karena mereka harus melakukan lebih banyak operasi.
Baru-baru ini, kami telah melihat lebih banyak bahasa hibrida seperti Jawa, yang menggunakan kompiler dan juru bahasa untuk membuatnya bekerja. Memang rumit, tetapi JVM lebih cepat, lebih canggih, dan jauh lebih dioptimalkan daripada penterjemah lama, sehingga JVM memiliki perubahan kinerja yang jauh lebih baik (seiring waktu) lebih dekat dengan kode yang langsung dikompilasi. Tentu saja, kompiler yang lebih baru juga memiliki trik optimisasi yang lebih mewah sehingga mereka cenderung menghasilkan kode yang jauh lebih baik daripada sebelumnya. Tetapi sebagian besar optimasi, paling sering (meskipun tidak selalu) membuat beberapa jenis trade-off sehingga mereka tidak selalu lebih cepat dalam semua situasi. Seperti yang lainnya, tidak ada yang datang secara gratis, sehingga pengoptimal harus membual dari suatu tempat (walaupun sering kali menggunakan kompilasi-waktu CPU untuk menghemat runtime CPU).
Kembali ke C, itu adalah bahasa yang sederhana, yang dapat dikompilasi menjadi perakitan yang cukup optimal dan kemudian dijalankan langsung pada mesin target. Di C, jika Anda menambah bilangan bulat, kemungkinan besar itu hanya satu langkah assembler di CPU, di Jawa, namun, itu bisa menjadi jauh lebih banyak dari itu (dan dapat mencakup sedikit pengumpulan sampah juga: -) C menawarkan Anda sebuah abstraksi yang jauh lebih dekat ke mesin (assembler adalah yang terdekat), tetapi Anda akhirnya harus melakukan lebih banyak pekerjaan untuk membuatnya berjalan dan tidak terlindungi, mudah digunakan atau ramah kesalahan. Sebagian besar bahasa lain memberi Anda abstraksi yang lebih tinggi dan mengurus lebih banyak detail yang mendasari untuk Anda, tetapi sebagai ganti fungsi lanjutannya, mereka membutuhkan lebih banyak sumber daya untuk dijalankan. Ketika Anda menggeneralisasi beberapa solusi, Anda harus menangani rentang komputasi yang lebih luas,
Paul.
sumber
++i
mungkin dikompilasi ke "add [ebp - 8], 1". Bukan untuk mengatakan bahwa mengambil, kenaikan, toko masih belum terjadi, tetapi ini diurus oleh CPU, dan hanya satu instruksi, seperti kata Paul.Mengesampingkan teknik optimasi canggih seperti optimasi hot-spot , pra-kompilasi meta-algoritma , dan berbagai bentuk paralelisme , kecepatan dasar bahasa berkorelasi kuat dengan kompleksitas di balik layar yang diperlukan untuk mendukung operasi yang biasanya ditentukan dalam loop batin .
Mungkin yang paling jelas adalah memeriksa validitas pada referensi memori tidak langsung - seperti memeriksa pointer
null
dan memeriksa indeks terhadap batasan array. Sebagian besar bahasa tingkat tinggi melakukan pemeriksaan ini secara implisit, tetapi C tidak. Namun, ini tidak selalu merupakan batasan mendasar dari bahasa-bahasa lain ini - kompiler yang cukup pintar mungkin dapat menghapus pemeriksaan ini dari loop dalam suatu algoritma melalui beberapa bentuk gerakan kode loop-invariant .Keuntungan yang lebih mendasar dari C (dan pada tingkat yang sama C ++ yang terkait erat) adalah ketergantungan yang besar pada alokasi memori berbasis stack , yang secara inheren cepat untuk alokasi, deallokasi, dan akses. Dalam C (dan C ++) tumpukan panggilan utama dapat digunakan untuk alokasi primitif, array, dan agregat (
struct
/class
).Sementara C memang menawarkan kemampuan untuk mengalokasikan memori secara dinamis dengan ukuran dan masa pakai yang sewenang-wenang (menggunakan apa yang disebut 'tumpukan'), hal itu dihindari secara default (tumpukan digunakan sebagai gantinya).
Menariknya, kadang-kadang mungkin untuk mereplikasi strategi alokasi memori C dalam lingkungan runtime bahasa pemrograman lain. Ini telah ditunjukkan oleh asm.js , yang memungkinkan kode yang ditulis dalam C atau C ++ untuk diterjemahkan ke dalam subset dari JavaScript dan berjalan dengan aman di lingkungan browser web - dengan kecepatan yang hampir sama dengan aslinya.
Sebagai tambahan, area lain di mana C dan C ++ mengalahkan sebagian besar bahasa lain untuk kecepatan adalah kemampuan untuk berintegrasi mulus dengan set instruksi mesin asli. Contoh penting dari hal ini adalah ketersediaan (kompiler dan platform tergantung) dari intrinsik SIMD yang mendukung konstruksi algoritme kustom yang mengambil keuntungan dari perangkat keras pemrosesan paralel yang kini hampir di mana-mana - sambil tetap menggunakan abstraksi alokasi data yang disediakan oleh bahasa (lebih rendah). alokasi alokasi -level dikelola oleh kompiler).
sumber
Saya telah menemukan jawaban di tautan tentang mengapa beberapa bahasa lebih cepat dan ada yang lebih lambat, saya harap ini akan lebih jelas tentang mengapa C atau C ++ lebih cepat daripada yang lain, Ada beberapa bahasa lain yang lebih cepat dari C, tapi kami tidak bisa gunakan semuanya. Beberapa penjelasan -
Salah satu alasan utama mengapa Fortran tetap penting adalah karena ia cepat: angka-angka rutinitas yang ditulis dalam Fortran cenderung lebih cepat daripada rutinitas yang setara yang ditulis dalam kebanyakan bahasa lain. Bahasa yang bersaing dengan Fortran di ruang ini — C dan C ++ - digunakan karena mereka bersaing dengan kinerja ini.
Ini menimbulkan pertanyaan: mengapa? Ada apa dengan C ++ dan Fortran yang membuatnya cepat, dan mengapa mereka mengungguli bahasa populer lainnya, seperti Java atau Python?
Menafsirkan versus mengkompilasi Ada banyak cara untuk mengategorikan dan mendefinisikan bahasa pemrograman, sesuai dengan gaya pemrograman yang mereka dorong dan fitur yang mereka tawarkan. Saat melihat kinerja, perbedaan tunggal terbesar adalah antara bahasa yang ditafsirkan dan yang dikompilasi.
Kesenjangannya tidak sulit; sebaliknya, ada spektrum. Di satu sisi, kami memiliki bahasa kompilasi tradisional, grup yang mencakup Fortran, C, dan C ++. Dalam bahasa ini, ada tahap kompilasi diskrit yang menerjemahkan kode sumber suatu program ke dalam bentuk yang dapat dieksekusi yang dapat digunakan prosesor.
Proses kompilasi ini memiliki beberapa langkah. Kode sumber dianalisis dan diuraikan. Kesalahan pengkodean dasar seperti kesalahan ketik dan kesalahan ejaan dapat dideteksi pada saat ini. Kode yang diurai digunakan untuk menghasilkan representasi dalam-memori, yang juga dapat digunakan untuk mendeteksi kesalahan — kali ini, kesalahan semantik, seperti fungsi panggilan yang tidak ada, atau mencoba melakukan operasi aritmatika pada string teks.
Representasi dalam memori ini kemudian digunakan untuk menggerakkan pembuat kode, bagian yang menghasilkan kode yang dapat dieksekusi. Optimasi kode, untuk meningkatkan kinerja kode yang dihasilkan, dilakukan pada berbagai waktu dalam proses ini: optimasi tingkat tinggi dapat dilakukan pada representasi kode, dan optimasi tingkat yang lebih rendah digunakan pada output pembuat kode.
Sebenarnya mengeksekusi kode terjadi nanti. Seluruh proses kompilasi hanya digunakan untuk membuat sesuatu yang dapat dieksekusi.
Di ujung yang berlawanan, kami memiliki juru bahasa. Penerjemah akan menyertakan tahap penguraian mirip dengan kompiler, tetapi ini kemudian digunakan untuk mengarahkan eksekusi langsung, dengan program yang sedang dijalankan segera.
Penerjemah yang paling sederhana memiliki kode yang dapat dieksekusi di dalamnya yang sesuai dengan berbagai fitur yang didukung bahasa — sehingga akan memiliki fungsi untuk menambahkan angka, menggabungkan string, apa pun yang dimiliki bahasa tertentu. Saat mem-parsing kode, itu akan mencari fungsi yang sesuai dan menjalankannya. Variabel yang dibuat dalam program akan disimpan dalam semacam tabel pencarian yang memetakan nama mereka ke data mereka.
Contoh paling ekstrim dari gaya interpreter adalah sesuatu seperti file batch atau skrip shell. Dalam bahasa-bahasa ini, kode yang dapat dieksekusi seringkali bahkan tidak dibangun ke dalam interpreter itu sendiri, tetapi agak terpisah, program mandiri.
Jadi mengapa ini membuat perbedaan untuk kinerja? Secara umum, setiap lapisan tipuan mengurangi kinerja. Sebagai contoh, cara tercepat untuk menambahkan dua angka adalah dengan memasukkan kedua angka tersebut dalam register dalam prosesor, dan menggunakan instruksi tambahan prosesor. Itulah yang dapat dilakukan oleh program yang dikompilasi; mereka dapat memasukkan variabel ke dalam register dan memanfaatkan instruksi prosesor. Tetapi dalam program yang ditafsirkan, penambahan yang sama mungkin membutuhkan dua pencarian dalam tabel variabel untuk mengambil nilai yang akan ditambahkan, kemudian memanggil fungsi untuk melakukan penambahan. Fungsi itu mungkin sangat baik menggunakan instruksi prosesor yang sama seperti program yang dikompilasi menggunakan untuk melakukan penambahan yang sebenarnya, tetapi semua pekerjaan tambahan sebelum instruksi tersebut benar-benar dapat digunakan membuat segalanya lebih lambat.
Jika Anda ingin tahu lebih banyak, silakan periksa Sumber
sumber
Beberapa algoritma C ++ lebih cepat daripada C, dan beberapa implementasi algoritma atau pola desain dalam bahasa lain bisa lebih cepat dari C.
Ketika orang mengatakan bahwa C itu cepat, dan kemudian berbicara tentang bahasa lain, mereka umumnya menggunakan kinerja C sebagai tolok ukur.
sumber
Dengan kompiler optimisasi modern, sangat tidak mungkin bahwa program C murni akan menjadi jauh lebih cepat daripada dikompilasi .net kode, jika sama sekali. Dengan peningkatan produktivitas yang diberikan kerangka kerja seperti .net kepada pengembang, Anda dapat melakukan hal-hal dalam sehari yang biasanya membutuhkan waktu berminggu-minggu atau berbulan-bulan dalam C. Biasanya, ditambah dengan biaya perangkat keras yang murah dibandingkan dengan gaji pengembang, WAY lebih murah untuk menulis barang-barang dalam bahasa tingkat tinggi dan melemparkan perangkat keras pada kelambatan apa pun.
Alasan Jeff dan Joel berbicara tentang C menjadi bahasa "programmer nyata" adalah karena tidak ada pegangan di C. Anda harus mengalokasikan memori Anda sendiri, membatalkan alokasi memori itu, melakukan pemeriksaan batas-batas Anda sendiri, dll. Tidak ada hal seperti itu sebagai objek baru (); Tidak ada pengumpulan sampah, kelas, OOP, kerangka kerja entitas, LINQ, properti, atribut, bidang, atau semacamnya. Anda harus mengetahui hal-hal seperti pointer aritmatika dan cara melakukan dereferensi pointer. Dan, dalam hal ini, ketahui dan pahami apa itu pointer. Anda harus tahu apa itu stack frame dan apakah pointer instruksi itu. Anda harus tahu model memori arsitektur CPU yang sedang Anda kerjakan. Ada banyak pemahaman implisit tentang arsitektur komputer mikro (biasanya yangkomputer mikro yang sedang Anda kerjakan) saat memprogram dalam C yang tidak ada atau perlu saat pemrograman dalam sesuatu seperti C # atau Java. Semua informasi itu telah dimuat ke programmer compiler (atau VM).
sumber
Perbedaan antara otomatis dan manual, bahasa tingkat yang lebih tinggi adalah abstraksi yang otomatis. C / C ++ dikontrol dan ditangani secara manual, bahkan kode pengecekan error terkadang merupakan pekerjaan manual.
C dan C ++ juga dikompilasi bahasa yang berarti tidak ada yang menjalankan bisnis di mana-mana, bahasa-bahasa ini harus disesuaikan untuk perangkat keras yang bekerja dengan Anda sehingga menambahkan lapisan tambahan gotcha. Meskipun ini sedikit menakutkan sekarang karena kompiler C / C ++ menjadi lebih umum di semua platform. Anda dapat melakukan kompilasi lintas antar platform. Ini masih bukan situasi berjalan di mana-mana, pada dasarnya Anda menginstruksikan kompiler A untuk mengkompilasi terhadap kompiler B kode yang sama arsitektur yang berbeda.
Intinya bahasa C tidak dimaksudkan untuk mudah dipahami atau alasan, ini juga mengapa mereka disebut sebagai bahasa sistem. Mereka keluar sebelum semua omong kosong abstraksi tingkat tinggi ini. Ini juga mengapa mereka tidak digunakan untuk pemrograman web front end. Mereka tidak cocok dengan tugas itu, maksud mereka untuk memecahkan masalah rumit yang tidak dapat diselesaikan dengan perkakas bahasa konvensional.
Inilah sebabnya mengapa Anda mendapatkan hal-hal gila seperti (mikro-arsitektur, driver, fisika kuantum, Game AAA, sistem operasi) ada hal-hal yang cocok untuk C dan C ++. Kecepatan dan angka menjadi area utama.
sumber
C cepat karena dikompilasi secara asli, bahasa tingkat rendah. Tapi C bukan yang tercepat. The Rekursif Fibonacci benchmark menunjukkan bahwa Rust, Crystal, dan Nim bisa lebih cepat.
sumber
Ada banyak alasan, termasuk:
sumber