Mengapa Java bisa lebih cepat daripada C ++?

80

Terkadang Java mengungguli C ++ dalam tolok ukur. Tentu saja, kadang-kadang C ++ mengungguli.

Lihat tautan berikut:

Tetapi bagaimana ini mungkin? Ini mengejutkan saya bahwa interpretasi bytecode bisa lebih cepat daripada bahasa yang dikompilasi.

Bisakah seseorang tolong jelaskan? Terima kasih!

Deets McGeets
sumber
2
Anda dapat melihat pada shootout.alioth.debian.org/u32/… untuk melihat jenis masalah yang berjalan lebih cepat di java / c ++ ... Lihat pola masalah, dan bukan masalah khusus ini ...
c0da
2
Lihat Mengapa java memiliki reputasi lambat? untuk banyak detail tentang topik ini.
Péter Török
11
Adalah melanggar hukum (Bagian 10.101.04.2c) untuk menghasilkan Java VM yang berkinerja lebih cepat daripada biner yang dapat dieksekusi yang diproduksi dengan C ++.
Mateen Ulhaq
1
@ muntoo Apa maksudmu? Bagian 10.101.04.2c tentang apa?
Highland Mark
3
@HighlandMark Anda bukan anggota lingkaran. Anda tidak perlu tahu apa yang ada di dalam lingkaran. Lingkaran itu mutlak - hukum-hukum lingkaran itu melampaui hukum alam. Anda tidak dapat menentang atau mempertanyakan lingkaran. Saya adalah lingkaran dan lingkaran adalah saya.
Mateen Ulhaq

Jawaban:

108

Pertama, sebagian besar JVM termasuk kompiler, jadi "interpretasi bytecode" sebenarnya cukup langka (setidaknya dalam kode benchmark - itu tidak cukup langka dalam kehidupan nyata, di mana kode Anda biasanya lebih dari beberapa loop sepele yang diulang sangat sering ).

Kedua, cukup banyak tolok ukur yang terlibat tampaknya cukup bias (apakah dengan niat atau tidak kompeten, saya tidak bisa mengatakannya). Sebagai contoh, bertahun-tahun yang lalu saya melihat beberapa kode sumber yang ditautkan dari salah satu tautan yang Anda posting. Itu kode seperti ini:

  init0 = (int*)calloc(max_x,sizeof(int));
  init1 = (int*)calloc(max_x,sizeof(int));
  init2 = (int*)calloc(max_x,sizeof(int));
  for (x=0; x<max_x; x++) {
    init2[x] = 0;
    init1[x] = 0;
    init0[x] = 0;
  }

Karena callocmenyediakan memori yang sudah memusatkan perhatian, menggunakan forloop ke nol lagi jelas tidak berguna. Ini diikuti (jika memori berfungsi) dengan mengisi memori dengan data lain (dan tidak ada ketergantungan pada itu yang memusatkan perhatian), jadi semua penekanan itu sama sekali tidak perlu. Mengganti kode di atas dengan yang sederhana malloc(seperti orang waras yang akan digunakan untuk memulainya) meningkatkan kecepatan versi C ++ cukup untuk mengalahkan versi Java (dengan selisih yang cukup lebar, jika memori berfungsi).

Pertimbangkan (untuk contoh lain) methcallpatokan yang digunakan dalam entri blog di tautan terakhir Anda. Terlepas dari namanya (dan bagaimana hal-hal bahkan terlihat), versi C ++ ini tidak benar - benar mengukur banyak tentang overhead panggilan metode sama sekali. Bagian dari kode yang ternyata kritis adalah di kelas Toggle:

class Toggle {
public:
    Toggle(bool start_state) : state(start_state) { }
    virtual ~Toggle() {  }
    bool value() {
        return(state);
    }
    virtual Toggle& activate() {
        state = !state;
        return(*this);
    }
    bool state;
};

Bagian penting ternyata adalah state = !state;. Pertimbangkan apa yang terjadi ketika kami mengubah kode untuk menyandikan status sebagai intalih - alih bool:

class Toggle {
    enum names{ bfalse = -1, btrue = 1};
    const static names values[2];
    int state;

public:
    Toggle(bool start_state) : state(values[start_state]) 
    { }
    virtual ~Toggle() {  }
    bool value() {  return state==btrue;    }

    virtual Toggle& activate() {
        state = -state;
        return(*this);
    }
};

Perubahan kecil ini meningkatkan kecepatan keseluruhan sekitar 5: 1 margin . Meskipun tolok ukur dimaksudkan untuk mengukur waktu pemanggilan metode, pada kenyataannya sebagian besar yang diukur adalah waktu untuk mengkonversi antara intdan bool. Saya pasti setuju bahwa ketidakefisienan yang ditunjukkan oleh dokumen asli sangat disayangkan - tetapi mengingat betapa jarang hal itu muncul dalam kode nyata, dan kemudahan untuk memperbaikinya ketika / jika muncul, saya mengalami kesulitan untuk berpikir itu sangat berarti.

Jika ada yang memutuskan untuk menjalankan kembali tolok ukur yang terlibat, saya juga harus menambahkan bahwa ada modifikasi yang hampir sama sepele untuk versi Java yang menghasilkan (atau setidaknya pada satu waktu diproduksi - saya belum menjalankan kembali tes dengan JVM baru-baru ini untuk mengkonfirmasi mereka masih melakukan) peningkatan yang cukup besar dalam versi Java juga. Versi Java memiliki NthToggle :: activate () yang terlihat seperti ini:

public Toggle activate() {
this.counter += 1;
if (this.counter >= this.count_max) {
    this.state = !this.state;
    this.counter = 0;
}
return(this);
}

Mengubah ini untuk memanggil fungsi dasar alih-alih memanipulasi this.statesecara langsung memberikan peningkatan kecepatan yang cukup besar (meskipun tidak cukup untuk mengikuti versi C ++ yang dimodifikasi).

Jadi, yang akhirnya kita dapatkan adalah asumsi yang salah tentang kode byte yang ditafsirkan vs beberapa tolok ukur terburuk (yang pernah saya lihat). Tidak ada yang memberikan hasil yang berarti.

Pengalaman saya sendiri adalah bahwa dengan programmer yang sama-sama berpengalaman memberikan perhatian yang sama untuk mengoptimalkan, C ++ akan mengalahkan Java lebih sering daripada tidak - tetapi (setidaknya di antara keduanya), bahasa jarang akan membuat perbedaan sebanyak programmer dan desain. Tolok ukur yang dikutip memberi tahu kami lebih banyak tentang kompetensi (dalam) / kejujuran penulis mereka daripada yang mereka lakukan tentang bahasa yang mereka maksud untuk dijadikan patokan.

[Sunting: Seperti yang tersirat di satu tempat di atas tetapi tidak pernah dinyatakan secara langsung seperti yang seharusnya saya miliki, hasil yang saya kutip adalah yang saya dapatkan ketika saya menguji ini ~ 5 tahun yang lalu, menggunakan implementasi C ++ dan Java yang saat ini ada pada saat itu . Saya belum menjalankan kembali tes dengan implementasi saat ini. Pandangan sekilas, menunjukkan bahwa kode belum diperbaiki, jadi semua yang akan berubah adalah kemampuan kompiler untuk menutupi masalah dalam kode.]

Jika kita mengabaikan contoh Java, bagaimanapun, adalah sebenarnya mungkin untuk kode ditafsirkan untuk berjalan lebih cepat daripada kode dikompilasi (meskipun sulit dan agak tidak biasa).

Cara biasa ini terjadi adalah bahwa kode yang ditafsirkan jauh lebih kompak daripada kode mesin, atau itu berjalan pada CPU yang memiliki cache data yang lebih besar daripada kode cache.

Dalam kasus seperti itu, juru bahasa kecil (misalnya, juru bahasa dalam implementasi Keempat) mungkin dapat masuk sepenuhnya dalam cache kode, dan program yang ditafsirkan sepenuhnya cocok dalam cache data. Cache biasanya lebih cepat dari memori utama dengan faktor setidaknya 10, dan seringkali jauh lebih (faktor 100 tidak terlalu jarang lagi).

Jadi, jika cache lebih cepat dari memori utama dengan faktor N, dan dibutuhkan lebih sedikit dari instruksi kode mesin N untuk mengimplementasikan setiap kode byte, kode byte harus menang (saya menyederhanakan, tapi saya pikir ide umum masih harus menjadi jelas).

Jerry Coffin
sumber
26
+1, ack penuh. Terutama "bahasa jarang akan membuat perbedaan sebanyak programmer dan desain" - Anda akan sering tersandung masalah di mana Anda dapat mengoptimalkan algoritma, misalnya meningkatkan big-O yang akan memberikan lebih banyak dorongan daripada kompiler terbaik yang bisa.
schnaader
1
"Seandainya ada yang memutuskan untuk menjalankan kembali tolok ukur yang terlibat ..." JANGAN! Kembali pada tahun 2005 tugas-tugas lama itu dibuang dan diganti dengan tugas-tugas yang sekarang ditampilkan dalam permainan tolok ukur. Jika ada yang ingin menjalankan kembali beberapa program maka silakan jalankan kembali program saat ini untuk tugas-tugas saat ini yang ditampilkan di halaman depan permainan benchmark shootout.alioth.debian.org
igouy
@igouy: Beberapa orang mungkin hanya ingin mengkonfirmasi / menolak hasil dari tolok ukur yang mereka jalankan, dengan minimum koreksi yang diperlukan untuk setidaknya memberi mereka sedikit hubungan dengan kenyataan. Pada saat yang sama, Anda pada dasarnya benar: tolok ukur yang dimaksud sangat buruk sehingga hanya memperbaiki kesalahan yang paling jelas tidak akan banyak membantu.
Jerry Coffin
Dan itulah sebabnya, pada tahun 2005, mereka dibuang dan digantikan oleh tugas-tugas yang sekarang ditampilkan dalam permainan benchmark. Orang-orang yang tidak tahu lebih baik menjalankan kembali program-program lama itu.
igouy
13
+1 Saya tidak suka orang-orang yang mengkode C ++ dalam gaya C atau Java dan kemudian menyatakan Java lebih unggul. disclaimer: Saya tidak menyebut bahasa superior, tetapi menulis kode C ++ jelek dalam gaya yang mungkin sangat cocok untuk bahasa lain tidak membuat kedua bahasa sebanding.
Christian Rau
112

Hand rolled C / C ++ yang dilakukan oleh seorang ahli dengan waktu tidak terbatas akan setidaknya secepat atau lebih cepat dari Java. Pada akhirnya, Java itu sendiri ditulis dalam C / C ++ sehingga Anda tentu saja dapat melakukan semua yang dilakukan Java jika Anda bersedia melakukan upaya rekayasa yang cukup.

Namun dalam praktiknya, Java sering dieksekusi sangat cepat karena alasan berikut:

  • Kompilasi JIT - meskipun kelas Java disimpan sebagai bytecode, ini (biasanya) dikompilasi ke kode asli oleh kompiler JIT saat program dimulai. Setelah dikompilasi, itu adalah kode asli asli - jadi secara teoritis dapat diharapkan untuk melakukan serta mengkompilasi C / C ++ setelah program telah berjalan cukup lama (yaitu setelah semua kompilasi JIT telah dilakukan)
  • Pengumpulan sampah di Jawa sangat cepat dan efisien - Hotspot GC mungkin merupakan penerapan GC serba terbaik di dunia. Ini adalah hasil dari upaya ahli selama bertahun-tahun oleh Sun dan perusahaan lain. Hampir semua sistem manajemen memori kompleks yang Anda gunakan C / C ++ akan lebih buruk. Tentu saja Anda dapat menulis skema manajemen memori dasar yang cukup cepat / ringan di C / C ++, tetapi skema itu tidak akan sekompleks sistem GC penuh. Karena sebagian besar sistem modern membutuhkan manajemen memori yang kompleks, Java karenanya memiliki keuntungan besar untuk situasi dunia nyata.
  • Penargetan platform yang lebih baik - dengan menunda kompilasi untuk memulai aplikasi (kompilasi JIT dll.) Kompiler Java dapat mengambil keuntungan dari fakta bahwa ia mengetahui prosesor yang tepat yang dijalankannya. Ini dapat mengaktifkan beberapa optimisasi yang sangat bermanfaat yang tidak dapat Anda lakukan dalam kode C / C ++ yang dikompilasi sebelumnya yang perlu menargetkan rangkaian instruksi prosesor "denominator umum terendah".
  • Statistik Runtime - karena kompilasi JIT dilakukan pada saat runtime, ia dapat mengumpulkan statistik saat program sedang dijalankan yang memungkinkan optimisasi yang lebih baik (misalnya mengetahui probabilitas bahwa cabang tertentu diambil). Ini dapat mengaktifkan kompiler Java JIT untuk menghasilkan kode yang lebih baik daripada kompiler C / C ++ (yang harus "menebak" cabang yang paling mungkin di muka, sebuah asumsi yang mungkin sering salah).
  • Pustaka yang sangat bagus - Java runtime berisi sejumlah pustaka yang ditulis dengan sangat baik dengan kinerja yang baik (terutama untuk aplikasi sisi server). Seringkali ini lebih baik daripada yang bisa Anda tulis sendiri atau dapatkan dengan mudah untuk C / C ++.

Pada saat yang sama C / C ++ juga memiliki beberapa keunggulan:

  • Lebih banyak waktu untuk melakukan optimisasi lanjutan - Kompilasi C / C ++ dilakukan sekali, dan karenanya dapat menghabiskan banyak waktu melakukan optimisasi lanjutan jika Anda mengonfigurasinya untuk melakukannya. Tidak ada alasan teoritis mengapa Java tidak dapat melakukan hal yang sama, tetapi dalam praktiknya Anda ingin Java mengkompilasi kode JIT relatif cepat, sehingga kompiler JIT cenderung fokus pada optimisasi "sederhana".
  • Instruksi yang tidak dapat diekspresikan dalam bytecode - sementara Java bytecode sepenuhnya bersifat umum, masih ada beberapa hal yang dapat Anda lakukan pada level rendah yang tidak dapat Anda lakukan dalam bytecode (aritmatika pointer yang tidak dicentang adalah contoh yang baik!). Dengan (ab) menggunakan trik semacam ini Anda bisa mendapatkan beberapa keunggulan kinerja
  • Kurang kendala "keselamatan" - Java melakukan beberapa pekerjaan tambahan untuk memastikan bahwa program-program tersebut aman dan andal. Contohnya adalah cek batas pada array, jaminan konkurensi tertentu, pemeriksaan pointer nol, ketik keamanan pada gips dll. Dengan menghindari ini dalam C / C ++ Anda bisa mendapatkan beberapa peningkatan kinerja (meskipun bisa dibilang ini bisa menjadi ide yang buruk!)

Secara keseluruhan:

  • Java dan C / C ++ dapat mencapai kecepatan yang sama
  • C / C ++ mungkin memiliki sedikit keunggulan dalam situasi yang ekstrim (tidak mengherankan bahwa pengembang game AAA masih lebih suka, misalnya)
  • Dalam praktiknya itu akan tergantung pada bagaimana faktor-faktor yang tercantum di atas menyeimbangkan untuk aplikasi khusus Anda.
mikera
sumber
9
Iklan "lebih banyak waktu untuk optimisasi dalam C ++": Itulah salah satu tweak yang dilakukan Oracle VM ketika Anda memilih Server VM: Ini menerima biaya awal yang lebih tinggi untuk memungkinkan kinerja yang lebih tinggi dalam jangka panjang. Namun, VM Klien diubah untuk waktu startup yang optimal. Sehingga perbedaan itu bahkan ada di Jawa.
Joachim Sauer
8
-1: Kompiler C ++ dapat mengambil lebih banyak waktu (berjam-jam, secara harfiah, untuk pustaka besar) untuk membuat biner yang sangat optimal. Kompiler Java JIT tidak dapat mengambil banyak waktu, bahkan versi "server". Saya benar-benar ragu bahwa kompiler Java JIT akan dapat melakukan Optimalisasi Program Utuh seperti yang dilakukan oleh kompiler MS C ++.
quant_dev
20
@quant_dev: pasti, tapi bukankah itu yang saya katakan dalam jawaban saya sebagai keunggulan C ++ (lebih banyak waktu untuk melakukan optimasi lanjutan)? Jadi mengapa -1?
mikera
13
Pengumpulan sampah bukan keuntungan kecepatan untuk Jawa. Ini hanya keuntungan kecepatan jika Anda seorang programmer C ++ yang tidak tahu apa yang Anda lakukan. Jika yang Anda periksa adalah seberapa cepat Anda dapat mengalokasikan, maka ya, pemulung akan menang. Performa program secara keseluruhan, bagaimanapun, masih bisa lebih baik dilakukan dengan mengelola memori secara manual.
Billy ONeal
4
... Tetapi dengan C ++, Anda selalu bisa secara teoritis menempatkan "lapisan seperti JIT" yang melakukan optimasi cabang yang sama saat runtime, sambil mempertahankan kecepatan mentah dari program C ++. (Secara teoritis. :()
Mateen Ulhaq
19

Java runtime tidak menafsirkan bytecode. Sebaliknya, ia menggunakan whats yang disebut Just In Time Compilation . Pada dasarnya, ketika program dijalankan, ia mengambil bytecode dan mengubahnya menjadi kode asli yang dioptimalkan untuk CPU tertentu.

GrandmasterB
sumber
Dalam latihan, ya. Pada prinsipnya, itu tergantung - mesin virtual Java awal yang digunakan oleh bytecode interpreter, dan Anda mungkin masih dapat menemukan VM interpretasi bytecode jika Anda terlihat cukup keras.
Steve314
10
@ Steve314: tetapi VM yang menafsirkan murni tidak akan menjadi yang mengungguli C ++, jadi mereka tidak benar-benar relevan dengan pertanyaan ini.
Joachim Sauer
Kompiler JIT juga dapat mengoptimalkan secara dinamis untuk penggunaan spesifik kode, yang tidak mungkin dilakukan dengan kode yang dikompilasi secara statis.
starblue
2
@ starblue, well, ini mungkin dilakukan dengan kompilasi statis - lihat optimasi berpandu profil.
SK-logic
19

Semua hal dianggap sama, Anda dapat mengatakan: tidak, Java seharusnya tidak pernah lebih cepat . Anda selalu dapat mengimplementasikan Java dalam C ++ dari awal dan karenanya mendapatkan kinerja yang setidaknya sama baiknya. Namun dalam praktiknya:

  • JIT mengkompilasi kode pada mesin pengguna akhir, memungkinkannya untuk mengoptimalkan CPU yang tepat yang mereka jalankan. Meskipun ada overhead di sini untuk kompilasi, itu mungkin membayar untuk aplikasi intensif. Seringkali program kehidupan nyata tidak dikompilasi untuk CPU yang Anda gunakan.
  • Kompiler Java mungkin lebih baik secara otomatis mengoptimalkan hal-hal daripada kompiler C ++. Atau mungkin tidak, tetapi di dunia nyata, segalanya tidak selalu sempurna.
  • Perilaku kinerja dapat bervariasi karena faktor-faktor lain, seperti pengumpulan sampah. Di C ++, Anda biasanya memanggil destruktor segera setelah selesai dengan objek. Di Jawa, Anda cukup merilis referensi, menunda kehancuran yang sebenarnya. Ini adalah contoh lain dari perbedaan yang tidak ada di sini atau di sana, dalam hal kinerja. Tentu saja, Anda dapat berargumen bahwa Anda dapat mengimplementasikan GC dalam C ++ dan selesai dengannya, tetapi kenyataannya hanya sedikit orang yang ingin / dapat melakukannya.

Sebagai tambahan, ini mengingatkan saya pada perdebatan tentang C di tahun 80-an / 90-an. Semua orang bertanya-tanya, "bisakah C secepat perakitan?" Pada dasarnya, jawabannya adalah: tidak di atas kertas, tetapi pada kenyataannya kompiler C menciptakan kode yang lebih efisien daripada 90% dari programer perakitan (baik, setelah sedikit matang).

Daniel B
sumber
2
Mengenai GC, bukan hanya bahwa GC dapat menunda penghancuran objek (yang seharusnya tidak menjadi masalah dalam jangka panjang); faktanya adalah bahwa dengan GC modern, alokasi / alokasi objek yang berumur pendek sangat murah di Jawa dibandingkan dengan C ++.
Péter Török
@ PéterTörök ya, Anda benar, poin bagus.
Daniel B
9
@ PéterTörök Tapi di C ++, objek berumur pendek sering diletakkan di stack, yang pada gilirannya jauh lebih cepat daripada heap GC-ed yang bisa digunakan Java.
quant_dev
@quant_dev, Anda lupa efek GC signifikan lainnya: pemadatan. Jadi saya tidak akan begitu yakin jalan mana yang lebih cepat.
SK-logic
3
@ DonalFellows Apa yang membuat Anda berpikir saya harus khawatir tentang manajemen memori di C ++? Sebagian besar waktu saya tidak. Ada pola-pola sederhana yang perlu Anda terapkan, yang berbeda dari Jawa, tetapi hanya itu.
quant_dev
10

Tetapi alokasi hanya setengah dari manajemen memori - alokasi adalah setengah lainnya. Ternyata untuk sebagian besar objek, biaya pengumpulan sampah langsung adalah - nol. Ini karena seorang kolektor penyalinan tidak perlu mengunjungi atau menyalin objek mati, hanya yang hidup. Jadi objek yang menjadi sampah tidak lama setelah alokasi berkontribusi tanpa beban kerja ke siklus pengumpulan.

...

Secara mengejutkan, JVM pandai mencari tahu hal-hal yang kami anggap hanya pengembang yang tahu. Dengan membiarkan JVM memilih antara alokasi tumpukan dan alokasi tumpukan berdasarkan kasus per kasus, kita bisa mendapatkan manfaat kinerja dari alokasi tumpukan tanpa membuat programmer merasa tersinggung apakah akan mengalokasikan pada tumpukan atau pada tumpukan.

http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html

Landei
sumber
Ini hanya sebagian kecil dari keseluruhan gambar, namun cukup relevan.
Joachim Sauer
2
Saya suka bagaimana substansinya: java adalah untuk noobs, percayalah pada magic GC, ia lebih tahu.
Morg.
1
@Morg: Atau Anda dapat membacanya seperti itu: Java adalah untuk orang-orang yang suka menyelesaikan sesuatu alih-alih membuang-buang waktu mereka dengan sedikit memutar-mutar dan manajemen memori manual.
Landei
4
@ Landei Saya pikir komentar Anda akan memiliki kredibilitas yang jauh lebih tinggi jika ada basis kode lama yang layak dan telah lama digunakan telah ditulis di Jawa. Di dunia saya, OS nyata ditulis dalam C, postgreSQL ditulis dalam C, seperti juga alat yang paling penting yang benar-benar akan merepotkan untuk menulis ulang. Java adalah (dan itu bahkan versi resmi) untuk memungkinkan orang yang kurang terampil untuk memprogram dalam kelompok dan belum mencapai hasil yang nyata.
Morg.
1
@ Maaf saya merasa sangat aneh bagaimana Anda tampaknya fokus hanya pada OS. Ini tidak bisa menjadi ukuran yang baik, karena beberapa alasan. Pertama, persyaratan OS sangat berbeda dari kebanyakan perangkat lunak lain, kedua Anda memiliki prinsip ibu jari Panda (yang ingin menulis ulang OS lengkap dalam bahasa lain, yang ingin menulis OS sendiri jika ada yang berfungsi dan bahkan alternatif gratis?) dan ketiga perangkat lunak lain menggunakan fitur OS, jadi tidak perlu lagi menulis disk driver, task manager, dll. Jika Anda tidak dapat memberikan beberapa argumen yang lebih baik (tidak didasarkan sepenuhnya pada OS) Anda terdengar seperti pembenci.
Landei
5

Sementara program Java yang sepenuhnya dioptimalkan jarang akan mengalahkan program C ++ yang sepenuhnya dioptimalkan, perbedaan dalam hal-hal seperti manajemen memori dapat membuat banyak algoritma diimplementasikan secara idiomatis di Jawa lebih cepat daripada algoritma yang sama yang diimplementasikan secara idiomatis di C ++.

Seperti yang ditunjukkan oleh @Jerry Coffin, ada banyak kasus di mana perubahan sederhana dapat membuat kode lebih cepat - tetapi seringkali terlalu banyak perubahan yang tidak jelas dalam satu bahasa atau yang lain untuk peningkatan kinerja menjadi berharga. Itu mungkin yang akan Anda lihat dalam tolok ukur yang baik yang menunjukkan Java melakukan lebih baik daripada C ++.

Juga, meskipun biasanya tidak terlalu signifikan, ada beberapa optimasi kinerja yang bisa dilakukan oleh bahasa JIT seperti Java yang tidak dapat dilakukan C ++. Java runtime dapat menyertakan peningkatan setelah kode dikompilasi, yang berarti bahwa JIT berpotensi menghasilkan kode yang dioptimalkan untuk memanfaatkan fitur CPU yang baru (atau setidaknya berbeda). Untuk alasan ini, biner Java 10 tahun yang berpotensi mengungguli biner C ++ 10 tahun.

Terakhir, keamanan tipe lengkap dalam gambar yang lebih besar dapat, dalam kasus yang sangat jarang, menawarkan peningkatan kinerja yang ekstrem. Singularity , sebuah OS eksperimental yang ditulis hampir seluruhnya dalam bahasa berbasis C #, memiliki komunikasi antar proses yang jauh lebih cepat dan multitasking karena kenyataan bahwa tidak perlu untuk batasan proses perangkat keras atau switch konteks yang mahal.

Rei Miyasaka
sumber
5

Diposting oleh Tim Holloway di JavaRanch:

Berikut adalah contoh primitif: Dulu ketika mesin dioperasikan dalam siklus yang ditentukan secara matematis, instruksi cabang biasanya memiliki 2 timing yang berbeda. Satu untuk saat cabang diambil, satu untuk saat cabang tidak diambil. Biasanya, case no-branch lebih cepat. Jelas, ini berarti bahwa Anda dapat mengoptimalkan logika berdasarkan pengetahuan tentang kasus mana yang lebih umum (tunduk pada batasan bahwa apa yang kita "tahu" tidak selalu apa yang sebenarnya terjadi).

Kompilasi JIT mengambil langkah ini lebih jauh. Ini memonitor penggunaan real-time aktual, dan membalikkan logika berdasarkan apa yang sebenarnya merupakan kasus yang paling umum. Dan balikkan lagi jika beban kerja bergeser. Kode yang dikompilasi secara statis tidak dapat melakukan ini. Begitulah cara Java kadang-kadang dapat melakukan out-tuned assembly / C / C ++ kode yang disesuaikan.

Sumber: http://www.coderanch.com/t/547458/Performance/java/Ahead-Time-vs-Just-time

Thiago Negri
sumber
3
Dan sekali lagi, ini salah / tidak lengkap. Kompiler statis dengan optimasi berpandu profil dapat mengenali ini.
Konrad Rudolph
2
Konrad, kompiler statis dapat membalik logika berdasarkan pada beban kerja saat ini? Seperti yang saya mengerti, kompiler statis menghasilkan kode sekali dan tetap sama selamanya.
Thiago Negri
2
Beban kerja saat ini, tidak. Tapi beban kerja yang khas . Optimalisasi yang dipandu profil menganalisis bagaimana program Anda berjalan di bawah beban tipikal dan mengoptimalkan hot-spot yang sesuai, seperti halnya HotSpot JIT.
Konrad Rudolph
4

Itu karena langkah terakhir menghasilkan kode mesin terjadi secara transparan di dalam JVM saat menjalankan program Java Anda, alih-alih secara eksplisit saat membuat proram C ++ Anda.

Anda harus mempertimbangkan fakta bahwa JVM modern menghabiskan cukup banyak waktu mengkompilasi kode byte dengan cepat ke kode mesin asli untuk membuatnya secepat mungkin. Ini memungkinkan JVM untuk melakukan semua jenis trik kompiler yang bisa lebih baik dengan mengetahui data profil dari program yang sedang dijalankan.

Hanya hal seperti secara otomatis inter pengambil, sehingga JUMP-RETURN tidak diperlukan untuk hanya mendapatkan nilai, mempercepat sesuatu.

Namun, hal yang benar-benar memungkinkan program cepat adalah pembersihan yang lebih baik setelahnya. Mekanisme pengumpulan sampah di Jawa lebih cepat daripada manual bebas malloc di C. Banyak implementasi bebas malloc modern menggunakan pemulung di bawahnya.


sumber
Perhatikan bahwa hal-hal yang disematkan ini membuat memulai JVM lebih besar dan lebih lambat hingga kode yang lebih baik memiliki peluang untuk mengejar ketinggalan.
1
"Banyak implementasi modern bebas-malloc menggunakan pemulung di bawahnya." Benarkah? Saya ingin tahu lebih banyak; Apakah Anda punya referensi?
Sean McMillan
Terima kasih. Saya mencoba untuk menemukan cara untuk mengatakan bahwa JVM tidak lagi hanya berisi kompiler tepat waktu yang mengkompilasi ke kode yang dapat dieksekusi, tetapi kompiler hot spot yang menampilkan kode yang sedang berjalan dan mengoptimalkan lebih lanjut sebagai hasilnya. Saya kompiler satu kali seperti C ++ berjuang untuk mencocokkannya.
Highland Mark
@SeanMcMillan, saya melihat analisis beberapa waktu lalu tentang kinerja implementasi bebas malloc di mana disebutkan bahwa yang tercepat menggunakan pengumpul sampah di bawahnya. Saya tidak ingat di mana saya membacanya.
Apakah itu BD konservatif GC?
Demi
4

Jawaban singkat - tidak. Lupakan saja, topiknya setua api atau roda. Java atau .NET tidak dan tidak akan lebih cepat dari C / C ++. Cukup cepat untuk sebagian besar tugas di mana Anda tidak perlu memikirkan pengoptimalan sama sekali. Seperti formulir dan pemrosesan SQL, tapi di situlah akhirnya.

Untuk tolok ukur, atau aplikasi kecil yang ditulis oleh pengembang yang tidak kompeten ya, hasil akhirnya adalah bahwa Java / .NET mungkin akan menjadi dekat dan mungkin bahkan lebih cepat.

Pada kenyataannya, hal-hal sederhana seperti mengalokasikan memori pada stack, atau hanya menggunakan memzones hanya akan mematikan Java / .NET di tempat.

Dunia pengumpulan sampah menggunakan semacam memzone dengan segala akuntingnya. Tambahkan memzone ke C dan C akan lebih cepat di sana di tempat. Khusus untuk tolok ukur "vs. kode kinerja" Java vs. C, yang berlaku seperti ini:

for(...)
{
alloc_memory//Allocating heap in a loop is verrry good, in't it?
zero_memory//Extra zeroing, we really need it in our performance code
do_stuff//something like memory[i]++
realloc//This is lovely speedup
strlen//loop through all memory, because storing string length is soo getting old
free//Java will do that outside out timing loop, but oh well, we're comparing apples to oranges here
}//loop 100000 times

Cobalah untuk menggunakan variabel berbasis stack dalam C / C ++ (atau penempatan baru), mereka menerjemahkannya ke dalam sub esp, 0xff, itu adalah instruksi x86 tunggal, kalahkan dengan Java - Anda tidak dapat ...

Sebagian besar waktu saya melihat bangku-bangku di mana Java terhadap C ++ dibandingkan menyebabkan saya pergi seperti, wth? Strategi alokasi memori yang salah, wadah yang tumbuh sendiri tanpa cadangan, banyak yang baru. Ini bahkan tidak dekat dengan kode C / C ++ yang berorientasi pada kinerja.

Juga bacaan yang bagus: https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf

Coder
sumber
1
Salah. Benar-benar salah. Anda tidak akan dapat mengungguli GC pemadat dengan manajemen memori manual Anda. Penghitungan referensi naif tidak akan pernah lebih baik dari tanda yang tepat. Begitu sampai pada manajemen memori yang rumit, C ++ adalah perlambatan.
SK-logic
3
@ SK-Logic: Salah, dengan memzones atau alokasi stack tidak ada alokasi memori atau alokasi sama sekali. Anda memiliki blok memori dan Anda hanya menulis saja. Tandai blok sebagai bebas dengan variabel volatil seperti perlindungan konkurensi, InterlockedExchange dll., Dan utas berikutnya hanya membuang datanya ke blok yang sudah dialokasikan tanpa pergi ke OS untuk memori sama sekali, jika ia melihat itu gratis. Dengan stack lebih mudah, dengan satu-satunya pengecualian bahwa Anda tidak dapat membuang 50MB di stack. Dan objek seumur hidup itu hanya di dalam {}.
Coder
2
@ SK-logic: Compiler adalah kebenaran pertama, kinerja kedua. Mesin pencari, mesin basis data, sistem perdagangan waktu-nyata, permainan adalah apa yang saya anggap penting untuk kinerja. Dan sebagian besar dari mereka bergantung pada struktur datar. Dan bagaimanapun, kebanyakan kompiler ditulis dalam C / C ++. Dengan pengalokasi khusus, saya kira. Kemudian lagi, saya melihat tidak ada masalah dengan menggunakan elemen pohon atau daftar di atas rammap. Anda cukup menggunakan penempatan baru. Tidak ada banyak kerumitan dalam hal itu.
Coder
3
@ SK-logic: Tidak terlalu cepat, setiap aplikasi .NET / Java yang saya lihat, selalu ternyata lebih lambat, dan benar-benar babi. Setiap penulisan ulang aplikasi yang dikelola ke dalam kode SANE C / C ++ menghasilkan aplikasi yang lebih bersih dan lebih ringan. Aplikasi yang dikelola selalu berat. Lihat VS2010 vs 2008. Struktur data yang sama, tetapi VS2010 adalah HOG. Aplikasi C / C ++ yang ditulis dengan benar biasanya boot dalam milidetik, dan tidak macet di layar splash, sementara juga mengkonsumsi lebih sedikit memori. Satu-satunya downside adalah bahwa Anda harus kode dengan perangkat keras dalam pikiran, dan banyak orang tidak tahu bagaimana sekarang ini. Ini hanya tolok ukur di mana dikelola memiliki peluang.
Coder
2
bukti anekdotal Anda tidak masuk hitungan. Tolok ukur yang tepat menunjukkan perbedaan nyata. Sangat aneh bahwa Anda mengacu pada aplikasi GUI, terikat ke perpustakaan GUI yang besar dan tidak optimal. Dan, yang lebih penting - dalam teori batas kinerja jauh lebih tinggi untuk penerapan GC yang benar.
SK-logic
2

Kenyataannya adalah mereka berdua hanya perakit tingkat tinggi yang melakukan persis apa yang disuruh programmer kepada mereka, tepatnya bagaimana programmer memberi tahu mereka dalam urutan yang tepat yang dikatakan oleh programmer. Perbedaan kinerja sangat kecil sehingga tidak penting untuk semua tujuan praktis.

Bahasa tidak "lambat", programmer menulis program lambat. Jarang sekali sebuah program menulis cara terbaik dalam satu bahasa lebih baik daripada (untuk tujuan praktis apa pun) program melakukan hal yang sama dengan menggunakan cara terbaik dari bahasa alternatif, kecuali jika penulis studi keluar untuk menggiling kapak khususnya.

Jelas jika Anda akan menggunakan case tepi yang langka seperti sistem embedded realtime yang sulit, pilihan bahasa dapat membuat perbedaan, tetapi seberapa sering hal ini terjadi? dan dari kasus-kasus itu, seberapa sering pilihan yang tepat tidak begitu jelas.

mattnz
sumber
2
Secara teori, VM JITting "ideal" harus mengungguli kode yang dikompilasi secara statis, dengan menyesuaikan optimisasinya dengan informasi profil yang dikumpulkan secara dinamis. Dalam praktiknya, kompiler JIT belum sepintar itu, tetapi mereka setidaknya mampu menghasilkan kode dengan kualitas yang sama dengan rekan-rekan statis yang lebih besar dan lebih lambat.
SK-logic
2

Lihat tautan berikut ... Tetapi bagaimana ini mungkin? Ini mengejutkan saya bahwa interpretasi bytecode bisa lebih cepat daripada bahasa yang dikompilasi.

  1. Apakah posting blog itu memberikan bukti yang dapat dipercaya?
  2. Apakah posting blog itu memberikan bukti yang pasti?
  3. Apakah posting blog itu bahkan memberikan bukti tentang "interpretasi bytecode"?

Keith Lea memberi tahu Anda ada "kekurangan yang jelas" tetapi tidak melakukan apa pun tentang "kekurangan yang jelas" itu. Kembali pada tahun 2005 tugas-tugas lama itu dibuang dan diganti dengan tugas-tugas yang sekarang ditampilkan dalam permainan tolok ukur .

Keith Lea memberi tahu Anda bahwa ia "mengambil kode tolok ukur untuk C ++ dan Java dari Great Computer Language Shootout yang sudah usang dan menjalankan tes" tetapi sebenarnya ia hanya menunjukkan pengukuran untuk 14 dari 25 tes yang sudah ketinggalan zaman .

Keith Lea sekarang memberitahu Anda bahwa dia tidak berusaha membuktikan apa pun dengan posting blog tujuh tahun sebelumnya, tetapi saat itu dia berkata, "Saya muak mendengar orang mengatakan Jawa lambat, ketika saya tahu itu cukup cepat ..." yang menunjukkan saat itu ada sesuatu yang dia coba buktikan.

Christian Felde memberi tahu Anda, "Saya tidak membuat kode, hanya menjalankan ulang tes." seolah-olah itu membebaskannya dari tanggung jawab atas keputusannya untuk mempublikasikan pengukuran tugas dan program yang dipilih Keith Lea.

Apakah pengukuran bahkan 25 program kecil mungil memberikan bukti pasti?

Pengukuran tersebut untuk program yang dijalankan sebagai "mode campuran" Java tidak menafsirkan Java - "Ingat cara kerja HotSpot." Anda dapat dengan mudah mengetahui seberapa baik Java menjalankan "interpreted bytecode", karena Anda dapat memaksa Java untuk hanya menafsirkan bytecode - cukup gunakan waktu beberapa program Java dengan dan tanpa opsi -Xint.

igouy
sumber
-1

Ini menghibur saya betapa meresap gagasan aneh "ditafsirkan bytecode" ini. Pernahkah Anda mendengar tentang kompilasi JIT? Argumen Anda tidak dapat diterapkan ke Java.

Tetapi, mengesampingkan JVM, ada kasus ketika kode berulir langsung atau bahkan interpretasi bytecode sepele dapat dengan mudah mengungguli kode asli yang sangat dioptimalkan. Penjelasannya cukup sederhana: bytecode bisa sangat ringkas dan akan cocok dengan cache kecil Anda ketika versi kode asli dari algoritma yang sama akan berakhir memiliki beberapa kesalahan cache untuk satu iterasi tunggal.

Logika SK
sumber
Keabsahan interpretasi ini mungkin disebabkan oleh orang yang ahli dalam ilmu komputer mereka. Mesin virtual java adalah mesin yang menerima bytecode java dan menjalankannya pada mesin / tidak / mampu menjalankan java bytecode secara asli, tanpa mampu menulis program asli yang secara fungsional setara. Ergo itu adalah juru bahasa. Anda bisa memberikan teknik caching apa pun nama yang dapat Anda pikirkan, JIT atau lainnya, tetapi itu adalah penerjemah berdasarkan definisi penerjemah.
thiton
@ thiton, kemungkinan CS-fu Anda agak lemah. JVM tidak melakukan interpretasi apa pun (untuk hot spot) - sebagai seseorang yang berani menyebutkan CS, Anda harus tahu apa artinya, dan bagaimana semantik operasional interpretasi berbeda dari menjalankan kode asli. Tetapi, sepertinya, Anda tidak cukup tahu tentang CS untuk membedakan kompilasi dari interpretasi.
SK-logic
2
Umm, tetapi bytecode, untuk dapat dijalankan, harus dikonversi ke kode asli - Anda tidak dapat memberi makan bytecode Java ke CPU. Jadi argumen ukuran tidak valid.
quant_dev
@quant_dev, tentu saja - saya mengatakan bahwa kasus ini sama sekali tidak terkait dengan JVM. Anda perlu mesin bytecode yang lebih sederhana untuk membuat efek itu bekerja.
SK-logic
-1

JIT, GC dan sebagainya, C ++ bisa sangat, sangat mudah dibuat lebih lambat dari Jawa. Ini tidak akan muncul di tolok ukur, tetapi aplikasi yang sama yang ditulis oleh pengembang Java dan pengembang C ++ mungkin jauh lebih cepat di Jawa.

  • Kelebihan operator. Setiap operator sederhana seperti "+" atau "=" dapat memanggil ratusan baris kode untuk melakukan pemeriksaan keselamatan, operasi disk, pencatatan, pelacakan, dan pembuatan profil. Dan mereka sangat mudah digunakan sehingga setelah Anda membebani operator, Anda menggunakannya secara alami dan berlebihan tanpa memperhatikan bagaimana penggunaannya.
  • Templat. Ini tidak mempengaruhi kecepatan sebanyak memori. Penggunaan template yang tidak hati-hati akan menghasilkan jutaan baris kode (alternatif untuk template dasar) tanpa Anda pernah melihatnya. Tapi kemudian waktu pemuatan biner, penggunaan memori, penggunaan swap - semua itu bertindak terhadap tolok ukur juga. Dan penggunaan RAM melewati atap.

Adapun pola pewarisan lanjutan, ini hampir mirip - C + + memiliki beberapa yang tidak Java dan sebaliknya, tetapi semuanya memperkenalkan overhead yang signifikan juga. Jadi tidak ada keunggulan khusus C ++ dalam pemrograman objek-berat.

Satu lagi peringatan: GC bisa lebih cepat atau lebih lambat daripada mengelola alokasi secara manual. Jika Anda mengalokasikan banyak objek kecil, dalam lingkungan GC biasanya sepotong memori dialokasikan dan potongan-potongan itu dikirim sesuai kebutuhan untuk objek baru. Dalam dikelola - setiap objek = alokasi terpisah membutuhkan waktu yang signifikan. OTOH, jika Anda malloc () banyak memori sekaligus dan kemudian hanya memberikan potongan-potongan itu ke objek Anda secara manual, atau menggunakan beberapa contoh objek yang lebih besar, Anda mungkin muncul lebih cepat.

SF.
sumber
4
Saya tidak setuju dengan kedua poin. Apakah Anda menggunakan operator atau metode tidak relevan. Anda mengatakan bahwa mereka akan berkembang biak. Omong kosong - tidak lebih dari metode akan; Anda juga perlu memanggil mereka, atau tidak. Dan templat menghasilkan kode tidak lebih dari tulisan tangan bahwa kode tertentu lagi untuk beberapa penggunaan. Mungkin ada lebih banyak kode daripada pengiriman runtime (fungsi virtual) tetapi ini juga tidak akan relevan: kinerja jalur cache instruksi paling penting dalam loop ketat dan di sini hanya akan ada satu contoh template yang digunakan, jadi tidak ada tekanan memori yang relevan karena template.
Konrad Rudolph
Pola pikir yang biasa adalah bahwa metode itu mahal, operator itu murah. Anda menggunakan metode saat Anda harus, operator kapan pun Anda ingin menghemat waktu dan mengoptimalkan. Ini bukan masalah teknis, tetapi psikologis - bukan karena operator "lebih berat", mereka hanya lebih mudah digunakan dan digunakan lebih sering. (ditambah Anda dapat membebani operator yang sering digunakan dalam kode yang sudah ada sebelumnya, membuatnya melakukan hal yang sama seperti aslinya, ditambah tambahan - dan tiba-tiba seluruh kode akan melambat secara signifikan.
SF.
Saya berpendapat bahwa fakta psikologis ini nyata, dan bahkan jika itu, Anda tidak punya pilihan : jika Anda memerlukan fungsionalitas, Anda menggunakannya, apakah itu dirangkum dalam operator atau metode. Psikologi tidak relevan untuk pilihan semantik Anda.
Konrad Rudolph
1
Pertanyaan jebakan. Saya tidak akan menebak ini sama sekali, saya akan mengukur, bertindak kemudian . Saya tidak pernah memiliki masalah dengan taktik itu.
Konrad Rudolph
1
@KonradRudolph: Ini semua benar ketika datang ke kejelasan dan kemudahan menulis kode, membuatnya bebas bug dan dapat dipelihara. Poin tentang efisiensi penerapan algoritma masih berdiri: jika Anda akan menulis obj.fetchFromDatabase("key")tiga kali dalam lima baris kode untuk kunci yang sama, Anda akan berpikir dua kali apakah akan mengambil nilai itu sekali dan menyimpannya dalam variabel lokal. Jika Anda menulis obj->"key"dengan ->kelebihan beban untuk bertindak sebagai pengambilan basis data, Anda jauh lebih rentan untuk membiarkannya berlalu karena biaya operasi tidak jelas.
SF.
-2

Entah bagaimana Stack Exchange tidak mengambil stackpoint saya yang lain jadi ... sayangnya tidak ada balasan ...

Namun jawaban terbanyak kedua di sini penuh dengan informasi yang salah dalam pendapat saya yang sederhana.

Aplikasi linting tangan oleh pakar C / C ++ SELALU akan jauh lebih cepat daripada aplikasi Java, titik. Tidak ada 'secepat Java atau Lebih Cepat'. hanya saja lebih cepat, justru karena item yang Anda kutip di bawah ini:

Kompilasi JIT : Apakah Anda benar-benar mengharapkan pengoptimal otomatis memiliki kecerdasan programmer ahli dan melihat tautan antara maksud dan kode yang benar-benar dijalankan CPU ??? Selain itu, semua JIT yang Anda lakukan adalah waktu yang hilang dibandingkan dengan program yang sudah dikompilasi.

Garbage Collection adalah alat yang secara sederhana mengalokasikan sumber daya yang lupa dilupakan oleh pemrogram, dengan cara yang lebih atau kurang efisien.

Jelas ini hanya bisa lebih lambat dari apa yang dilakukan oleh seorang ahli (Anda memilih istilahnya) programmer C untuk menangani ingatannya (dan tidak ada kebocoran pada aplikasi yang ditulis dengan benar).

Aplikasi C yang dioptimalkan kinerja mengetahui bahwa CPU sedang berjalan, sudah dikompilasi, apakah itu berarti Anda tidak cukup mengambil semua langkah untuk kinerja, bukan?

Statistik Runtime Ini di luar pengetahuan saya, tetapi saya curiga bahwa seorang pakar di C memiliki lebih dari cukup pengetahuan prediksi cabang untuk mengakali lagi optimasi otomatis -

Perpustakaan yang sangat baik Ada banyak fungsi yang tidak dioptimalkan yang tersedia melalui perpustakaan di Jawa, dan hal yang sama berlaku dalam bahasa apa pun, namun perpustakaan yang paling optimal ditulis dalam C, terutama untuk perhitungan.

JVM adalah lapisan abstraksi, yang menyiratkan kedua hal baik yang banyak di atas, dan juga menyiratkan bahwa solusi keseluruhan lebih lambat oleh desain.

Secara keseluruhan:

Java tidak pernah dapat mencapai kecepatan C / C ++ karena cara kerjanya di JVM dengan banyak perlindungan, fitur dan alat.

C ++ memiliki keunggulan yang jelas dalam perangkat lunak yang dioptimalkan, baik itu untuk komputasi atau permainan, dan itu biasa untuk melihat implementasi C ++ memenangkan kontes pengkodean hingga titik bahwa implementasi Java terbaik hanya dapat dilihat di halaman kedua.

Dalam praktiknya C ++ bukan mainan dan tidak akan membiarkan Anda lolos dengan banyak kesalahan yang dapat ditangani oleh sebagian besar bahasa modern, namun dengan menjadi lebih sederhana dan kurang aman, itu pada dasarnya lebih cepat.

Dan sebagai kesimpulan, saya ingin mengatakan bahwa kebanyakan orang tidak memberikan dua sen tentang ini, bahwa pada akhirnya optimalisasi adalah olahraga yang hanya dimiliki oleh beberapa pengembang yang beruntung dan bahwa kecuali dalam kasus di mana kinerja benar-benar menjadi perhatian. (yaitu ketika mengalikan perangkat keras dengan 10 tidak akan membantu Anda - atau setidaknya mewakili jutaan), sebagian besar manajer akan lebih memilih aplikasi yang tidak dioptimalkan dan satu ton perangkat keras.

Morg.
sumber
Lagi. Pengumpulan sampah tidak hanya merupakan "alat yang mengalokasikan". GC dapat memadatkan struktur Anda. GC dapat menangani referensi Anda yang lemah dan membantu Anda menyeimbangkan caching Anda dengan cara ini. Multistage GC membuat alokasi tumpukan jauh lebih murah daripada Anda yang besar, lambat newatau malloc(). Ini bisa menjadi jauh lebih cepat secara umum daripada manajemen memori manual - karena Anda tidak akan dapat memindahkan objek secara manual. Jadi, semua alasan Anda jelas salah dan bias. Pengetahuan Anda tentang algoritma GC dan metode optimisasi JIT terlalu terbatas.
SK-logic
4
Jawaban ini penuh dengan kesalahpahaman tentang apa yang dapat dilakukan oleh pengoptimal modern. Kode yang dioptimalkan dengan tangan tidak tahan terhadap hal itu. Tapi kemudian, C ++ juga memiliki kompiler yang mengoptimalkan.
Konrad Rudolph
Terima kasih atas komentar Anda SK-logika, tetapi ketika Anda menyatakannya, GC dapat menjadi jauh lebih cepat secara umum, kita berbicara tentang apa yang akan menjadi yang tercepat dalam kasus tertentu, dan sepertinya sebagian besar orang setuju bahwa apa pun yang dapat GC apakah seorang programmer dapat melakukannya, dan bahkan lebih baik lagi. Tentu saja Anda dapat memindahkan objek secara manual ketika Anda memiliki akses memori langsung .. lol. Pengetahuan saya tentang internal JVM pasti terbatas dan saya berharap Java-head menunjukkan kepada saya cahaya, tidak hanya memberi tahu saya omong kosong acak tentang GC yang dapat melakukan hal-hal yang tidak dapat dilakukan secara manual (lol ... bahkan GC harus gunakan instruksi CPU;)).
Morg.
Konrad, saya setuju bahwa saya sangat meremehkan pengoptimal modern ... namun saya merasa menarik bahwa Anda menganggap kode yang dioptimalkan dengan tangan lebih rendah daripada kode yang dioptimalkan secara otomatis. Apa tepatnya yang Anda harapkan dari kompiler untuk melihat bahwa manusia tidak bisa?
Morg.
1
Baik . terus mendorong -1, itu tidak akan mengubah fakta bahwa C ++ lebih cepat dari Java. Saya mungkin tidak tahu banyak tentang kompiler modern, tetapi itu tidak membuat perbedaan ke poin utama, yang benar dan bertentangan dengan jawaban yang paling banyak dipilih di sini. Mengapa lagi C ++ menjadi prioritas untuk nVidia pada GPU mereka untuk HPC. Mengapa lagi semua game ditulis dalam C ++, mengapa lagi setiap mesin DB tunggal ditulis dalam C?
Morg.
-4

Saya telah melihat setidaknya dua mmo mengesankan dilakukan di Jawa, untuk mengatakan itu tidak cukup cepat untuk permainan adalah keliru. Hanya karena para perancang game lebih menyukai C ++ daripada bahasa lain mengatakan itu tidak hanya terkait dengan Java, itu hanya berarti bahwa programmer tidak pernah benar-benar mencoba-coba bahasa pemrograman / paradigma lain. Apa pun dalam bahasa apa pun semaju C / C ++ atau bahkan Java dapat menghasilkan kode yang secara teknis dapat memenuhi atau mengalahkan argumen kecepatan. Semua yang dikatakan dengan baik berasal dari apa yang diketahui pemrogram, tim apa yang paling cocok bekerja dan yang paling penting mengapa mereka menggunakan alat tersebut. Karena kita menangani aspek pengembangan game dari pemrograman, maka harus ada lebih banyak argumen. Sederhananya ' Semua tentang uang dan waktu untuk bisnis yang mati karena menggunakan alat yang memenuhi QA dan di dunia nyata tidak mempermasalahkan alasan xx untuk memilih C ++ di Jawa atau bahasa lainnya. Itu hanya keputusan produksi massal. Pada level paling dasar dari algoritma komputasi yang kita mainkan adalah satu dan nol, argumen kecepatan adalah salah satu argumen paling bodoh yang pernah diterapkan pada gaming. Jika Anda menginginkan peningkatan kecepatan yang buruk maka hilangkan bahasa pemrograman sepenuhnya dan bekerja dengan perakitan yang mungkin merupakan keuntungan terbaik sejauh ini.

Meh
sumber
2
Dinding teks ini tampaknya tidak menambahkan apa pun yang belum dinyatakan dalam jawaban lain. Harap edit jawaban Anda agar lebih mudah dibaca, dan pastikan jawaban Anda menunjuk poin yang tidak dimunculkan oleh jawaban lainnya. Kalau tidak, silakan pertimbangkan untuk menghapus jawaban Anda karena itu hanya menambah kebisingan pada saat ini.