Sebuah. Bagaimana kecepatan Java saat ini dibandingkan dengan C ++?
Sulit diukur. Perlu dicatat bahwa sebagian besar kecepatan implementasi, itu adalah pengalokasi memori, adalah algoritma yang sangat berbeda di Jawa dan C ++. Sifat kolektor yang non-deterministik membuatnya sangat sulit untuk mendapatkan data kinerja yang bermakna dibandingkan dengan manajemen memori deterministik C ++, karena Anda tidak pernah dapat memastikan keadaan kolektor saat ini. Ini berarti bahwa sangat sulit untuk menulis benchmark yang mungkin membandingkan mereka secara bermakna. Beberapa pola alokasi memori berjalan lebih cepat dengan GC, beberapa menjalankan lebih cepat dengan pengalokasi asli.
Apa yang akan saya katakan adalah, Java GC harus berjalan cepat dalam setiap situasi. Namun, pengalokasi asli dapat diganti dengan yang lebih sesuai. Saya baru-baru ini mengajukan pertanyaan pada SO tentang mengapa C # Dictionary
bisa dieksekusi di (0,45 ms di komputer saya) dibandingkan dengan yang setarastd::unordered_map
yang dieksekusi pada (10 ms di mesin saya). Namun, dengan hanya mengganti pengalokasi dan hasher untuk yang lebih tepat, saya memotong waktu eksekusi menjadi 0,34 ms pada mesin saya - sepertiga puluh dari run-time asli. Anda tidak akan pernah bisa berharap untuk melakukan optimasi khusus semacam itu dengan Java. Contoh yang sangat baik di mana ini dapat membuat perbedaan nyata adalah threading. Pustaka thread asli seperti TBB menyediakan pengalokasi caching thread yang jauh lebih cepat daripada pengalokasi tradisional ketika berhadapan dengan banyak alokasi pada banyak thread.
Sekarang, banyak orang akan berbicara tentang peningkatan JIT dan bagaimana JIT memiliki informasi lebih lanjut. Tentu itu benar. Tapi itu masih bahkan tidak jauh dari apa yang dapat ditarik oleh kompiler C ++ - karena kompiler memiliki, secara komparatif, waktu dan ruang tak terbatas untuk menjalankan, dari perspektif run-time dari program akhir. Setiap siklus dan setiap byte yang dihabiskan JIT untuk memikirkan cara terbaik untuk mengoptimalkan program Anda adalah siklus dimana program Anda tidak menghabiskan mengeksekusi dan tidak dapat digunakan untuk kebutuhan memori itu sendiri.
Selain itu, akan selalu ada saat-saat di mana optimisasi kompiler dan JIT tidak dapat membuktikan optimisasi tertentu - terutama dalam hal-hal seperti melarikan diri analisis. Dalam C ++, kemudian sebagai nilai pada stack pula , compiler tidak perlu melakukan itu. Selain itu, ada hal-hal sederhana, seperti memori yang berdekatan. Jika Anda mengalokasikan array di C ++, maka Anda mengalokasikan satu array yang berdekatan. Jika Anda mengalokasikan array di Java, maka itu tidak bersebelahan sama sekali, karena array hanya diisi dengan pointer yang bisa menunjuk ke mana saja. Ini bukan hanya memori dan overhead waktu untuk tipuan ganda, tetapi overhead cache juga. Hal semacam ini adalah di mana semantik bahasa Jawa hanya menegakkan bahwa itu harus lebih lambat daripada kode C ++ yang setara.
Pada akhirnya, pengalaman pribadi saya adalah bahwa Java dapat sekitar setengah kecepatan C ++, rata-rata. Namun, secara realistis tidak ada cara untuk mendukung pernyataan kinerja apa pun tanpa rangkaian tolok ukur yang sangat komprehensif, karena algoritme yang berbeda secara mendasar.
b. Apakah mungkin untuk membuat judul AAA modern menggunakan Java?
Saya berasumsi bahwa maksud Anda "permainan", di sini, dan bukan kesempatan. Pertama, Anda harus menulis semuanya sendiri dari awal karena hampir semua perpustakaan dan infrastruktur yang ada menargetkan C ++. Meskipun tidak membuat hal itu mustahil, hal itu tentu saja dapat memberikan kontribusi yang kuat terhadap yang tidak mungkin. Kedua, bahkan mesin C ++ hampir tidak dapat memenuhi batasan memori kecil dari konsol yang ada - jika JVM bahkan ada untuk konsol tersebut - dan gamer PC mengharapkan sedikit lebih banyak untuk memori mereka. Membuat game AAA berkinerja cukup sulit di C ++, saya tidak melihat bagaimana itu bisa dicapai di Jawa. Tidak ada yang pernah menulis game AAA dengan waktu yang signifikan dihabiskan dalam bahasa yang tidak dikompilasi. Lebih dari itu, itu hanya akan sangat rawan kesalahan. Penghancuran deterministik sangat penting ketika berhadapan dengan, misalnya, sumber daya GPU- dan di Jawa, Anda
c. Di area apa secara spesifik Java lebih lambat dari C ++, jika sama sekali? (Yaitu Angka-angka, grafik, atau hanya sekitar)
Saya pasti akan pergi untuk semua. Sifat referensi yang dipaksakan dari semua objek Java berarti bahwa Java memiliki tipuan yang jauh lebih banyak dan referensi di dalamnya daripada C ++ tidak - contoh yang saya berikan sebelumnya dengan array, tetapi juga berlaku untuk semua objek anggota, misalnya. Ketika kompiler C ++ dapat mencari variabel anggota dalam waktu konstan, Java run-time harus mengikuti pointer lain. Semakin banyak akses yang Anda lakukan, semakin lambat ini akan didapat, dan tidak ada yang bisa dilakukan JIT tentang itu.
Di mana C ++ dapat membebaskan dan menggunakan kembali sepotong memori hampir secara instan, di Jawa Anda harus menunggu koleksi, dan saya berharap potongan itu tidak keluar dari cache, dan secara inheren membutuhkan lebih banyak memori berarti cache lebih rendah dan kinerja paging. Kemudian lihat semantik untuk hal-hal seperti tinju dan unboxing. Di Jawa, jika Anda ingin referensi int, Anda harus mengalokasikannya secara dinamis. Itu pemborosan yang melekat dibandingkan dengan semantik C ++.
Maka Anda memiliki masalah generik. Di Jawa, Anda hanya bisa beroperasi pada objek generik melalui run-time inheritance. Di C ++, templat benar-benar nol overhead - sesuatu yang tidak cocok dengan Java. Ini berarti bahwa semua kode generik di Jawa secara inheren lebih lambat daripada setara generik dalam C ++.
Dan kemudian Anda datang ke Perilaku Tidak Terdefinisi. Semua orang membencinya ketika program mereka memamerkan UB, dan semua orang berharap itu tidak ada. Namun, UB pada dasarnya memungkinkan optimalisasi yang tidak pernah ada di Jawa. Lihatlah postingan ini yang menjelaskan optimisasi berdasarkan UB. Tidak mendefinisikan perilaku berarti bahwa implementasi dapat melakukan lebih banyak optimasi dan mengurangi kode yang diperlukan untuk memeriksa kondisi yang tidak terdefinisi dalam C ++ tetapi didefinisikan dalam Java.
Pada dasarnya, semantik Java menyatakan bahwa itu adalah bahasa yang lebih lambat daripada C ++.
Apakah Java sekarang dianggap sebagai bahasa yang dikompilasi atau bahasa yang ditafsirkan?
Itu tidak benar-benar cocok dengan salah satu dari kelompok-kelompok itu. Saya akan mengatakan bahwa dikelola benar-benar merupakan kategori yang terpisah pada dirinya sendiri, meskipun saya akan mengatakan itu pasti lebih seperti bahasa yang ditafsirkan daripada bahasa yang dikompilasi. Lebih penting lagi, hanya ada dua sistem yang dikelola utama, JVM dan CLR, dan ketika Anda mengatakan "dikelola" itu cukup eksplisit.
Apa saja kekurangan utama Jawa yang telah diatasi sejak awal?
Tinju otomatis dan unboxing adalah satu-satunya hal yang saya ketahui. Obat generik memecahkan beberapa masalah, tetapi jauh dari banyak.
Apa saja kekurangan utama di Jawa yang belum ditangani?
Obat generik mereka sangat, sangat lemah. Obat generik C # jauh lebih kuat - walaupun tentu saja, tidak ada yang cukup templat. Kehancuran deterministik adalah kekurangan besar lainnya. Segala bentuk lambda / closure juga merupakan masalah utama - Anda bisa melupakan API fungsional di Jawa. Dan, tentu saja, selalu ada masalah kinerja, untuk bidang-bidang yang membutuhkannya.