Performa C ++ vs.Java / C #

119

Pemahaman saya adalah bahwa C / C ++ menghasilkan kode native untuk dijalankan pada arsitektur mesin tertentu. Sebaliknya, bahasa seperti Java dan C # berjalan di atas mesin virtual yang mengabstraksi arsitektur asli. Logikanya, tampaknya tidak mungkin bagi Java atau C # untuk menyamai kecepatan C ++ karena langkah perantara ini, namun saya telah diberitahu bahwa kompiler terbaru ("hot spot") dapat mencapai kecepatan ini atau bahkan melampauinya.

Mungkin ini lebih merupakan pertanyaan kompilator daripada pertanyaan bahasa, tetapi adakah yang bisa menjelaskan dalam bahasa Inggris sederhana bagaimana mungkin salah satu bahasa mesin virtual ini berkinerja lebih baik daripada bahasa asli?

pengguna23126
sumber
Java dan C # dapat melakukan pengoptimalan berdasarkan bagaimana aplikasi sebenarnya dijalankan menggunakan kode yang tersedia saat runtime. misalnya, ia dapat memasukkan kode dalam pustaka bersama yang sebenarnya dapat berubah saat program berjalan dan masih benar.
Peter Lawrey
Beberapa pengukuran aktual untuk diperiksa sebelum membaca banyak teori yang sangat rapuh dalam jawaban ini: shootout.alioth.debian.org/u32/…
Justicle

Jawaban:

178

Secara umum, C # dan Java bisa sama cepatnya atau lebih cepat karena kompilator JIT - kompilator yang mengkompilasi IL Anda saat pertama kali dijalankan - dapat membuat pengoptimalan yang tidak bisa dilakukan oleh program yang dikompilasi C ++ karena ia dapat melakukan kueri pada mesin. Ini dapat menentukan apakah mesin itu Intel atau AMD; Pentium 4, Core Solo, atau Core Duo; atau jika mendukung SSE4, dll.

Program C ++ harus dikompilasi terlebih dahulu biasanya dengan pengoptimalan campuran agar dapat berjalan dengan baik di semua mesin, tetapi tidak dioptimalkan sebanyak mungkin untuk konfigurasi tunggal (yaitu prosesor, set instruksi, perangkat keras lain).

Selain itu, fitur bahasa tertentu memungkinkan compiler di C # dan Java membuat asumsi tentang kode Anda yang memungkinkannya mengoptimalkan bagian tertentu yang tidak aman untuk dilakukan compiler C / C ++. Ketika Anda memiliki akses ke pointer, ada banyak pengoptimalan yang tidak aman.

Selain itu, Java dan C # dapat melakukan alokasi heap dengan lebih efisien daripada C ++ karena lapisan abstraksi antara pengumpul sampah dan kode Anda memungkinkannya melakukan semua kompresi heapnya sekaligus (operasi yang cukup mahal).

Sekarang saya tidak dapat berbicara untuk Java pada poin berikutnya ini, tetapi saya tahu bahwa C # misalnya akan benar-benar menghapus metode dan panggilan metode ketika mengetahui tubuh metode kosong. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda.

Jadi seperti yang Anda lihat, ada banyak alasan mengapa implementasi C # atau Java tertentu akan lebih cepat.

Sekarang ini semua dikatakan, pengoptimalan khusus dapat dilakukan di C ++ yang akan menerbangkan apa pun yang dapat Anda lakukan dengan C #, terutama di bidang grafis dan kapan pun Anda dekat dengan perangkat keras. Pointer melakukan keajaiban di sini.

Jadi, tergantung pada apa yang Anda tulis, saya akan memilih salah satunya. Tetapi jika Anda menulis sesuatu yang tidak bergantung pada perangkat keras (driver, permainan video, dll), saya tidak akan khawatir tentang kinerja C # (sekali lagi tidak dapat berbicara tentang Java). Ini akan baik-baik saja.

Di sisi Jawa, @Swati menunjukkan artikel yang bagus:

https://www.ibm.com/developerworks/library/j-jtp09275

Orion Adrian
sumber
Alasan Anda palsu - program C ++ dibangun untuk arsitektur target mereka, mereka tidak perlu beralih saat runtime.
Justicle
3
@Justicle Yang terbaik yang ditawarkan oleh c ++ compiler Anda untuk arsitektur yang berbeda biasanya adalah x86, x64, ARM, dan lainnya. Sekarang Anda dapat memintanya untuk menggunakan fitur tertentu (katakanlah SSE2) dan jika Anda beruntung, ia bahkan akan menghasilkan beberapa kode cadangan jika fitur itu tidak tersedia, tapi itu sesederhana mungkin. Tentu tidak ada spesialisasi tergantung pada ukuran cache dan yang lainnya.
Voo
4
Lihat shootout.alioth.debian.org/u32/… untuk contoh teori ini tidak terjadi.
Justicle
1
Sejujurnya, ini adalah salah satu jawaban terburuk. Itu sangat tidak berdasar, saya hanya bisa membalikkannya. Terlalu banyak generalisasi, terlalu banyak ketidaktahuan (mengoptimalkan fungsi kosong sebenarnya hanyalah puncak gunung es). Satu kompiler C ++ mewah memiliki: Waktu. Kemewahan lainnya: Tidak ada pemeriksaan yang diberlakukan. Tetapi temukan lebih banyak di stackoverflow.com/questions/145110/c-performance-vs-java-c/… .
Sebastian Mach
1
@OrionAdrian ok kita lingkaran penuh sekarang ... Lihat shootout.alioth.debian.org/u32/… untuk contoh teori ini tidak terjadi. Dengan kata lain, tunjukkan bahwa teori Anda dapat dibuktikan kebenarannya sebelum membuat pernyataan spekulatif yang tidak jelas.
Justicle
197

JIT vs. Kompiler Statis

Seperti yang sudah dikatakan di posting sebelumnya, JIT dapat mengkompilasi IL / bytecode menjadi kode native saat runtime. Biaya sebesar itu disebutkan, tetapi tidak sampai pada kesimpulannya:

JIT memiliki satu masalah besar yaitu ia tidak dapat mengkompilasi semuanya: kompilasi JIT membutuhkan waktu, sehingga JIT hanya akan mengkompilasi beberapa bagian kode, sedangkan kompiler statis akan menghasilkan biner asli yang lengkap: Untuk beberapa jenis program, statis kompiler akan dengan mudah mengungguli JIT.

Tentu saja, C # (atau Java, atau VB) biasanya lebih cepat menghasilkan solusi yang layak dan kuat daripada C ++ (jika hanya karena C ++ memiliki semantik yang kompleks, dan pustaka standar C ++, meskipun menarik dan kuat, cukup buruk jika dibandingkan dengan yang lengkap. cakupan pustaka standar dari .NET atau Java), jadi biasanya, perbedaan antara C ++ dan .NET atau Java JIT tidak akan terlihat oleh sebagian besar pengguna, dan untuk biner yang sangat penting, Anda masih dapat memanggil pemrosesan C ++ dari C # atau Java (meskipun panggilan asli semacam ini bisa sangat mahal harganya) ...

Pemrograman C ++

Perhatikan bahwa biasanya, Anda membandingkan kode runtime C ++ dengan padanannya di C # atau Java. Tetapi C ++ memiliki satu fitur yang dapat mengungguli Java / C # di luar kotak, yaitu template metaprograming: Pemrosesan kode akan dilakukan pada waktu kompilasi (dengan demikian, meningkatkan waktu kompilasi secara signifikan), menghasilkan runtime nol (atau hampir nol).

Saya belum begitu melihat efek kehidupan nyata pada ini (saya bermain hanya dengan konsep, tetapi pada saat itu, perbedaannya adalah detik eksekusi untuk JIT, dan nol untuk C ++), tetapi ini layak untuk disebutkan, di samping fakta template metaprograming tidak sepele...

Sunting 2011-06-10: Dalam C ++, bermain dengan tipe dilakukan pada waktu kompilasi, yang berarti menghasilkan kode generik yang memanggil kode non-generik (misalnya parser generik dari string ke tipe T, memanggil API perpustakaan standar untuk tipe T yang dikenali, dan membuat parser mudah diperluas oleh penggunanya) sangat mudah dan sangat efisien, sedangkan padanan di Java atau C # paling sulit untuk ditulis, dan akan selalu lebih lambat dan diselesaikan pada waktu proses bahkan ketika jenisnya diketahui pada waktu kompilasi, artinya satu-satunya harapan Anda adalah agar JIT menyejajarkan semuanya.

...

Sunting 2011-09-20: Tim di belakang Blitz ++ ( Homepage , Wikipedia ) pergi ke arah itu, dan tampaknya, tujuan mereka adalah untuk mencapai kinerja FORTRAN pada kalkulasi ilmiah dengan memindahkan sebanyak mungkin dari eksekusi runtime ke waktu kompilasi, melalui metaprogramming template C ++ . Jadi " Saya belum begitu melihat efek kehidupan nyata tentang hal ini " bagian saya tulis di atas tampaknya tidak eksis dalam kehidupan nyata.

Penggunaan Memori C ++ Asli

C ++ memiliki penggunaan memori yang berbeda dari Java / C #, dan karenanya, memiliki kelebihan / kekurangan yang berbeda.

Tidak peduli optimasi JIT, tidak ada yang akan berjalan secepat akses pointer langsung ke memori (mari kita abaikan sebentar cache prosesor, dll.). Jadi, jika Anda memiliki data yang berdekatan dalam memori, mengaksesnya melalui pointer C ++ (yaitu pointer C ... Mari beri Caesar haknya) akan berjalan kali lebih cepat daripada di Java / C #. Dan C ++ memiliki RAII, yang membuat banyak pemrosesan jauh lebih mudah daripada di C # atau bahkan di Java. C ++ tidak perlu usingmencakup keberadaan objeknya. Dan C ++ tidak memiliki finallyklausa. Ini bukan sebuah kesalahan.

:-)

Dan meskipun struct mirip C # primitif, objek C ++ "pada tumpukan" tidak akan dikenakan biaya pada alokasi dan penghancuran, dan tidak memerlukan GC untuk bekerja di utas independen untuk melakukan pembersihan.

Sedangkan untuk fragmentasi memori, pengalokasi memori pada tahun 2008 bukanlah pengalokasi memori lama dari tahun 1980 yang biasanya dibandingkan dengan GC: Alokasi C ++ tidak dapat dipindahkan ke memori, benar, tetapi kemudian, seperti pada sistem file Linux: Siapa yang membutuhkan hard disk defragmenting saat fragmentasi tidak terjadi? Menggunakan pengalokasi yang tepat untuk tugas yang tepat harus menjadi bagian dari perangkat pengembang C ++. Sekarang, menulis pengalokasi tidaklah mudah, dan kemudian, kebanyakan dari kita memiliki hal-hal yang lebih baik untuk dilakukan, dan untuk sebagian besar penggunaan, RAII atau GC lebih dari cukup.

Edit 2011-10-04: Untuk contoh tentang pengalokasi yang efisien: Pada platform Windows, sejak Vista, Heap Fragmentasi Rendah diaktifkan secara default. Untuk versi sebelumnya, LFH dapat diaktifkan dengan memanggil fungsi WinAPI HeapSetInformation ). Di OS lain, pengalokasi alternatif disediakan (lihathttps://secure.wikimedia.org/wikipedia/en/wiki/Malloc untuk daftar)

Sekarang, model memori menjadi lebih rumit dengan munculnya teknologi multicore dan multithreading. Di bidang ini, saya kira .NET memiliki keunggulan, dan Java, saya diberi tahu, memegang posisi teratas. Sangat mudah bagi beberapa hacker "on the bare metal" untuk memuji kode "near the machine" miliknya. Tetapi sekarang, lebih sulit untuk menghasilkan perakitan yang lebih baik dengan tangan daripada membiarkan kompilator menjalankan tugasnya. Untuk C ++, kompilator biasanya menjadi lebih baik daripada peretas sejak satu dekade. Untuk C # dan Java, ini lebih mudah.

Namun, C ++ 0x standar baru akan memberlakukan model memori sederhana ke kompiler C ++, yang akan menstandarisasi (dan dengan demikian menyederhanakan) kode multiprosesing / paralel / threading yang efektif dalam C ++, dan membuat pengoptimalan menjadi lebih mudah dan aman bagi penyusun. Tapi kemudian, kita akan melihat dalam beberapa tahun jika janjinya dipenuhi.

C ++ / CLI vs. C # / VB.NET

Catatan: Di bagian ini, saya berbicara tentang C ++ / CLI, yaitu C ++ yang dihosting oleh .NET, bukan C ++ asli.

Minggu lalu, saya mengikuti pelatihan tentang pengoptimalan .NET, dan menemukan bahwa kompiler statis sangat penting. Sama pentingnya dari JIT.

Kode yang sama yang dikompilasi di C ++ / CLI (atau leluhurnya, Managed C ++) bisa jadi kali lebih cepat daripada kode yang sama yang diproduksi di C # (atau VB.NET, yang kompilernya menghasilkan IL yang sama daripada C #).

Karena kompilator statis C ++ jauh lebih baik untuk menghasilkan kode yang sudah dioptimalkan daripada C #.

Misalnya, fungsi sebaris dalam .NET terbatas pada fungsi yang bytecode-nya kurang atau sama dengan 32 byte. Jadi, beberapa kode dalam C # akan menghasilkan pengakses 40 byte, yang tidak akan pernah di-inline oleh JIT. Kode yang sama di C ++ / CLI akan menghasilkan aksesor 20 byte, yang akan di-inline oleh JIT.

Contoh lain adalah variabel sementara, yang hanya dikompilasi oleh kompilator C ++ sementara masih disebutkan dalam IL yang dihasilkan oleh kompilator C #. Pengoptimalan kompilasi statis C ++ akan menghasilkan lebih sedikit kode, sehingga mengizinkan pengoptimalan JIT yang lebih agresif lagi.

Alasannya berspekulasi adalah fakta bahwa compiler C ++ / CLI mendapatkan keuntungan dari teknik pengoptimalan yang luas dari compiler asli C ++.

Kesimpulan

Saya suka C ++.

Tapi sejauh yang saya lihat, C # atau Java semuanya merupakan taruhan yang lebih baik. Bukan karena mereka lebih cepat dari C ++, tetapi karena ketika Anda menambahkan kualitasnya, mereka akhirnya menjadi lebih produktif, membutuhkan lebih sedikit pelatihan, dan memiliki pustaka standar yang lebih lengkap daripada C ++. Dan untuk sebagian besar program, perbedaan kecepatannya (dengan satu atau lain cara) akan dapat diabaikan ...

Sunting (2011-06-06)

Pengalaman saya di C # /. NET

Saya sekarang memiliki 5 bulan pengkodean C # profesional yang hampir eksklusif (yang menambahkan hingga CV saya sudah penuh dengan C ++ dan Java, dan sentuhan C ++ / CLI).

Saya bermain dengan WinForms (Ahem ...) dan WCF (keren!), Dan WPF (Keren !!!! Baik melalui XAML dan raw C #. WPF sangat mudah Saya percaya Swing tidak bisa dibandingkan dengannya), dan C # 4.0.

Kesimpulannya adalah bahwa meskipun lebih mudah / lebih cepat untuk menghasilkan kode yang berfungsi di C # / Java daripada di C ++, jauh lebih sulit untuk menghasilkan kode yang kuat, aman, dan tangguh di C # (dan bahkan lebih sulit di Java) daripada di C ++. Ada banyak alasan, tetapi dapat diringkas oleh:

  1. Generik tidak sekuat template ( coba tulis metode Parse generik yang efisien (dari string ke T), atau yang setara dengan boost :: lexical_cast di C # yang efisien untuk memahami masalahnya )
  2. RAII tetap tak tertandingi ( GC masih bisa bocor (ya, saya harus menangani masalah itu) dan hanya akan menangani memori. Bahkan C # usingtidak semudah dan sekuat itu karena menulis implementasi Buang yang benar itu sulit )
  3. C # readonlydan Java finalsama sekali tidak berguna seperti C ++const ( Tidak ada cara Anda dapat mengekspos data kompleks yang hanya dapat dibaca (Pohon Node, misalnya) di C # tanpa kerja yang luar biasa, sementara itu adalah fitur bawaan C ++. Data yang tidak dapat diubah adalah solusi yang menarik , tetapi tidak semuanya bisa dibuat tidak berubah, jadi itu tidak cukup, sejauh ini ).

Jadi, C # tetap menjadi bahasa yang menyenangkan selama Anda menginginkan sesuatu yang berhasil, tetapi bahasa yang membuat frustrasi saat Anda menginginkan sesuatu yang selalu dan aman berfungsi.

Java bahkan lebih membuat frustasi, karena memiliki masalah yang sama daripada C #, dan banyak lagi: Kurangnya usingkata kunci yang setara dengan C # , seorang kolega saya yang sangat terampil menghabiskan terlalu banyak waktu untuk memastikan sumber dayanya dibebaskan dengan benar, sedangkan padanan di C ++ akan mudah (menggunakan destruktor dan petunjuk cerdas).

Jadi saya kira keuntungan produktivitas C # / Java terlihat untuk sebagian besar kode ... sampai Anda membutuhkan kode untuk sesempurna mungkin. Hari itu, Anda akan tahu rasa sakit. (Anda tidak akan percaya apa yang diminta dari server dan aplikasi GUI kami ...).

Tentang Java sisi server dan C ++

Saya terus berhubungan dengan tim server (saya bekerja 2 tahun di antara mereka, sebelum kembali ke tim GUI), di sisi lain gedung, dan saya belajar sesuatu yang menarik.

Beberapa tahun terakhir, trennya adalah aplikasi server Java ditakdirkan untuk menggantikan aplikasi server C ++ lama, karena Java memiliki banyak kerangka kerja / alat, dan mudah dipelihara, diterapkan, dll. Dll.

... Sampai masalah latensi rendah muncul beberapa bulan terakhir ini. Kemudian, aplikasi server Java, tidak peduli pengoptimalan yang dilakukan oleh tim Java kami yang terampil, kalah bersaing dengan yang lama, server C ++ yang tidak benar-benar dioptimalkan.

Saat ini, keputusannya adalah mempertahankan server Java untuk penggunaan umum di mana performa masih penting, tidak peduli dengan target latensi rendah, dan secara agresif mengoptimalkan aplikasi server C ++ yang sudah lebih cepat untuk kebutuhan latensi rendah dan latensi ultra-rendah.

Kesimpulan

Tidak ada yang sesederhana yang diharapkan.

Java, dan bahkan lebih banyak lagi C #, adalah bahasa yang keren, dengan pustaka dan kerangka kerja standar yang luas, tempat Anda dapat membuat kode dengan cepat, dan segera mendapatkan hasil.

Tetapi ketika Anda membutuhkan kekuatan mentah, pengoptimalan yang kuat dan sistematis, dukungan kompiler yang kuat, fitur bahasa yang kuat dan keamanan mutlak, Java dan C # mempersulit untuk memenangkan persentase kualitas terakhir yang hilang tetapi penting yang Anda butuhkan untuk tetap berada di atas persaingan.

Seolah-olah Anda membutuhkan lebih sedikit waktu dan pengembang yang kurang berpengalaman di C # / Java daripada di C ++ untuk menghasilkan kode kualitas rata-rata, tetapi di sisi lain, saat Anda membutuhkan kode kualitas yang sangat baik untuk menyempurnakan, tiba-tiba lebih mudah dan lebih cepat untuk mendapatkan hasil tepat di C ++.

Tentu saja, ini adalah persepsi saya sendiri, mungkin terbatas pada kebutuhan khusus kita.

Tapi tetap saja, itulah yang terjadi hari ini, baik di tim GUI dan tim sisi server.

Tentu saja, saya akan memperbarui posting ini jika sesuatu yang baru terjadi.

Sunting (2011-06-22)

"Kami menemukan bahwa dalam hal kinerja, C ++ menang dengan selisih yang besar. Namun, itu juga membutuhkan upaya penyetelan yang paling ekstensif, banyak di antaranya dilakukan pada tingkat kecanggihan yang tidak akan tersedia untuk pemrogram rata-rata.

[...] Versi Java mungkin yang paling sederhana untuk diterapkan, tetapi yang paling sulit untuk dianalisis performanya. Secara khusus, efek seputar pengumpulan sampah rumit dan sangat sulit disetel. "

Sumber:

Sunting (2011-09-20)

"Kata-kata di Facebook adalah bahwa ' kode C ++ yang ditulis dengan wajar hanya berjalan cepat, ' yang menggarisbawahi upaya besar yang dihabiskan untuk mengoptimalkan kode PHP dan Java. Paradoksnya, kode C ++ lebih sulit untuk ditulis daripada di bahasa lain, tetapi kode yang efisien adalah jauh lebih mudah [untuk menulis dalam C ++ daripada dalam bahasa lain]. "

- Herb Sutter di // build / , mengutip Andrei Alexandrescu

Sumber:

paercebal
sumber
8
Anda mengedit setelah 5 bulan C # menjelaskan dengan tepat pengalaman saya (template lebih baik, lebih baik, RAII). +1. Ketiganya tetap menjadi fitur pembunuh pribadi saya untuk C ++ (atau D, yang saya belum punya waktu untuk itu).
Sebastian Mach
"Pemrosesan kode akan dilakukan pada waktu kompilasi". Oleh karena itu, pemrograman metaprogram hanya bekerja dalam program yang tersedia pada waktu kompilasi yang seringkali tidak terjadi, misalnya tidak mungkin untuk menulis pustaka ekspresi reguler yang berkinerja kompetitif di vanilla C ++ karena tidak mampu menghasilkan kode waktu proses (aspek penting dari metaprogramming).
JD
"bermain dengan tipe dilakukan pada waktu kompilasi ... padanan di Java atau C # paling sulit untuk ditulis, dan akan selalu lebih lambat dan diselesaikan saat runtime bahkan ketika tipe diketahui pada waktu kompilasi". Di C #, itu hanya benar untuk tipe referensi dan tidak benar untuk tipe nilai.
JD
1
"Tidak peduli pengoptimalan JIT, tidak ada yang akan berjalan secepat akses penunjuk langsung ke memori ... jika Anda memiliki data yang berdekatan dalam memori, mengaksesnya melalui penunjuk C ++ (yaitu penunjuk C ... Mari beri Caesar haknya) akan berjalan berkali-kali lebih cepat daripada di Java / C # ". Orang-orang telah mengamati Java mengalahkan C ++ pada tes SOR dari tolok ukur SciMark2 justru karena petunjuk menghalangi pengoptimalan terkait aliasing. blogs.oracle.com/dagastine/entry/sun_java_is_faster_than
JD
Juga perlu dicatat bahwa .NET melakukan spesialisasi jenis generik di seluruh pustaka yang ditautkan secara dinamis setelah menautkan sedangkan C ++ tidak bisa karena templat harus diselesaikan sebelum menautkan. Dan jelas keuntungan besar yang dimiliki obat generik dibandingkan template adalah pesan kesalahan yang dapat dipahami.
JD
48

Setiap kali saya berbicara tentang kinerja yang dikelola vs. tidak terkelola, saya suka menunjukkan seri Rico (dan Raymond) yang membandingkan versi C ++ dan C # dari kamus bahasa Mandarin / Inggris. Pencarian google ini akan membiarkan Anda membaca sendiri, tapi saya suka ringkasan Rico.

Jadi, apakah saya malu dengan kekalahan telak saya? Hampir tidak. Kode yang dikelola mendapat hasil yang sangat bagus untuk hampir tidak ada usaha. Untuk mengalahkan yang berhasil, Raymond harus:

  • Tulis file I / O nya sendiri
  • Tulis kelas senarnya sendiri
  • Tulis alokatornya sendiri
  • Tulis pemetaan internasionalnya sendiri

Tentu saja dia menggunakan perpustakaan tingkat bawah yang tersedia untuk melakukan ini, tetapi itu masih banyak pekerjaan. Bisakah Anda menyebut apa yang tersisa dari program STL? Saya tidak berpikir begitu, saya pikir dia menyimpan kelas std :: vector yang pada akhirnya tidak pernah menjadi masalah dan dia menyimpan fungsi find. Hampir semua hal lainnya hilang.

Jadi, ya, Anda pasti bisa mengalahkan CLR. Menurut saya, Raymond dapat membuat programnya berjalan lebih cepat.

Menariknya, waktu untuk mengurai file seperti yang dilaporkan oleh kedua program pengatur waktu internal hampir sama - masing-masing 30 md. Perbedaannya ada pada overhead.

Bagi saya intinya adalah dibutuhkan 6 revisi untuk versi yang tidak dikelola untuk mengalahkan versi yang dikelola yang merupakan port sederhana dari kode asli yang tidak dikelola. Jika Anda membutuhkan setiap kinerja terakhir (dan memiliki waktu dan keahlian untuk mendapatkannya), Anda harus tidak dikelola, tetapi bagi saya, saya akan mengambil urutan keuntungan yang saya miliki pada versi pertama di atas 33 % Saya mendapatkan jika saya mencoba 6 kali.

Jon Norton
sumber
3
link mati, menemukan artikel yang disebutkan di sini: blogs.msdn.com/b/ricom/archive/2005/05/10/416151.aspx
gjvdkamp
Pertama-tama, jika kita melihat kode Raymond Chen, dia jelas tidak memahami C ++ atau struktur data dengan baik. Kodenya hampir mencapai langsung kode C tingkat rendah bahkan dalam kasus di mana kode C tidak memiliki manfaat kinerja (sepertinya itu semacam ketidakpercayaan dan mungkin kurangnya pengetahuan tentang cara menggunakan profiler). Dia juga gagal untuk memahami cara yang paling logis dalam mengimplementasikan kamus (dia menggunakan std :: find demi Tuhan). Jika ada sesuatu yang baik tentang Java, Python, C #, dll. - semuanya menyediakan kamus yang sangat efisien ...
stinky472
Tries atau bahkan std :: map akan jauh lebih menguntungkan terhadap C ++ atau bahkan tabel hash. Terakhir, kamus adalah jenis program yang paling diuntungkan dari pustaka dan kerangka kerja tingkat tinggi. Itu tidak menunjukkan perbedaan dalam bahasa sebanyak perpustakaan yang terlibat (yang, saya akan dengan senang hati mengatakan bahwa C # jauh lebih lengkap dan menyediakan lebih banyak alat yang cocok untuk tugas tersebut). Tunjukkan program yang memanipulasi blok memori yang besar sebagai perbandingan, seperti kode matriks / vektor skala besar. Itu akan menyelesaikan masalah ini dengan cukup cepat bahkan jika, seperti dalam kasus ini, pembuat kode tidak tahu apa ...
stinky472
26

Kompilasi untuk pengoptimalan CPU tertentu biasanya dinilai terlalu tinggi. Ambil saja program di C ++ dan kompilasi dengan optimasi untuk pentium PRO dan jalankan pada pentium 4. Kemudian kompilasi ulang dengan optimalkan untuk pentium 4. Saya melewati sore yang panjang melakukannya dengan beberapa program. Hasil umum ?? Biasanya peningkatan kinerja kurang dari 2-3%. Jadi keunggulan JIT teoritis hampir tidak ada. Sebagian besar perbedaan kinerja hanya dapat diamati saat menggunakan fitur pemrosesan data skalar, sesuatu yang pada akhirnya memerlukan penyesuaian manual untuk mencapai kinerja maksimum. Pengoptimalan semacam itu lambat dan mahal untuk dilakukan sehingga terkadang tidak cocok untuk JIT.

Di dunia nyata dan aplikasi nyata, C ++ biasanya masih lebih cepat daripada java, terutama karena jejak memori yang lebih ringan yang menghasilkan kinerja cache yang lebih baik.

Tetapi untuk menggunakan semua kemampuan C ++ Anda, pengembang harus bekerja keras. Anda dapat mencapai hasil yang lebih unggul, tetapi Anda harus menggunakan otak Anda untuk itu. C ++ adalah bahasa yang memutuskan untuk memberi Anda lebih banyak alat, dengan harga yang harus Anda pelajari agar dapat menggunakan bahasa dengan baik.

Pria tua
sumber
4
Ini tidak terlalu banyak yang Anda kompilasi untuk pengoptimalan CPU, tetapi Anda mengompilasi untuk pengoptimalan jalur waktu proses. Jika Anda menemukan bahwa suatu metode sangat sering dipanggil dengan parameter tertentu, Anda dapat melakukan pra-kompilasi rutinitas tersebut dengan parameter tersebut sebagai konstanta yang dapat (dalam kasus boolean yang mengontrol aliran) memfaktorkan potongan pekerjaan raksasa. C ++ tidak bisa mendekati melakukan pengoptimalan semacam itu.
Bill K
1
Jadi, bagaimana JIT melakukan kompilasi ulang rutinitas untuk memanfaatkan runpath yang diamati, dan seberapa besar perbedaannya?
David Thornley
2
@Bill Saya mungkin mencampur dua hal ... tetapi bukankah prediksi cabang yang dilakukan pada waktu proses di pipeline instruksi mencapai tujuan yang sama terlepas dari bahasa?
Hardy
@Hardy ya, CPU dapat melakukan prediksi cabang apa pun bahasanya, tetapi CPU tidak dapat memfaktorkan seluruh loop dengan mengamati bahwa loop tidak berpengaruh pada apa pun. Ini juga tidak akan mengamati bahwa mult (0) terprogram untuk mengembalikan 0 dan hanya mengganti seluruh pemanggilan metode dengan if (param == 0) result = 0; dan hindari seluruh pemanggilan fungsi / metode. C dapat melakukan hal-hal ini jika kompiler memiliki gambaran umum yang komprehensif tentang apa yang terjadi, tetapi umumnya tidak memiliki cukup info pada waktu kompilasi.
Bill K
21

JIT (Just In Time Compiling) bisa sangat cepat karena dioptimalkan untuk platform target.

Ini berarti ia dapat memanfaatkan trik kompiler apa pun yang dapat didukung oleh CPU Anda, terlepas dari CPU apa yang pengembang tuliskan kode tersebut.

Konsep dasar dari .NET JIT bekerja seperti ini (sangat disederhanakan):

Memanggil metode untuk pertama kali:

  • Kode program Anda memanggil metode Foo ()
  • CLR melihat tipe yang mengimplementasikan Foo () dan mendapatkan metadata yang terkait dengannya
  • Dari metadata, CLR mengetahui alamat memori tempat penyimpanan IL (Intermediate byte code).
  • CLR mengalokasikan satu blok memori, dan memanggil JIT.
  • JIT mengkompilasi IL ke dalam kode asli, menempatkannya ke dalam memori yang dialokasikan, dan kemudian mengubah penunjuk fungsi di metadata jenis Foo () untuk menunjuk ke kode asli ini.
  • Kode asli dijalankan.

Memanggil metode untuk kedua kalinya:

  • Kode program Anda memanggil metode Foo ()
  • CLR melihat tipe yang mengimplementasikan Foo () dan menemukan penunjuk fungsi dalam metadata.
  • Kode asli di lokasi memori ini dijalankan.

Seperti yang Anda lihat, untuk kedua kalinya, prosesnya hampir sama dengan C ++, kecuali dengan keuntungan dari pengoptimalan waktu nyata.

Meskipun demikian, masih ada masalah overhead lain yang memperlambat bahasa terkelola, tetapi JIT sangat membantu.

FlySwat
sumber
Ngomong-ngomong, Jonathan, menurutku seseorang masih meremehkan barang-barangmu. Ketika saya memilih Anda, Anda memiliki -1 pada posting ini.
Brian R. Bondy
12

Saya suka jawaban Orion Adrian , tapi ada aspek lain darinya.

Pertanyaan yang sama diajukan puluhan tahun lalu tentang bahasa assembly vs. bahasa "manusia" seperti FORTRAN. Dan sebagian dari jawabannya serupa.

Ya, program C ++ mampu menjadi lebih cepat daripada C # pada algoritme apa pun (non-trivial?), Tetapi program dalam C # sering kali secepat atau lebih cepat daripada implementasi "naif" di C ++, dan versi yang dioptimalkan dalam C ++ akan memakan waktu lebih lama untuk dikembangkan, dan mungkin masih mengalahkan versi C # dengan selisih yang sangat kecil. Jadi, apakah itu sangat berharga?

Anda harus menjawab pertanyaan itu satu per satu.

Meskipun demikian, saya sudah lama menjadi penggemar C ++, dan menurut saya ini adalah bahasa yang sangat ekspresif dan kuat - terkadang kurang dihargai. Tetapi dalam banyak masalah "kehidupan nyata" (bagi saya pribadi, itu berarti "jenis yang harus saya selesaikan"), C # akan menyelesaikan pekerjaan lebih cepat dan lebih aman.

Hukuman terbesar yang Anda bayar? Banyak program .NET dan Java adalah babi memori. Saya telah melihat aplikasi .NET dan Java mengambil "ratusan" megabyte memori, ketika program C ++ dengan kompleksitas yang sama hampir tidak menggores "puluhan" MB.

Euro Micelli
sumber
7

Saya tidak yakin seberapa sering Anda akan menemukan bahwa kode Java akan berjalan lebih cepat daripada C ++, bahkan dengan Hotspot, tetapi saya akan menjelaskan bagaimana hal itu bisa terjadi.

Pikirkan kode Java yang dikompilasi sebagai bahasa mesin yang ditafsirkan untuk JVM. Ketika prosesor Hotspot mengetahui bahwa bagian tertentu dari kode yang dikompilasi akan digunakan berkali-kali, ia melakukan pengoptimalan pada kode mesin. Karena Hand-tuning Assembly hampir selalu lebih cepat daripada kode yang dikompilasi C ++, tidak apa-apa untuk mengetahui bahwa kode mesin yang disetel secara terprogram tidak akan terlalu buruk.

Jadi, untuk kode yang sangat berulang, saya bisa melihat di mana memungkinkan Hotspot JVM untuk menjalankan Java lebih cepat dari C ++ ... sampai pengumpulan sampah mulai bekerja. :)

billjamesdev
sumber
Bisakah Anda memperluas pernyataan tersebut Since hand-tuning Assembly is almost always faster than C++ compiled code? Apa yang Anda maksud dengan "Hand-tuning Assembly" dan "C ++ compiled code"?
paercebal
Ini didasarkan pada gagasan bahwa pengoptimal kompiler mengikuti aturan, dan pembuat kode tidak. Jadi akan selalu ada kode yang menurut pengoptimal tidak dapat dioptimalkan dengan sempurna, sedangkan manusia bisa, baik dengan melihat gambaran yang lebih besar atau mengetahui lebih banyak tentang apa yang sebenarnya dilakukan kode tersebut. Saya akan menambahkan bahwa ini adalah komentar berusia 3 tahun, dan saya tahu lebih banyak tentang HotSpot daripada dulu, dan saya dapat dengan mudah melihat pengoptimalan dinamis sebagai cara yang SANGAT bagus untuk menjalankan kode lebih cepat.
billjamesdev
1. Optimasi dari Hotspot atau JIT lainnya masih merupakan optimasi compiler. JIT memiliki keunggulan dibandingkan kompilator statis karena dapat menyebariskan beberapa hasil (kode yang sering disebut), atau bahkan membuat pengoptimalan berdasarkan prosesor yang menjalankan, tetapi ini masih merupakan pengoptimalan kompilator. . . 2. Saya rasa Anda sedang berbicara tentang optimasi algoritma, bukan "assembly fine tuning". "fine tuning perakitan manual oleh pembuat kode manusia" gagal menghasilkan hasil yang lebih baik daripada pengoptimalan kompiler sejak lebih dari satu dekade. Faktanya, manusia yang bermain-main dengan perakitan biasanya mengacaukan optimasi apa pun ...
paercebal
Oke, saya mengerti bahwa saya menggunakan terminologi yang salah, "pengoptimalan kompiler" daripada "pengoptimalan statis". Saya ingin menunjukkan bahwa, setidaknya di industri game, baru-baru ini untuk PS2 kami masih menggunakan perakitan kode tangan di beberapa tempat untuk "mengoptimalkan" chip tertentu yang kami tahu ada di konsol; kompiler silang untuk chip baru ini belum secanggih yang ada untuk arsitektur x86. Kembali ke pertanyaan awal di atas: JIT memiliki manfaat untuk dapat mengukur sebelum mengoptimalkan, yang merupakan Good Thing (TM)
billjamesdev
Perhatikan bahwa sebagian besar GC produksi juga menggunakan assembler yang ditulis tangan karena C / C ++ tidak memotongnya.
JD
6

Umumnya, program Anda algoritme akan jauh lebih penting untuk kecepatan aplikasi Anda daripada bahasanya . Anda dapat menerapkan algoritme yang buruk dalam bahasa apa pun, termasuk C ++. Dengan mengingat hal itu, biasanya Anda akan dapat menulis kode yang dijalankan lebih cepat dalam bahasa yang membantu Anda menerapkan algoritme yang lebih efisien.

Bahasa tingkat yang lebih tinggi melakukannya dengan sangat baik dalam hal ini dengan menyediakan akses yang lebih mudah ke banyak struktur data yang dibuat sebelumnya yang efisien dan mendorong praktik yang akan membantu Anda menghindari kode yang tidak efisien. Tentu saja, terkadang mereka juga dapat membuatnya mudah untuk menulis banyak kode yang sangat lambat, jadi Anda masih harus tahu platform Anda.

Juga, C ++ mengejar dengan fitur "baru" (perhatikan tanda kutip) seperti kontainer STL, penunjuk otomatis, dll - lihat pustaka peningkatan, misalnya. Dan terkadang Anda mungkin menemukan bahwa cara tercepat untuk menyelesaikan beberapa tugas memerlukan teknik seperti aritmatika penunjuk yang dilarang dalam bahasa tingkat tinggi - meskipun secara tipikal memungkinkan Anda memanggil pustaka yang ditulis dalam bahasa yang dapat menerapkannya sesuai keinginan. .

Hal utama adalah mengetahui bahasa yang Anda gunakan, itu terkait API, apa yang bisa dilakukannya, dan apa batasannya.

Joel Coehoorn
sumber
5

Saya juga tidak tahu ... program Java saya selalu lambat. :-) Saya tidak pernah benar-benar memperhatikan program C # menjadi sangat lambat.

Paul Nathan
sumber
4

Berikut adalah patokan menarik lainnya, yang dapat Anda coba sendiri di komputer Anda sendiri.

Ini membandingkan ASM, VC ++, C #, Silverlight, applet Java, Javascript, Flash (AS3)

Demo kecepatan plugin Roozz

Harap dicatat bahwa kecepatan javascript bervariasi tergantung pada browser apa yang menjalankannya. Hal yang sama juga berlaku untuk Flash dan Silverlight karena plugin ini berjalan dalam proses yang sama seperti browser hosting. Tetapi plugin Roozz menjalankan file .exe standar, yang berjalan dalam prosesnya sendiri, sehingga kecepatannya tidak dipengaruhi oleh browser hosting.

Thomas
sumber
4

Anda harus mendefinisikan "kinerja lebih baik dari ..". Yah, saya tahu, Anda bertanya tentang kecepatan, tapi itu bukan segalanya yang penting.

  • Apakah mesin virtual melakukan lebih banyak overhead waktu proses? Iya!
  • Apakah mereka makan lebih banyak memori kerja? Iya!
  • Apakah mereka memiliki biaya awal yang lebih tinggi (inisialisasi runtime dan kompiler JIT)? Iya!
  • Apakah mereka membutuhkan perpustakaan besar yang terpasang? Iya!

Dan seterusnya, biasnya, ya;)

Dengan C # dan Java Anda membayar harga untuk apa yang Anda dapatkan (pengkodean lebih cepat, manajemen memori otomatis, perpustakaan besar dan sebagainya). Tapi Anda tidak punya banyak ruang untuk tawar-menawar tentang detailnya: ambil paket lengkap atau tidak sama sekali.

Bahkan jika bahasa-bahasa tersebut dapat mengoptimalkan beberapa kode untuk dieksekusi lebih cepat daripada kode yang dikompilasi, keseluruhan pendekatan (IMHO) tidak efisien. Bayangkan mengemudi setiap hari sejauh 5 mil ke tempat kerja Anda, dengan sebuah truk! Nyaman, enak rasanya, Anda aman (zona crumple ekstrim) dan setelah Anda tancap gas beberapa lama, bahkan akan secepat mobil standar! Mengapa kita tidak punya truk untuk dikendarai ke tempat kerja? ;)

Di C ++ Anda mendapatkan apa yang Anda bayar, tidak lebih, tidak lebih sedikit.

Mengutip Bjarne Stroustrup: "C ++ adalah bahasa pengumpulan sampah favorit saya karena menghasilkan sangat sedikit sampah" teks tautan

Frunsi
sumber
Yah, saya pikir dia punya ide bagus tentang kekurangannya, dia juga berkata: "C membuatnya mudah untuk menembak diri sendiri di kaki; C ++ membuatnya lebih sulit, tetapi ketika Anda melakukannya menghancurkan seluruh kaki Anda";)
Frunsi
"Apakah mereka memerlukan perpustakaan besar terpasang" Java mengatasi masalah ini dengan jigsaw proyek yang saya percaya.
toc777
"Dalam C ++ Anda mendapatkan apa yang Anda bayar, tidak lebih, tidak lebih sedikit". Contoh penghitung: Saya membandingkan implementasi pohon RB di OCaml dan C ++ (GNU GCC) yang menggunakan pengecualian untuk lompat jauh dari rekursi jika elemen yang ditambahkan sudah ada untuk menggunakan kembali set yang ada. OCaml naik 6x lebih cepat daripada C ++ karena tidak membayar untuk memeriksa destruktor karena tumpukan dibatalkan.
JD
3
@ Jon: tetapi pada suatu waktu (nanti?) Ia harus menghancurkan objek-objeknya (setidaknya ia harus melepaskan memorinya). Dan juga perhatikan, bahwa pengecualian untuk kasus luar biasa, setidaknya di C ++ aturan itu harus dipatuhi. Pengecualian C ++ mungkin berat ketika pengecualian terjadi, yang merupakan trade-off.
Frunsi
@ Jon: mungkin coba ulangi patokan Anda dengan timesdi shell. Sehingga ia memeriksa seluruh program, bukan hanya satu aspek. Apakah hasilnya serupa?
Frunsi
3

Kode yang dapat dieksekusi yang dihasilkan dari kompilator Java atau C # tidak diinterpretasikan - ia dikompilasi ke kode asli "just in time" (JIT). Jadi, kode pertama kali dalam program Java / C # ditemukan selama eksekusi, ada beberapa overhead saat "kompilator runtime" (alias kompiler JIT) mengubah kode byte (Java) atau kode IL (C #) menjadi instruksi mesin asli. Namun, saat kode tersebut ditemukan saat aplikasi masih berjalan, kode asli segera dijalankan. Ini menjelaskan bagaimana beberapa program Java / C # tampak lambat pada awalnya, tetapi kemudian berkinerja lebih baik semakin lama program tersebut dijalankan. Contoh yang bagus adalah situs web ASP.Net. Pertama kali situs web diakses, mungkin akan sedikit lebih lambat karena kode C # dikompilasi ke kode asli oleh kompiler JIT.

Peter Meyer
sumber
3

Beberapa jawaban bagus di sini tentang pertanyaan spesifik yang Anda ajukan. Saya ingin mundur dan melihat gambaran yang lebih besar.

Ingatlah bahwa persepsi pengguna Anda tentang kecepatan perangkat lunak yang Anda tulis dipengaruhi oleh banyak faktor lain selain dari seberapa baik codegen mengoptimalkan. Berikut beberapa contohnya:

  • Manajemen memori manual sulit dilakukan dengan benar (tidak ada kebocoran), dan bahkan lebih sulit dilakukan dengan efisien (kosongkan memori segera setelah Anda selesai melakukannya). Menggunakan GC, secara umum, lebih mungkin menghasilkan program yang mengelola memori dengan baik. Apakah Anda bersedia bekerja sangat keras, dan menunda pengiriman perangkat lunak Anda, dalam upaya untuk mengalahkan GC?

  • C # saya lebih mudah dibaca & dipahami daripada C ++ saya. Saya juga memiliki lebih banyak cara untuk meyakinkan diri sendiri bahwa kode C # saya berfungsi dengan benar. Itu berarti saya dapat mengoptimalkan algoritme saya dengan risiko yang lebih kecil untuk menimbulkan bug (dan pengguna tidak menyukai perangkat lunak yang mogok, meskipun itu terjadi dengan cepat!)

  • Saya dapat membuat perangkat lunak saya lebih cepat di C # daripada di C ++. Itu membebaskan waktu untuk mengerjakan kinerja, dan tetap mengirimkan perangkat lunak saya tepat waktu.

  • Lebih mudah untuk menulis UI yang bagus di C # daripada C ++, jadi saya lebih mungkin untuk mendorong pekerjaan ke latar belakang sementara UI tetap responsif, atau untuk memberikan UI kemajuan atau dengar ketika program harus memblokir untuk sementara waktu. Ini tidak membuat apa pun lebih cepat, tetapi membuat pengguna lebih senang menunggu.

Semua yang saya katakan tentang C # mungkin benar untuk Java, saya hanya tidak memiliki pengalaman untuk mengatakan dengan pasti.

Jay Bazuzi
sumber
3

Jika Anda seorang programmer Java / C # yang mempelajari C ++, Anda akan tergoda untuk terus memikirkan istilah Java / C # dan menerjemahkan kata demi kata ke sintaks C ++. Dalam hal ini, Anda hanya mendapatkan manfaat yang disebutkan sebelumnya dari kode asli vs. ditafsirkan / JIT. Untuk mendapatkan peningkatan kinerja terbesar dalam C ++ vs. Java / C #, Anda harus belajar berpikir dalam C ++ dan merancang kode secara khusus untuk memanfaatkan kekuatan C ++.

Untuk memparafrasekan Edsger Dijkstra : [bahasa pertama Anda] memutilasi pikiran melampaui pemulihan.
Untuk memparafrasekan Jeff Atwood : Anda dapat menulis [bahasa pertama Anda] dalam bahasa baru apa pun.

palm3D
sumber
1
Saya menduga bahwa ungkapan "Anda dapat menulis FORTRAN dalam bahasa apa pun" mendahului karier Jeff.
David Thornley
3

Salah satu pengoptimalan JIT yang paling signifikan adalah metode inlining. Java bahkan dapat menyebariskan metode virtual jika dapat menjamin ketepatan waktu proses. Pengoptimalan semacam ini biasanya tidak dapat dilakukan oleh kompiler statis standar karena memerlukan analisis seluruh program, yang sulit karena kompilasi terpisah (sebaliknya, JIT memiliki semua program yang tersedia untuk itu). Metode penyebarisan meningkatkan pengoptimalan lainnya, memberikan blok kode yang lebih besar untuk dioptimalkan.

Alokasi memori standar di Java / C # juga lebih cepat, dan deallocation (GC) tidak jauh lebih lambat, tetapi hanya kurang deterministik.

pengguna57697
sumber
Perhatikan bahwa freedan deletejuga tidak deterministik dan GC dapat dibuat deterministik dengan tidak mengalokasikan.
JD
3

Bahasa mesin virtual tidak mungkin mengungguli bahasa yang dikompilasi tetapi mereka bisa cukup dekat sehingga tidak masalah, karena (setidaknya) alasan berikut (saya berbicara untuk Java di sini karena saya tidak pernah melakukan C #).

1 / Java Runtime Environment biasanya dapat mendeteksi potongan kode yang sering dijalankan dan melakukan kompilasi just-in-time (JIT) dari bagian tersebut sehingga, di masa mendatang, kode tersebut berjalan dengan kecepatan terkompilasi penuh.

2 / Sebagian besar pustaka Java dikompilasi sehingga, saat Anda memanggil fungsi pustaka, Anda menjalankan kode yang dikompilasi, tidak diinterpretasikan. Anda dapat melihat kode (dalam C) dengan mendownload OpenJDK.

3 / Kecuali jika Anda melakukan kalkulasi besar-besaran, sebagian besar waktu program Anda berjalan, program itu menunggu masukan dari manusia yang sangat lambat (secara relatif).

4 / Karena banyak validasi bytecode Java dilakukan pada saat memuat kelas, overhead normal pemeriksaan runtime sangat berkurang.

5 / Pada kasus terburuk, kode intensif kinerja dapat diekstraksi ke modul yang dikompilasi dan dipanggil dari Java (lihat JNI) sehingga berjalan dengan kecepatan penuh.

Singkatnya, bytecode Java tidak akan pernah mengungguli bahasa mesin asli, tetapi ada beberapa cara untuk menguranginya. Keuntungan besar dari Java (seperti yang saya lihat) adalah pustaka standar BESAR dan sifat lintas platform.

paxdiablo
sumber
1
Re item 2, "2 / Sebagian besar dari library Java dikompilasi sehingga, ketika Anda memanggil fungsi library, Anda menjalankan kode yang dikompilasi, tidak diinterpretasikan": Apakah Anda memiliki kutipan untuk itu? Jika itu benar-benar seperti yang Anda gambarkan, saya berharap untuk sering menemukan kode asli dari debugger saya, tetapi saya tidak melakukannya.
cero
Re: cero Debugger sering menggunakan jalur yang kurang efisien tetapi lebih ekspresif, dan oleh karena itu bukan penanda yang baik untuk kinerja apa pun yang terkait.
Guvante
2
Ada keuntungan kinerja besar lainnya untuk pustaka HUGH ini - kode pustaka mungkin lebih baik ditulis daripada apa yang akan ditulis sendiri oleh banyak pemrogram (dengan waktu yang terbatas, dan kurangnya pengetahuan khusus) dan di Java, karena banyak alasan, pemrogram sering menggunakan Perpustakaan.
Liran Orevi
3

Orion Adrian , izinkan saya membalikkan posting Anda untuk melihat betapa tidak berdasarnya komentar Anda, karena banyak yang dapat dikatakan tentang C ++ juga. Dan mengatakan bahwa compiler Java / C # mengoptimalkan fungsi kosong benar-benar membuat Anda terdengar seperti Anda bukan ahli saya dalam pengoptimalan, karena a) mengapa program nyata harus berisi fungsi kosong, kecuali untuk kode warisan yang sangat buruk, b) itu sebenarnya bukan optimasi hitam dan tepi berdarah.

Terlepas dari frasa itu, Anda secara terang-terangan mengoceh tentang pointer, tetapi bukankah objek di Java dan C # pada dasarnya berfungsi seperti pointer C ++? Mungkinkah mereka tidak tumpang tindih? Mungkinkah mereka tidak nol? C (dan sebagian besar implementasi C ++) memiliki kata kunci pembatasan, keduanya memiliki tipe nilai, C ++ memiliki referensi-ke-nilai dengan jaminan bukan nol. Apa yang ditawarkan Java dan C #?

>>>>>>>>>>

Secara umum, C dan C ++ bisa sama cepat atau lebih cepat karena kompiler AOT - kompiler yang mengkompilasi kode Anda sebelum penerapan, sekali dan untuk semua, pada memori tinggi Anda, banyak server build inti - dapat melakukan pengoptimalan bahwa program kompilasi C # tidak bisa karena punya banyak waktu untuk melakukannya. Kompiler dapat menentukan apakah mesin tersebut Intel atau AMD; Pentium 4, Core Solo, atau Core Duo; atau jika mendukung SSE4, dll, dan jika kompilator Anda tidak mendukung pengiriman runtime, Anda dapat menyelesaikannya sendiri dengan menerapkan beberapa biner khusus.

Program AC # biasanya dikompilasi setelah menjalankannya sehingga berjalan dengan baik di semua mesin, tetapi tidak dioptimalkan sebanyak mungkin untuk satu konfigurasi (yaitu prosesor, set instruksi, perangkat keras lain), dan itu harus menghabiskan waktu pertama. Fitur-fitur seperti fisi loop, inversi loop, vektorisasi otomatis, pengoptimalan seluruh program, perluasan template, IPO, dan banyak lagi, sangat sulit untuk diselesaikan semuanya dan sepenuhnya dengan cara yang tidak mengganggu pengguna akhir.

Selain itu, fitur bahasa tertentu memungkinkan compiler dalam C ++ atau C membuat asumsi tentang kode Anda yang memungkinkannya untuk mengoptimalkan bagian tertentu yang tidak aman untuk dilakukan oleh compiler Java / C #. Ketika Anda tidak memiliki akses ke id tipe lengkap dari generik atau aliran program terjamin, ada banyak pengoptimalan yang tidak aman.

Juga C ++ dan C melakukan banyak alokasi tumpukan sekaligus dengan hanya satu penambahan register, yang tentunya lebih efisien daripada alokasi Javas dan C # seperti untuk lapisan abstraksi antara pengumpul sampah dan kode Anda.

Sekarang saya tidak dapat berbicara untuk Java pada poin berikutnya ini, tetapi saya tahu bahwa compiler C ++ misalnya akan benar-benar menghapus metode dan panggilan metode ketika mengetahui tubuh metode kosong, itu akan menghilangkan subekspresi umum, mungkin mencoba dan mencoba lagi untuk menemukan penggunaan register yang optimal, itu tidak memaksakan pemeriksaan batas, itu akan mengotovektorisasi loop dan loop dalam dan akan membalikkan dalam ke luar, itu memindahkan kondisional keluar dari loop, itu membagi dan membatalkan loop. Ini akan memperluas std :: vector menjadi native zero overhead arrays seperti yang Anda lakukan dengan cara C. Ini akan melakukan optimasi antar prosedural. Ini akan membangun nilai kembali secara langsung di situs pemanggil. Ini akan melipat dan menyebarkan ekspresi. Ini akan menyusun ulang data menjadi cara yang ramah cache. Ini akan melakukan jump threading. Ini memungkinkan Anda menulis pelacak sinar waktu kompilasi dengan overhead waktu proses nol. Ini akan membuat pengoptimalan berbasis grafik yang sangat mahal. Ini akan melakukan pengurangan kekuatan, jika itu menggantikan kode tertentu dengan kode yang secara sintaksis sama sekali tidak sama tetapi secara semantik setara ("xor foo, foo" yang lama hanyalah yang paling sederhana, meskipun pengoptimalan yang sudah ketinggalan zaman dari jenis seperti itu). Jika Anda memintanya dengan ramah, Anda dapat menghilangkan standar titik mengambang IEEE dan mengaktifkan lebih banyak lagi pengoptimalan seperti pemesanan ulang operan titik mengambang. Setelah itu memijat dan membantai kode Anda, itu mungkin mengulangi seluruh proses, karena seringkali, pengoptimalan tertentu meletakkan dasar untuk pengoptimalan yang lebih pasti. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. apakah itu menggantikan kode-kode tertentu dengan kode yang secara sintaksis sama sekali tidak sama tetapi secara semantik setara ("xor foo, foo" yang lama hanyalah pengoptimalan yang paling sederhana, meskipun ketinggalan jaman). Jika Anda memintanya dengan ramah, Anda dapat menghilangkan standar titik mengambang IEEE dan mengaktifkan lebih banyak lagi pengoptimalan seperti pemesanan ulang operan titik mengambang. Setelah itu memijat dan membantai kode Anda, itu mungkin mengulangi seluruh proses, karena seringkali, pengoptimalan tertentu meletakkan dasar untuk pengoptimalan yang lebih pasti. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. apakah itu menggantikan kode-kode tertentu dengan kode yang secara sintaksis sama sekali tidak sama tetapi secara semantik setara ("xor foo, foo" yang lama hanyalah pengoptimalan yang paling sederhana, meskipun ketinggalan jaman). Jika Anda memintanya dengan ramah, Anda dapat menghilangkan standar titik mengambang IEEE dan mengaktifkan lebih banyak lagi pengoptimalan seperti pemesanan ulang operan titik mengambang. Setelah itu memijat dan membantai kode Anda, itu mungkin mengulangi seluruh proses, karena seringkali, pengoptimalan tertentu meletakkan dasar untuk pengoptimalan yang lebih pasti. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. Jika Anda memintanya dengan ramah, Anda dapat menghilangkan standar titik mengambang IEEE dan mengaktifkan lebih banyak lagi pengoptimalan seperti pemesanan ulang operan titik mengambang. Setelah itu memijat dan membantai kode Anda, itu mungkin mengulangi seluruh proses, karena seringkali, pengoptimalan tertentu meletakkan dasar untuk pengoptimalan yang lebih pasti. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. Jika Anda memintanya dengan ramah, Anda dapat menghilangkan standar titik mengambang IEEE dan mengaktifkan lebih banyak lagi pengoptimalan seperti pemesanan ulang operan titik mengambang. Setelah itu memijat dan membantai kode Anda, itu mungkin mengulangi seluruh proses, karena seringkali, pengoptimalan tertentu meletakkan dasar untuk pengoptimalan yang lebih pasti. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda. Mungkin juga mencoba lagi dengan parameter yang diacak dan melihat bagaimana skor varian lain dalam peringkat internalnya. Dan itu akan menggunakan logika semacam ini di seluruh kode Anda.

Jadi seperti yang Anda lihat, ada banyak alasan mengapa implementasi C ++ atau C tertentu akan lebih cepat.

Sekarang ini semua dikatakan, banyak pengoptimalan dapat dilakukan di C ++ yang akan menghilangkan semua yang dapat Anda lakukan dengan C #, terutama di ranah pengolah angka, waktu nyata dan dekat-ke-logam, tetapi tidak secara eksklusif di sana. Anda bahkan tidak perlu menyentuh satu pun penunjuk untuk melangkah jauh.

Jadi, tergantung pada apa yang Anda tulis, saya akan memilih salah satunya. Tetapi jika Anda menulis sesuatu yang tidak bergantung pada perangkat keras (driver, permainan video, dll), saya tidak akan khawatir tentang kinerja C # (sekali lagi tidak dapat berbicara tentang Java). Ini akan baik-baik saja.

<<<<<<<<<<

Secara umum, argumen umum tertentu mungkin terdengar keren di pos tertentu, tetapi umumnya tidak terdengar kredibel.

Bagaimanapun, untuk berdamai: AOT itu bagus, begitu pula JIT . Satu-satunya jawaban yang benar adalah: Tergantung. Dan orang pintar sejati tahu bahwa Anda bisa menggunakan yang terbaik dari kedua dunia itu.

Sebastian Mach
sumber
2

Ini hanya akan terjadi jika interpreter Java menghasilkan kode mesin yang sebenarnya lebih baik dioptimalkan daripada kode mesin yang dihasilkan compiler Anda untuk kode C ++ yang Anda tulis, sampai pada titik di mana kode C ++ lebih lambat daripada Java dan biaya interpretasinya.

Namun, kemungkinan hal itu benar-benar terjadi cukup rendah - kecuali jika Java memiliki pustaka yang ditulis dengan sangat baik, dan Anda memiliki pustaka C ++ yang ditulis dengan buruk.

ine
sumber
Saya juga percaya bahwa ada bobot bahasa tertentu juga, ketika bekerja di tingkat yang lebih rendah, dengan sedikit abstraksi, Anda akan mengembangkan program yang lebih cepat. Ini tidak berhubungan dengan poin-poin tentang eksekusi bytecode itu sendiri.
Brian R. Bondy
2

Sebenarnya, C # tidak benar-benar berjalan di mesin virtual seperti Java. IL dikompilasi ke dalam bahasa assembly, yang seluruhnya merupakan kode asli dan berjalan dengan kecepatan yang sama dengan kode asli. Anda dapat melakukan pra-JIT aplikasi .NET yang sepenuhnya menghilangkan biaya JIT dan kemudian Anda menjalankan kode asli sepenuhnya.

Perlambatan dengan .NET akan datang bukan karena kode .NET lebih lambat, tetapi karena ia melakukan lebih banyak hal di belakang layar untuk melakukan hal-hal seperti mengumpulkan sampah, memeriksa referensi, menyimpan bingkai tumpukan lengkap, dll. Ini bisa sangat berguna dan membantu saat membangun aplikasi, tetapi juga membutuhkan biaya. Perhatikan bahwa Anda dapat melakukan semua hal ini dalam program C ++ juga (sebagian besar fungsionalitas inti .NET sebenarnya adalah kode .NET yang dapat Anda lihat di ROTOR). Namun, jika Anda menulis fungsionalitas yang sama, Anda mungkin akan berakhir dengan program yang jauh lebih lambat karena runtime .NET telah dioptimalkan dan disetel dengan baik.

Karena itu, salah satu kekuatan kode yang dikelola adalah dapat sepenuhnya diverifikasi, yaitu. Anda dapat memverifikasi bahwa kode tidak akan pernah mengakses memori proses lain atau melakukan hal-hal yang tidak berguna sebelum Anda menjalankannya. Microsoft memiliki prototipe penelitian dari sistem operasi yang dikelola sepenuhnya yang secara mengejutkan telah menunjukkan bahwa lingkungan yang dikelola 100% sebenarnya dapat bekerja secara signifikan lebih cepat daripada sistem operasi modern mana pun dengan memanfaatkan verifikasi ini untuk mematikan fitur keamanan yang tidak lagi diperlukan oleh program yang dikelola. (kita berbicara seperti 10x dalam beberapa kasus). Radio SE memiliki episode hebat membicarakan proyek ini.

jezell
sumber
1

Dalam beberapa kasus, kode yang dikelola sebenarnya bisa lebih cepat daripada kode asli. Misalnya, algoritme pengumpulan sampah "mark-and-sweep" memungkinkan lingkungan seperti JRE atau CLR untuk membebaskan sejumlah besar objek berumur pendek (biasanya) dalam satu langkah, di mana sebagian besar objek heap C / C ++ dibebaskan satu-at- sebuah waktu.

Dari wikipedia :

Untuk banyak tujuan praktis, algoritme intensif alokasi / dealokasi yang diimplementasikan dalam bahasa yang dikumpulkan sampah sebenarnya bisa lebih cepat daripada yang setara dengan menggunakan alokasi heap manual. Alasan utama untuk ini adalah bahwa pengumpul sampah memungkinkan sistem runtime untuk mengamortisasi alokasi dan operasi deallocation dengan cara yang berpotensi menguntungkan.

Meskipun demikian, saya telah menulis banyak C # dan banyak C ++, dan saya telah menjalankan banyak benchmark. Dalam pengalaman saya, C ++ jauh lebih cepat daripada C #, dalam dua cara: (1) jika Anda mengambil beberapa kode yang telah Anda tulis di C #, masukkan ke C ++ kode asli cenderung lebih cepat. Seberapa cepat? Yah, ini sangat bervariasi, tetapi tidak jarang melihat peningkatan kecepatan 100%. (2) Dalam beberapa kasus, pengumpulan sampah dapat memperlambat aplikasi yang dikelola secara besar - besaran . .NET CLR melakukan pekerjaan yang buruk dengan tumpukan besar (katakanlah,> 2GB), dan dapat menghabiskan banyak waktu di GC - bahkan dalam aplikasi yang memiliki sedikit - atau bahkan tidak ada - objek dari rentang hidup menengah.

Tentu saja, dalam kebanyakan kasus yang saya temui, bahasa terkelola cukup cepat, dengan tembakan panjang, dan pengorbanan pemeliharaan dan pengkodean untuk kinerja ekstra C ++ sama sekali tidak bagus.

cero
sumber
1
Masalahnya adalah bahwa untuk proses yang berjalan lama, seperti server web, memori Anda dari waktu ke waktu akan menjadi sangat terfragmentasi (dalam program tertulis C ++) sehingga Anda harus menerapkan sesuatu yang menyerupai pengumpulan sampah (atau sering restart, lihat IIS ).
Tony BenBrahim
3
Saya belum mengamati itu pada program Unix besar yang dimaksudkan untuk berjalan selamanya. Mereka cenderung ditulis dalam C, yang bahkan lebih buruk untuk manajemen memori daripada C ++.
David Thornley
Tentu saja, pertanyaannya adalah apakah kita membandingkan implementasi program dalam kode terkelola vs. tidak terkelola, atau kinerja teoretis bahasa tersebut. Jelas, kode unmanaged selalu dapat setidaknya secepat dikelola, seperti dalam kasus terburuk Anda hanya bisa menulis program unmanaged yang melakukan hal yang persis sama dengan kode dikelola! Tetapi sebagian besar masalah kinerja bersifat algoritmik, bukan mikro. Selain itu, Anda tidak mengoptimalkan kode yang dikelola dan tidak dikelola dengan cara yang sama, jadi "C ++ di C #" biasanya tidak akan berfungsi dengan baik.
kyoryu
2
Dalam C / C ++ Anda dapat mengalokasikan objek berumur pendek di tumpukan, dan Anda melakukannya jika sesuai. Dalam kode terkelola Anda tidak bisa , Anda tidak punya pilihan. Selain itu, di C / C ++ Anda dapat mengalokasikan daftar objek di area bersebelahan (Foo baru [100]), dalam kode terkelola Anda tidak bisa. Jadi, perbandingan Anda tidak valid. Nah, kekuatan pilihan ini membebani para pengembang, tetapi dengan cara ini mereka belajar untuk mengetahui dunia tempat mereka tinggal (memori ......).
Frunsi
@frunsi: "di C / C ++ Anda dapat mengalokasikan daftar objek di area bersebelahan (Foo baru [100]), dalam kode terkelola Anda tidak bisa". Itu tidak benar. Tipe nilai lokal dialokasikan stack dan Anda bahkan dapat mengalokasikan stack arraynya di C #. Bahkan ada sistem produksi yang ditulis dalam C # yang sama sekali tidak memiliki alokasi dalam kondisi mapan.
JD
1

Sebenarnya Sun's HotSpot JVM menggunakan eksekusi "mode campuran". Ini menafsirkan bytecode metode sampai ia menentukan (biasanya melalui penghitung semacam) bahwa blok kode tertentu (metode, loop, blok try-catch, dll.) Akan banyak dieksekusi, kemudian JIT mengkompilasinya. Waktu yang dibutuhkan untuk JIT mengkompilasi metode seringkali memakan waktu lebih lama daripada jika metode itu akan ditafsirkan jika itu adalah metode yang jarang dijalankan. Performa biasanya lebih tinggi untuk "mode campuran" karena JVM tidak membuang waktu JITing kode yang jarang, jika pernah, dijalankan. C # dan .NET jangan lakukan ini. .NET JITs segala sesuatu yang, sering kali, membuang-buang waktu.

mcjabberz.dll
sumber
1

Bacalah tentang HP Labs ' Dynamo , penerjemah untuk PA-8000 yang berjalan pada PA-8000, dan sering kali menjalankan program lebih cepat daripada aslinya. Maka itu tidak akan mengejutkan sama sekali!

Jangan menganggapnya sebagai "langkah perantara" - menjalankan program sudah melibatkan banyak langkah lain, dalam bahasa apa pun.

Itu sering kali bermuara pada:

  • program memiliki titik panas, jadi meskipun Anda lebih lambat menjalankan 95% dari badan kode yang harus Anda jalankan, Anda masih dapat bersaing dengan kinerja jika Anda lebih cepat di 5% panas

  • HLL tahu lebih banyak tentang maksud Anda daripada LLL seperti C / C ++, sehingga dapat menghasilkan kode yang lebih dioptimalkan (OCaml memiliki lebih banyak, dan dalam praktiknya seringkali lebih cepat)

  • kompilator JIT memiliki banyak informasi yang tidak dimiliki oleh kompilator statis (seperti, data aktual yang kebetulan Anda miliki saat ini)

  • kompiler JIT dapat melakukan pengoptimalan pada waktu proses yang tidak diizinkan oleh linker tradisional (seperti menyusun ulang cabang sehingga kasus umumnya datar, atau panggilan perpustakaan sebaris)

Secara keseluruhan, C / C ++ adalah bahasa yang cukup buruk untuk performa: hanya ada sedikit informasi tentang tipe data Anda, tidak ada informasi tentang data Anda, dan tidak ada runtime dinamis yang memungkinkan banyak hal dalam pengoptimalan waktu proses.

Ken
sumber
1

Anda mungkin mendapatkan semburan singkat saat Java atau CLR lebih cepat daripada C ++, tetapi secara keseluruhan kinerjanya lebih buruk selama masa pakai aplikasi: lihat www.codeproject.com/KB/dotnet/RuntimePerformance.aspx untuk beberapa hasil untuk itu.

dmihailescu
sumber
1

Pemahaman saya adalah bahwa C / C ++ menghasilkan kode native untuk dijalankan pada arsitektur mesin tertentu. Sebaliknya, bahasa seperti Java dan C # berjalan di atas mesin virtual yang mengabstraksi arsitektur asli. Logikanya, tampaknya tidak mungkin bagi Java atau C # untuk menyamai kecepatan C ++ karena langkah perantara ini, namun saya telah diberitahu bahwa kompiler terbaru ("hot spot") dapat mencapai kecepatan ini atau bahkan melampauinya.

Itu tidak masuk akal. Penggunaan representasi perantara tidak secara inheren menurunkan kinerja. Misalnya, llvm-gcc mengkompilasi C dan C ++ melalui LLVM IR (yang merupakan mesin register tak terbatas virtual) ke kode asli dan mencapai kinerja yang sangat baik (sering mengalahkan GCC).

Mungkin ini lebih merupakan pertanyaan kompilator daripada pertanyaan bahasa, tetapi adakah yang bisa menjelaskan dalam bahasa Inggris sederhana bagaimana mungkin salah satu bahasa mesin virtual ini berkinerja lebih baik daripada bahasa asli?

Berikut beberapa contohnya:

  • Mesin virtual dengan kompilasi JIT memfasilitasi pembuatan kode waktu proses (misalnya System.Reflection.Emitpada .NET) sehingga Anda dapat mengkompilasi kode yang dihasilkan secara langsung dalam bahasa seperti C # dan F # tetapi harus menggunakan penerjemah yang relatif lambat dalam C atau C ++. Misalnya, untuk menerapkan ekspresi reguler.

  • Bagian-bagian dari mesin virtual (mis. Penghalang tulis dan pengalokasi) sering ditulis dalam assembler yang diberi kode tangan karena C dan C ++ tidak menghasilkan kode yang cukup cepat. Jika sebuah program menekankan bagian-bagian dari sistem ini maka program tersebut dapat mengungguli apa pun yang dapat ditulis dalam C atau C ++.

  • Penautan dinamis kode asli memerlukan kesesuaian dengan ABI yang dapat menghambat kinerja dan meniadakan pengoptimalan seluruh program sedangkan penautan biasanya ditangguhkan pada VM dan dapat memanfaatkan pengoptimalan seluruh program (seperti obat generik yang direifikasi .NET).

Saya juga ingin membahas beberapa masalah dengan jawaban paercebal yang sangat disukai di atas (karena seseorang terus menghapus komentar saya pada jawabannya) yang menyajikan pandangan terpolarisasi secara kontra-produktif:

Pemrosesan kode akan dilakukan pada waktu kompilasi ...

Oleh karena itu, pemrograman metaprogram hanya berfungsi jika program tersedia pada waktu kompilasi yang seringkali tidak terjadi, misalnya tidak mungkin untuk menulis pustaka ekspresi reguler yang berkinerja kompetitif di vanilla C ++ karena tidak mampu menghasilkan kode waktu proses (aspek penting dari metaprogramming).

... bermain dengan tipe dilakukan pada waktu kompilasi ... padanan di Java atau C # paling sulit untuk ditulis, dan akan selalu lebih lambat dan diselesaikan pada waktu proses bahkan ketika tipe diketahui pada waktu kompilasi.

Di C #, itu hanya benar untuk tipe referensi dan tidak benar untuk tipe nilai.

Tidak peduli pengoptimalan JIT, tidak ada yang akan berjalan secepat akses penunjuk langsung ke memori ... jika Anda memiliki data yang berdekatan dalam memori, mengaksesnya melalui penunjuk C ++ (yaitu penunjuk C ... Mari beri Caesar haknya) akan berjalan lebih cepat daripada di Java / C #.

Orang-orang telah mengamati Java mengalahkan C ++ pada tes SOR dari tolok ukur SciMark2 justru karena petunjuk menghalangi pengoptimalan terkait aliasing.

Juga perlu dicatat bahwa .NET melakukan spesialisasi jenis generik di seluruh pustaka yang ditautkan secara dinamis setelah menautkan sedangkan C ++ tidak bisa karena templat harus diselesaikan sebelum menautkan. Dan jelas keuntungan besar yang dimiliki obat generik dibandingkan template adalah pesan kesalahan yang dapat dipahami.

Jon Harrop
sumber
0

Di atas apa yang dikatakan beberapa orang lain, dari pemahaman saya. NET dan Java lebih baik dalam alokasi memori. Misalnya, mereka dapat memadatkan memori karena terfragmentasi sedangkan C ++ tidak bisa (aslinya, tetapi bisa jika Anda menggunakan pengumpul sampah yang pintar).

Giovanni Galbo
sumber
Atau jika Anda menggunakan pengalokasi C ++ dan / atau kumpulan objek yang lebih baik. Ini jauh dari keajaiban, dari sudut pandang C ++, dan itu bisa bermuara pada "alokasi heap" menjadi secepat alokasi tumpukan.
paercebal
Jika Anda selalu mengalokasikan semuanya di heap, maka .NET dan Java bahkan dapat bekerja lebih baik daripada C / C ++. Tetapi Anda tidak akan melakukan ini di C / C ++.
Frunsi
0

Untuk apa pun yang membutuhkan banyak kecepatan, JVM hanya memanggil implementasi C ++, jadi ini lebih mempertanyakan seberapa bagus libs mereka daripada seberapa bagus JVM untuk sebagian besar hal terkait OS. Pengumpulan sampah memotong memori Anda menjadi dua, tetapi menggunakan beberapa fitur STL dan Boost yang lebih bagus akan memiliki efek yang sama tetapi dengan potensi bug berkali-kali lipat.

Jika Anda hanya menggunakan pustaka C ++ dan banyak fitur tingkat tingginya dalam proyek besar dengan banyak kelas, Anda mungkin akan berakhir lebih lambat daripada menggunakan JVM. Kecuali jauh lebih rawan kesalahan.

Namun, keuntungan dari C ++ adalah memungkinkan Anda untuk mengoptimalkan diri sendiri, jika tidak, Anda akan terjebak dengan apa yang dilakukan oleh compiler / jvm. Jika Anda membuat container sendiri, menulis manajemen memori Anda sendiri yang selaras, menggunakan SIMD, dan turun ke perakitan di sana-sini, Anda dapat mempercepat setidaknya 2x-4x kali lipat dari apa yang kebanyakan compiler C ++ akan lakukan sendiri. Untuk beberapa operasi, 16x-32x. Itu menggunakan algoritme yang sama, jika Anda menggunakan algoritme yang lebih baik dan memparalelkan, peningkatan bisa dramatis, terkadang ribuan kali lebih cepat daripada metode yang umum digunakan.

Keju Charles Eli
sumber
0

Saya melihatnya dari beberapa sudut pandang yang berbeda.

  1. Dengan waktu dan sumber daya yang tidak terbatas, akankah kode yang dikelola atau tidak dikelola menjadi lebih cepat? Jelas, jawabannya adalah bahwa kode yang tidak dikelola selalu dapat setidaknya mengikat kode yang dikelola dalam aspek ini - seperti dalam kasus terburuk, Anda baru saja membuat kode keras untuk solusi kode yang dikelola.
  2. Jika Anda mengambil program dalam satu bahasa, dan langsung menerjemahkannya ke bahasa lain, seberapa buruk performanya? Mungkin banyak, untuk setiap dua bahasa. Sebagian besar bahasa memerlukan pengoptimalan yang berbeda dan memiliki gotcha yang berbeda. Kinerja mikro sering kali banyak tentang mengetahui detail ini.
  3. Mengingat waktu dan sumber daya yang terbatas, manakah dari dua bahasa yang akan menghasilkan hasil yang lebih baik? Ini adalah pertanyaan yang paling menarik, karena meskipun bahasa yang dikelola dapat menghasilkan kode yang sedikit lebih lambat (mengingat program yang ditulis secara wajar untuk bahasa itu), versi tersebut kemungkinan akan selesai lebih cepat, sehingga memungkinkan lebih banyak waktu yang dihabiskan untuk pengoptimalan.
kyoryu
sumber
0

Jawaban yang sangat singkat: Dengan anggaran tetap, Anda akan mencapai aplikasi java yang berkinerja lebih baik daripada aplikasi C ++ (pertimbangan ROI) Selain itu, platform Java memiliki profiler yang lebih baik, yang akan membantu Anda menentukan hotspot dengan lebih cepat

Lifey
sumber