Apakah Java benar-benar lambat?

180

Jawa memiliki beberapa tingkat reputasi karena lambat .

  • Apakah Java benar-benar lambat?
  • Jika ya, mengapa? Di mana (atau) kemacetan itu? Apakah karena JVM yang tidak efisien? Pengumpulan sampah? Pustaka bytecode murni alih-alih kode C yang dibungkus JNI? Banyak bahasa lain memiliki fitur-fitur ini, tetapi mereka tidak memiliki reputasi untuk kelambatan.
Stefano Borini
sumber
35
orang menjadi sangat gugup ... tidak melihat bagaimana ini bisa subjektif, juga tidak argumentatif. Saya ingin tahu apakah pertanyaan seperti "mengapa bubble sort lambat" akan memperoleh hasil yang sama. Saya mengajukan pertanyaan teknis, dan menginginkan jawaban teknis (yang saya dapatkan), tetapi menutup pertanyaan sebagai subyektif dan argumentatif itu konyol.
Stefano Borini
1
Saya telah membaca sebagian besar komentar teratas dan sepertinya tidak ada yang membahas fakta mencolok bahwa aplikasi desktop berbasis C # GUI berjalan jauh lebih cepat daripada aplikasi desktop berbasis Java GUI, termasuk yang modern.
BobTurbo
3
Sebagai web dev sisi klien yang telah berurusan dengan .net webforms, .net MVC, PHP, Rails, Django, dan berbagai macam segalanya kecuali Spring (yang saya dengar bagus) di Jawa, saya mengharapkan kinerja / arsitektur yang buruk dari ujung belakang dibangun oleh tim Jawa. Saya menduga masalah sebenarnya bukan tolok ukur, tetapi masalah tentang hanya menjadi omong kosong ton Jawa biasa-biasa saja di luar sana. Itu bukan salah bahasa. Bukan salah para pengembang Java yang mengasah keterampilan mereka dan belajar bahasa selain Jawa. Namun itu mungkin karena kesalahan Sun, sertifikat, tahun 90-an, dan industri TI pada umumnya.
Erik Reppen

Jawaban:

236

Java modern adalah salah satu bahasa tercepat, meskipun itu masih babi memori. Java memiliki reputasi lambat karena biasanya membutuhkan waktu lama bagi VM untuk memulai.

Jika Anda masih menganggap Java lambat , lihat hasil benchmark permainan . Kode yang dioptimalkan dengan ketat yang ditulis dalam bahasa yang dikompilasi sebelumnya (C, Fortran, dll.) Dapat mengalahkannya; Namun, Java bisa lebih dari 10x secepat PHP, Ruby, Python, dll. Ada area spesifik di mana ia bisa mengalahkan bahasa yang dikompilasi umum (jika mereka menggunakan perpustakaan standar).

Tidak ada alasan untuk aplikasi Java "lambat" sekarang. Pengembang dan kode warisan / perpustakaan yang harus disalahkan, jauh lebih dari bahasa. Juga, salahkan apa pun 'usaha.'

Dalam keadilan untuk kerumunan "Java lambat", berikut adalah area yang lambat (diperbarui untuk 2013):

  • Perpustakaan sering ditulis untuk "benar" dan mudah dibaca, bukan kinerja. Menurut pendapat saya, ini adalah alasan utama Java masih memiliki reputasi yang buruk, terutama sisi server. Ini membuat masalah String lebih buruk secara eksponensial. Beberapa kesalahan sederhana sering terjadi: objek sering digunakan sebagai ganti primitif, mengurangi kinerja dan meningkatkan penggunaan memori. Banyak perpustakaan Java (termasuk yang standar) akan sering membuat Strings, daripada menggunakan kembali format yang bisa diubah atau lebih sederhana (char [] atau StringBuffer). Ini lambat dan menghasilkan banyak sampah untuk dikumpulkan nanti. Untuk memperbaikinya, saya sarankan pengembang menggunakan koleksi primitif dan terutama perpustakaan Javalution, jika memungkinkan.

  • Operasi string agak lambat. Java menggunakan objek string yang tidak dapat diubah, UTF-16 . Ini berarti Anda memerlukan lebih banyak memori, lebih banyak akses memori, dan beberapa operasi lebih kompleks daripada dengan ASCII (C, C ++). Pada saat itu, itu adalah keputusan yang tepat untuk portabilitas, tetapi itu membawa biaya kinerja yang kecil. UTF-8 sepertinya pilihan yang lebih baik sekarang.

  • Akses array sedikit lebih lambat dibandingkan dengan C, karena batas pemeriksaan. Denda sebelumnya besar, tetapi sekarang kecil (Java 7 mengoptimalkan banyak pemeriksaan batas yang berlebihan).

  • Kurangnya akses memori sewenang-wenang dapat membuat beberapa I / O dan pemrosesan bit-level lambat (kompresi / dekompresi misalnya). Ini adalah fitur keamanan dari sebagian besar bahasa tingkat tinggi sekarang.

  • Java menggunakan memori BANYAK lebih banyak daripada C, dan jika aplikasi Anda terikat memori atau bandwidth memori terikat (caching, dll.) Ini membuatnya lebih lambat. Flipside adalah bahwa alokasi / deallokasi sangat cepat (sangat dioptimalkan). Ini adalah fitur dari sebagian besar bahasa tingkat tinggi sekarang, dan karena objek dan penggunaan GC daripada alokasi memori eksplisit. Ditambah keputusan perpustakaan yang buruk.

  • I / O berbasis stream lambat karena (IMO, pilihan yang buruk) memerlukan sinkronisasi pada setiap akses stream. NIO memperbaikinya, tetapi sulit digunakan. Orang dapat mengatasi ini dengan melakukan baca / tulis ke array, bukan elemen pada suatu waktu.

  • Java tidak menyediakan fungsionalitas tingkat rendah yang sama dengan C, jadi Anda tidak bisa menggunakan trik assembler kotor inline untuk membuat beberapa operasi lebih cepat. Ini memberikan portabilitas dan merupakan fitur dari sebagian besar bahasa tingkat tinggi sekarang.

  • Adalah umum untuk melihat aplikasi Java terkait dengan versi JVM yang sangat lama. Terutama sisi server. JVM lama ini bisa sangat tidak efisien, dibandingkan dengan versi terbaru.

Pada akhirnya, Java dirancang untuk memberikan keamanan dan portabilitas dengan mengorbankan beberapa kinerja, dan untuk beberapa operasi yang benar-benar menuntut. Sebagian besar reputasinya untuk kelambatan tidak lagi layak.


Namun, ada beberapa tempat di mana Java lebih cepat dari kebanyakan bahasa lain:

  • Alokasi memori dan de-alokasi cepat dan murah. Saya telah melihat kasus di mana 20% LEBIH CEPAT (atau lebih!) Untuk mengalokasikan array multi-kB yang baru daripada menggunakan kembali yang di-cache.

  • Instansiasi objek dan fitur berorientasi objek menyala cepat untuk digunakan (lebih cepat daripada C ++ dalam beberapa kasus), karena mereka dirancang sejak awal. Ini sebagian dari GC yang baik daripada alokasi eksplisit (yang lebih ramah untuk banyak alokasi objek kecil). Satu dapat kode C yang mengalahkan ini (dengan menggulung manajemen memori kustom dan melakukan malloc efisien), tetapi itu tidak mudah.

  • Metode panggilan pada dasarnya gratis dan dalam beberapa kasus lebih cepat daripada kode metode besar. The HotSpot compiler menggunakan informasi eksekusi dengan metode mengoptimalkan panggilan dan memiliki inlining sangat efisien. Dengan menggunakan informasi eksekusi tambahan, kadang-kadang dapat mengungguli kompiler di depan waktu dan bahkan (dalam kasus yang jarang terjadi) penyisipan manual. Bandingkan dengan C / C ++ di mana panggilan metode datang dengan penalti kinerja kecil jika kompiler memutuskan untuk tidak inline.

  • Sinkronisasi dan multi-threading mudah dan efisien. Java dirancang untuk menjadi thread-aware sejak awal, dan itu menunjukkan. Komputer modern biasanya menampilkan banyak core, dan karena threading dibangun ke dalam bahasa, Anda dapat dengan mudah memanfaatkannya. Pada dasarnya peningkatan kecepatan 100% hingga 300% ekstra vs. kode C single-threaded standar. Ya, C threading dan pustaka yang ditulis dengan hati-hati dapat mengalahkan ini, tapi itu banyak pekerjaan ekstra untuk programmer.

  • String termasuk panjang: beberapa operasi lebih cepat. Ini berdetak menggunakan string null-delimited (umum dalam C). Di Java 7, Oracle mengeluarkan optimasi String.subString (), karena orang-orang menggunakannya dengan bodoh dan mendapatkan kebocoran memori.

  • Salinan array sangat dioptimalkan. Dalam versi terbaru, Java menggunakan assembler yang disetel dengan tangan untuk System.arraycopy. Hasilnya adalah bahwa dalam operasi arraycopy / memcopy-heavy, saya telah melihat kode saya mengalahkan yang setara dalam C dengan margin yang wajar.

  • Kompiler JIT pintar menggunakan L1 / L2 cache . Program yang dikompilasi sebelumnya tidak dapat mengubah kode mereka secara real-time ke CPU & sistem spesifik yang mereka jalankan. JIT menyediakan beberapa transformasi loop yang sangat efisien dengan cara ini.

Beberapa fakta sejarah lainnya berkontribusi pada reputasi "Jawa lambat":

  • Sebelum kompilasi JIT (Java 1.2 / 1.3), bahasa hanya ditafsirkan, tidak dikompilasi, dan dengan demikian sangat lambat.
  • Kompilasi JIT membutuhkan waktu untuk menjadi efisien (peningkatan besar pada setiap versi)
  • Classloading menjadi jauh lebih efisien selama ini. Dulu cukup tidak efisien dan lambat selama startup.
  • Swing dan kode UI tidak menggunakan perangkat keras grafis asli dengan baik.
  • Ayunan hanya mengerikan. Saya menyalahkan AWT dan Swing untuk alasan mengapa Java tidak pernah menggunakan desktop.
  • Penggunaan sinkronisasi yang berat di kelas perpustakaan; versi yang tidak disinkronkan sekarang tersedia
  • Applet membutuhkan waktu lama untuk memuat, karena mentransmisikan JAR penuh melalui jaringan dan memuat VM untuk boot.
  • Sinkronisasi digunakan untuk membawa penalti performa berat (ini telah dioptimalkan dengan setiap versi Java). Refleksi masih mahal.
BobMcGee
sumber
49
Object instantiation and object-oriented features are blazing fast to use (faster than C++ in many cases) because they're designed in from the beginning.dan Collections are fast. Standard Java beats standard C/C++ in this area, even for most optimized C code.klaim liar tidak didukung oleh bukti apa pun yang ditautkan di sini.
Sjoerd
8
@ Sojerd - Klaimnya hampir tidak liar - itu jelas bagi saya, dan seharusnya bagi siapa saja yang memahami perbedaan dalam arsitektur sistem memori default di C / C ++ vs. Java. Anda dapat melakukan jauh lebih baik jika Anda menulis penangan memori Anda sendiri (dengan hal-hal seperti daftar gratis, kumpulan memori, dan sebagainya) atau menggunakan perpustakaan yang mengimplementasikannya.
Rex Kerr
15
@Rex Kerr - Mengapa menggunakan penangan memori jika Anda dapat menggunakan misalnya tumpukan untuk alokasi ?! Anda membingungkan tumpukan alokasi memori dengan instantiation objek.
Sjoerd
20
@Rex Kerr - Pada dasarnya Anda mengklaim bahwa karena segala sesuatu di Jawa melibatkan alokasi memori pada heap, dan karena alokasi Java pada heap di Jawa lebih cepat daripada C ++, semuanya di Jawa lebih cepat. Berikut ini beberapa berita untuk Anda: dalam C ++ Anda dapat melakukannya tanpa mengalokasikan memori pada tumpukan dalam banyak kasus!
Sjoerd
10
@ Soerd - Di mana saya mengatakan bahwa segala sesuatu di Jawa lebih cepat? Baca saja apa yang saya katakan. Saya mengatakan apa yang saya maksud, dan sudah membahas semua yang Anda katakan dalam komentar terakhir Anda.
Rex Kerr
49

Awalnya Jawa tidak terlalu cepat, tetapi juga tidak terlalu lambat. Saat ini, Jawa sangat cepat. Dari orang yang saya ajak bicara kesan Jawa lambat berasal dari dua hal:

  1. Waktu startup VM yang lambat. Implementasi Java awal membutuhkan waktu lama untuk memulai dan memuat pustaka yang diperlukan dan aplikasi dibandingkan dengan aplikasi asli.

  2. UI lambat. Swing awal lambat. Mungkin tidak membantu bahwa sebagian besar pengguna Windows menemukan Metal L&F jelek juga.

Dengan poin-poin di atas, tidak heran orang mendapat kesan 'Java is slow'.

Untuk pengguna atau pengembang yang digunakan untuk mengembangkan aplikasi asli, atau bahkan Visual Basic aplikasi , dua poin ini adalah hal yang paling terlihat dalam suatu aplikasi, dan ini adalah kesan pertama yang akan Anda dapatkan tentang suatu aplikasi (kecuali itu adalah aplikasi non-GUI di mana hanya huruf 1. yang berlaku.).

Anda tidak akan meyakinkan pengguna bahwa "itu mengeksekusi kode sangat cepat" ketika aplikasi membutuhkan 8 detik untuk memulai vs aplikasi Visual Basic tuanya yang segera dimulai - meskipun eksekusi kode dan waktu startup mungkin tidak terhubung sama sekali.

Merusak kesan pertama adalah cara yang bagus untuk memulai rumor dan mitos. Dan rumor dan mitos sulit untuk dibunuh.

Singkatnya, Java tidak lambat. Orang yang memiliki "Java is slow attitude" didasarkan pada kesan pertama tentang Jawa lebih dari 10 tahun yang lalu.

tidak
sumber
3
Java sangat lambat beberapa tahun yang lalu tetapi dalam tes benchmark baru-baru ini berjalan hampir secepat C / C ++ dan dalam beberapa situasi berjalan lebih cepat.
ChadNC
23
Aplikasi Java pada OSX 10.6 di Macbook saya mulai lebih lambat daripada aplikasi yang ditulis di Objective-C. Apa bukti untuk waktu startup yang cepat?
Zan Lynx
2
Dekompresi sama sekali bukan masalah kinerja. Komputer saya pada tahun 1992 dapat dieksekusi yang dapat dieksekusi ketika memulai program yang meningkatkan kinerja dibandingkan memuat file yang lebih panjang dari hard drive. Perbedaan antara CPU dan hard drive telah berkembang pesat selama bertahun-tahun. Namun, ada masalah dengan menggunakan format arsip zip untuk rt.jar (kenapa? !!!) dan file kelas yang terkandung tidak ditautkan (kacang !!).
Tom Hawtin - tackline
5
@ Zan: perhatikan bahwa JVM untuk Mac OS X ditulis (atau setidaknya diadaptasi) oleh Apple. Sun telah menginvestasikan beberapa waktu untuk membuat waktu startup lebih cepat pada platform yang mereka dukung (Windows, Linux dan Solaris), tetapi mereka tidak dapat melakukannya untuk Mac OS x (karena mereka tidak mempertahankan port itu). Mungkin Mac tidak bisa / tidak menerapkan / port semua optimasi ke Mac OS X.
Joachim Sauer
1
Saya tidak menganggap java lambat (saya tahu ada pembuat game yang membuat game di dalamnya); hanya buruk karena alasan UI. Bukan aplikasi java "biasa" tunggal yang pernah saya lihat memiliki UI yang layak dan berfungsi penuh.
RCIX
40

Setelah membaca halaman yang penuh dengan komentar yang mengatakan Java tidak lambat, saya hanya perlu menjawab dengan pendapat yang berbeda.

Kelambatan bahasa sangat tergantung pada apa harapan Anda untuk 'cepat'. Jika Anda menganggap C # terlalu cepat, Java pasti juga cepat. Jika domain masalah Anda terkait dengan database, atau pemrosesan semi-time, Java pasti juga cukup cepat. Jika Anda senang skala aplikasi Anda dengan menambahkan lebih banyak perangkat keras, Java mungkin cepat untuk Anda. Jika Anda menganggap bahwa percepatan faktor konstan dalam skala 5-10 tidak layak, Anda mungkin mempertimbangkan Java dengan cepat.

Jika Anda melakukan perhitungan numerik pada kumpulan data besar, atau terikat pada lingkungan eksekusi, di mana sumber daya CPU terbatas, di mana peningkatan kecepatan konstan dalam skala 5-10 akan sangat besar. Bahkan kecepatan 0,5 mungkin berarti pengurangan 500 jam untuk menyelesaikan komputasinya. Dalam kasus ini, Java tidak memungkinkan Anda untuk mendapatkan halaman kinerja terakhir, dan Anda mungkin menganggap Java lambat.

Sami
sumber
2
setuju, dan memberi +1 pada seluruh pos karena Anda menyajikan poin yang valid, namun, C ++ misalnya memiliki ketenaran yang berbeda karena sulit untuk di-debug, dan mudah meledakkan seluruh kaki Anda, tetapi jarang saya dengar C ++ lambat seperti banyak ketika saya mendengar tentang java.
Stefano Borini
33

Anda sepertinya mengajukan dua pertanyaan yang agak berbeda:

  1. Apakah Java benar-benar lambat, dan jika demikian mengapa?
  2. Mengapa Java dianggap lambat, meskipun lebih cepat daripada banyak alternatif?

Pertanyaan pertama kurang lebih merupakan pertanyaan "berapa panjang tali". Itu datang ke definisi Anda tentang "lambat". Dibandingkan dengan penerjemah murni, Java sangat cepat. Dibandingkan dengan bahasa lain yang (biasanya) dikompilasi ke semacam bytecode, kemudian secara dinamis dikompilasi ke kode mesin (misalnya C # atau apa pun di .NET) Java kira-kira setara. Dibandingkan dengan bahasa yang biasanya dikompilasi dengan kode mesin murni, dan memiliki (sering besar) tim orang yang mengerjakan apa pun selain meningkatkan pengoptimalisasi mereka (mis. C, C ++, Fortran, Ada) Java melakukan beberapa hal dengan sangat baik , tetapi secara keseluruhan cenderung setidaknya agak lambat.

Banyak dari hal ini terkait terutama dengan implementasi - pada dasarnya, ini tergantung pada kenyataan bahwa pengguna sedang menunggu saat kompiler dinamis / JIT berjalan, jadi kecuali Anda memiliki program yang berjalan cukup lama untuk memulainya, itu sulit untuk dibenarkan karena kompiler menghabiskan banyak waktu untuk optimasi yang sulit. Oleh karena itu, kebanyakan kompiler Java (dan C #, dll.) Tidak melakukan banyak upaya untuk optimasi yang sangat sulit. Dalam banyak kasus, ini kurang tentang apa yang dilakukan optimasi, daripada di mana mereka diterapkan. Banyak masalah optimisasi selesai NP, sehingga waktu yang dibutuhkan tumbuh dengan cepat dengan ukuran masalah yang diserang. Salah satu cara untuk menjaga waktu tetap masuk akal adalah dengan hanya menerapkan optimasi pada sesuatu seperti fungsi tunggal pada suatu waktu. Saat itu hanya pengembang yang menunggu kompiler, Anda dapat mengambil lebih banyak, dan menerapkan optimasi yang sama untuk potongan yang jauh lebih besar dari program ini. Demikian juga, kode untuk beberapa optimasi cukup berbulu (dan karenanya bisa sangat besar). Sekali lagi, karena pengguna menunggu sementara kode itu dimuat (dan waktu startup JVM sering merupakan faktor penting dalam keseluruhan waktu), implementasi harus menyeimbangkan waktu yang disimpan di satu tempat vs hilang di tempat lain - dan mengingat betapa sedikitnya kode manfaat dari optimasi berbulu, menjaga JVM kecil biasanya lebih bermanfaat.

Masalah kedua adalah bahwa dengan Java, Anda sering mendapatkan solusi yang lebih atau kurang "satu ukuran cocok untuk semua". Sebagai contoh, bagi banyak pengembang Java, Swing pada dasarnya adalah satu - satunya perpustakaan windowing yang tersedia. Dalam sesuatu seperti C ++, ada lusinan perpustakaan windowing, kerangka kerja aplikasi, dll., Masing-masing dengan kompromi sendiri antara kemudahan penggunaan vs eksekusi cepat, tampilan dan rasa yang konsisten vs tampilan dan nuansa asli, dan sebagainya. Satu-satunya titik pelekatan yang nyata adalah bahwa beberapa (misalnya Qt) bisa sangat mahal (setidaknya untuk penggunaan komersial).

Ketiga banyak kode yang ditulis dalam C ++ (dan C bahkan lebih) hanya lebih tua dan lebih matang. Pada banyak itu berisi inti dari rutinitas yang ditulis beberapa dekade yang lalu, ketika menghabiskan waktu ekstra mengoptimalkan kode itu normal, perilaku yang diharapkan. Itu sering kali memiliki manfaat nyata dalam kode yang lebih kecil dan lebih cepat. C ++ (atau C) mendapatkan kredit untuk kode yang kecil dan cepat, tetapi itu benar-benar lebih merupakan produk dari pengembang dan kendala waktu kode ditulis. Sampai taraf tertentu, ini mengarah pada ramalan yang terpenuhi dengan sendirinya - ketika orang peduli dengan kecepatan, mereka sering memilih C ++ karena memiliki reputasi itu. Mereka menggunakan waktu dan tenaga ekstra untuk optimasi, dan generasi baru kode C ++ cepat ditulis.

Sebagai rangkuman, implementasi Java yang normal membuat optimalisasi maksimal menjadi masalah. Lebih buruk lagi, di mana Java terlihat , hal-hal seperti windowing toolkit dan waktu startup JVM sering memainkan peran yang lebih besar daripada kecepatan eksekusi bahasa itu sendiri. Dalam banyak kasus, C dan C ++ juga mendapatkan kredit untuk apa sebenarnya produk dari hanya bekerja lebih keras dalam pengoptimalan.

Adapun pertanyaan kedua, saya pikir itu sebagian besar masalah sifat manusia di tempat kerja. Beberapa fanatik membuat klaim yang agak meningkat tentang Jawa yang sangat cepat. Seseorang mencobanya, dan menemukan bahwa bahkan sebuah program sepele membutuhkan beberapa detik untuk memulai, dan terasa lambat dan kikuk ketika dijalankan. Sedikit yang mungkin repot menganalisis hal-hal untuk menyadari bahwa sebagian besar dari ini adalah waktu startup JVM, dan fakta bahwa ketika mereka pertama kali mencoba hal-hal, belum ada kode yang dikompilasi - beberapa kode ditafsirkan, dan beberapa disusun sementara mereka menunggu. Lebih buruk lagi, bahkan ketika itu berjalan cukup cepat, tampilan dan rasa biasanya akan terasa asing dan canggung bagi sebagian besar pengguna, jadi bahkan jika pengukuran objektif menunjukkan waktu respon yang cepat, itu masih tampak canggung.

Menambahkan itu bersama-sama mengarah pada reaksi yang cukup sederhana dan alami: bahwa Jawa lambat, jelek dan canggung. Mengingat hype mengatakan itu sangat cepat, ada kecenderungan untuk bereaksi berlebihan dan menyimpulkan menganggapnya sangat lambat, alih-alih (lebih akurat) "sedikit lebih lambat, dan yang sebagian besar dalam keadaan tertentu." Ini umumnya paling buruk bagi pengembang yang menulis beberapa program pertama dalam bahasa tersebut. Eksekusi program "hello world" di sebagian besar bahasa muncul seketika, tetapi di Jawa ada jeda yang mudah terlihat saat JVM dijalankan. Bahkan seorang penerjemah murni yang berjalan jauh lebih lambat di loop ketat dan semacam itu masih akan sering muncul lebih cepat untuk kode seperti ini, hanya karena dapat dimuat dan mulai menjalankan sedikit lebih cepat.

Jerry Coffin
sumber
16

Ini adalah informasi yang ketinggalan zaman sejak awal (pertengahan hingga akhir 1990-an) di Jawa. Setiap versi utama Java telah memperkenalkan percepatan signifikan dibandingkan dengan versi sebelumnya. Dengan Oracle yang tampaknya menggabungkan JRockit dengan JVM Sun untuk Java 7, tren ini tampaknya akan berlanjut.

Dibandingkan dengan banyak bahasa modern populer lainnya (Python, Ruby, PHP), Java sebenarnya jauh lebih cepat untuk sebagian besar penggunaan. Itu tidak cukup cocok dengan C atau C ++ tetapi untuk banyak tugas cukup dekat. Masalah kinerja sebenarnya seharusnya tentang berapa banyak memori yang digunakan.

Dan Dyer
sumber
14

Penyebab utama dalam "waktu mulai yang lama" adalah penautan dinamis. Aplikasi Java terdiri dari kelas yang dikompilasi. Setiap kelas merujuk kelas lain (untuk tipe argumen, pemanggilan metode ...) berdasarkan nama . JVM harus memeriksa dan mencocokkan nama-nama tersebut pada saat startup. Itu melakukannya secara bertahap, hanya mengerjakan bagian-bagian yang diperlukan pada waktu tertentu, tetapi masih ada beberapa pekerjaan yang harus dilakukan.

Dalam aplikasi C, fase penautan tersebut terjadi di akhir kompilasi. Ini lambat, terutama untuk aplikasi besar, tetapi hanya pengembang yang melihatnya. Menautkan menghasilkan file yang dapat dieksekusi yang OS hanya perlu memuat dalam RAM "sebagaimana adanya".

Di Jawa, penautan terjadi setiap saat aplikasi dijalankan. Karena itu waktu startup yang lama.

Berbagai optimasi telah diterapkan, termasuk teknik caching, dan komputer menjadi lebih cepat (dan mereka mendapatkan "lebih cepat" daripada aplikasi menjadi "lebih besar"), sehingga pentingnya masalah telah jauh berkurang belakangan ini; tapi prasangka lama tetap ada.

Adapun kinerja setelah itu, tolok ukur saya sendiri pada komputasi kompak dengan akses array (sebagian besar fungsi hash dan algoritma kriptografi lainnya) biasanya menunjukkan bahwa kode C yang dioptimalkan sekitar 3x lebih cepat daripada kode Java; terkadang C hanya 30% lebih cepat dari Java, terkadang C bisa 4x lebih cepat, tergantung pada algoritma yang diterapkan. Saya melihat faktor 10x ketika kode "C" sebenarnya dirakit untuk aritmatika integer besar, karena 64x64-> 128 oplikasi kode yang ditawarkan prosesor tetapi Java tidak dapat menggunakan karena tipe integer terpanjangnya adalah 64-bit long. Ini adalah kasus tepi. Dalam kondisi praktis, pertimbangan I / O dan bandwidth memori mencegah kode C benar - benar tiga kali lebih cepat daripada Java.

Thomas Pornin
sumber
Hmm ... Saya pikir sebagian besar perpustakaan C secara dinamis terhubung juga saat ini. Atau apakah Anda berbicara tentang sesuatu yang berbeda?
Sean McMillan
4
@Sean: tautan dinamis untuk C muncul untuk "simbol eksternal": fungsi yang digunakan dalam satu DLL dan didefinisikan di yang lain. Aplikasi C yang khas akan menggunakan selusin DLL. Untuk Java dynamic linking terjadi untuk semua metode di semua kelas: ada ribuan yang ada di aplikasi Java yang khas (termasuk perpustakaan standar). Di dunia C, sebagian besar tautan (semua tautan yang tidak melewati batas DLL) diselesaikan pada waktu kompilasi, hanya sebagian kecil yang masih harus dilakukan saat runtime.
Thomas Pornin
14

Java jelas lambat, terutama untuk pekerjaan kuantitatif.

Saya menggunakan kombinasi R , Python dan C / C ++ dengan pustaka ATLAS multithreaded yang dioptimalkan . Dalam masing-masing bahasa ini saya dapat mengalikan matriks 3000 dengan 3000 matriks ganda dengan dirinya sendiri dalam waktu sekitar 4 detik. Menggunakan Colt dan Parallel Colt di Jawa, operasi yang sama membutuhkan waktu 185 detik! Mengagumkan meskipun perpustakaan java ini bersifat paralel.

Jadi semuanya, Jawa murni tidak cocok untuk pekerjaan kuantitatif. Jblas tampaknya menjadi perpustakaan aljabar linear terbaik untuk Java karena menggunakan ATLAS.

Mesin saya adalah HP Core 2 Duo dengan 3 GB RAM. Saya menggunakan Ubuntu 10,04 64-bit (Lucid Lynx).

Hamaad Shah
sumber
Sebagai lanjutan dari komentar saya di atas, saya melakukan operasi penggandaan matriks yang sama menggunakan JAMA dan butuh sekitar 50 detik. Masih terlalu lambat dibandingkan dengan bahasa lain.
Hamaad Shah
7
Berapa lama waktu yang diperlukan Java ketika Anda melakukan perkalian dalam libraires yang dipanggil melalui JNI. Mengingat bahwa apa pun yang dapat Anda lakukan di C / C ++ dapat Anda lakukan dengan JNI (tambahkan beberapa ratus mnano-detik) marginnya relatif kecil. Saya menduga perkalian matriks R dan Python Anda tidak ditulis dalam R atau Python, baru saja dipanggil dari bahasa tersebut.
Peter Lawrey
2
Karena penasaran, apakah Anda sudah melakukan profiling untuk mengidentifikasi jika Anda memiliki beberapa hotspot dalam kode Anda (konversi tipe / autoboxing)?
Thorbjørn Ravn Andersen
10

Untuk pengalaman kebanyakan orang berinteraksi dengan itu - Java adalah lambat. Kita semua telah melihat bahwa cangkir kopi berputar di browser kita sebelum beberapa applet muncul. Butuh beberapa saat untuk memutar JVM dan mengunduh biner applet, dan itu memengaruhi pengalaman pengguna dengan cara yang terlihat.

Itu tidak membantu bahwa lambatnya JVM spin-up dan waktu mengunduh applet secara mencolok dicap dengan cangkir kopi Jawa, sehingga orang mengaitkan penantian dengan Java. Ketika Flash membutuhkan waktu lama untuk memuat, pencitraan merek dari "memuat" ditentukan oleh pengembang Flash, sehingga orang tidak menyalahkan teknologi Flash secara keseluruhan.

Semua ini tidak ada hubungannya dengan kinerja Java di server, atau dalam banyak cara lain yang digunakan Java di luar browser. Tapi itulah yang dilihat orang, dan apa yang diingat pengembang non-Jawa saat mereka memikirkan Java.

Spike Williams
sumber
9

Java memiliki reputasi sebagai lambat karena itu lambat. Versi pertama Java tidak memiliki atau tepatnya kompilasi Just In Time yang buruk. Ini berarti bahwa kode, meskipun bytecode, sedang ditafsirkan, sehingga bahkan untuk operasi yang paling sederhana (seperti menambahkan dua bilangan bulat) mesin harus melakukan segala macam perbandingan dan penunjuk dereferensi dan panggilan fungsi. Kompiler JIT telah terus membaik; sekarang ini pada titik di mana jika saya menulis kode C ++ dengan sembarangan dan kode Java sembarangan, Java kadang-kadang akan mengungguli C ++ karena kompiler JIT menyadari bahwa saya punya beberapa pointer dereferencing yang tidak perlu dan akan mengurusnya untuk saya.

Jika Anda ingin melihat seberapa besar perbedaan kompilasi JIT membuat, periksa tolok ukur ditafsirkan vs non-ditafsirkan di Computer Benchmark Game Computer . (Pidigits menggunakan perpustakaan eksternal untuk melakukan semua perhitungan, sehingga tolok ukur tidak berubah; yang lain menunjukkan percepatan 6-16x!)

Jadi, itulah alasan utamanya. Ada berbagai alasan lain yang lebih kecil yang tidak membantu: pada awalnya, waktu startup Java lambat (sekarang diperbaiki); aplikasi web di Java membutuhkan waktu lama untuk diunduh (apalagi sekarang dengan broadband yang dapat diakses secara luas, dan dengan hal-hal besar seperti film yang diharapkan); Swing UI tidak (dan masih belum) ditulis dengan kinerja dalam pikiran sehingga jauh lebih tajam daripada yang setara dalam misalnya C ++.

Rex Kerr
sumber
6

Java lambat, kembali pada hari itu. Ini telah menjadi jauh lebih cepat, karena beberapa generasi peningkatan kinerja . Terakhir saya dengar, biasanya dalam 10% dari kecepatan C # - kadang lebih cepat, kadang lebih lambat.

Startup applet Java masih lambat karena Anda harus memulai seluruh JVM, yang harus memuat semua kelasnya. Agak seperti boot komputer lain. Setelah JVM dimulai itu cukup cepat, tetapi startup biasanya adalah apa yang orang ingat.

Juga, setidaknya ada beberapa orang yang tidak akan pernah percaya akan kelangsungan hidup Jawa.

Kaleb Brasee
sumber
1
Sayangnya, startup JVM masih jauh lebih lambat daripada startup CLR. Ini karena Sun telah menyeret kakinya dengan cara terburuk dalam melepaskan Java 7, jadi kami terjebak dengan tambalan tambahan ke Java 6 tahun yang ke- 6.
BobMcGee
3
Wow, Java 6 berumur 4 tahun ??? Ya saya kira begitu (jika Anda menghitung beta). Masih terasa baru bagi saya - saya baru saja berhenti menggunakan 1,4 di tempat kerja.
Kaleb Brasee
Java 1.4 dapat digunakan, tetapi agak payah, karena 1,5 dan 1,6 menambahkan banyak peningkatan kinerja dan gula sintaksis. Batas-periksa dan optimasi System.arraycopy diperkenalkan sejak itu. Begitu juga banyak peningkatan sinkronisasi. Saya pikir itu adil untuk mengatakan 1.4 benar-benar lambat.
BobMcGee
LOL, saya tahu - setiap kali saya harus mengulang secara manual atau menggunakan array daripada Daftar generik, saya ingin memecah laptop saya menjadi dua ... IBM sebenarnya memiliki Java 5 tersedia di WS 6.1 selama bertahun-tahun, tapi saya ' telah terjebak pada WAS 6.0 :( Saya telah menggunakan Java 5/6 sejak keluar untuk barang-barang saya sendiri, tetapi saya hanya dibatasi oleh versi server lama di tempat kerja. Ada peningkatan kinerja dua digit persen dari 1,4 ke versi terbaru untuk banyak hal, dan saya menantikannya
Kaleb Brasee
6

Stefano:

Saya telah menggunakan Java sejak awal, jadi dari sudut pandang saya, ketenaran menjadi lambat diciptakan oleh antarmuka GUI yang tidak responsif dan lambat (AWT, dan kemudian Swing) dan di Applets mungkin karena tambahan waktu startup lambat dari VM.

Java telah menetapkan dan mempromosikan banyak penelitian di area VM, dan ada beberapa perbaikan, termasuk pengumpulan sampah (Anda dapat mengatur banyak hal sebenarnya; namun, seringkali saya melihat sistem di mana hanya default yang digunakan) dan hotspot optimasi (yang pada awalnya dan mungkin masih lebih efisien di sisi server).

Java di backend dan tingkat komputasi tidak terlalu lambat. Colt adalah salah satu contoh terbaik:

Rilis stabil terbaru Colt menembus penghalang 1,9 Gflop / s pada JDK ibm-1.4.1, RedHat 9.0, 2x [email protected] GHz.

Ada banyak hal di luar Jawa mainstream yang harus dipertimbangkan, seperti Java Realtime atau mekanisme khusus untuk meningkatkan kecepatan seperti Javolution , serta kompilasi Ahead-Of-Time (seperti gcj). Juga, ada IC yang dapat mengeksekusi Java Bytecode secara langsung, seperti misalnya yang ada di iPhone saat ini dan iPod ARM Jazelle .

Saya pikir pada umumnya hari ini adalah keputusan politik (seperti tidak ada dukungan Java pada iPhone / iPod), dan keputusan melawan Jawa sebagai bahasa (karena banyak yang berpikir itu terlalu bertele-tele).

Namun, ada banyak bahasa lain untuk Java VM saat ini (misalnya Python, Ruby, JavaScript, Groovy, Scala dll.) Yang mungkin menjadi alternatif.

Secara pribadi saya terus menikmatinya sebagai platform yang fleksibel dan dapat diandalkan, dengan ketersediaan alat dan perpustakaan yang sangat baik, yang memungkinkan seseorang untuk bekerja dengan segala sesuatu dari perangkat terkecil (misalnya JavaCard) hingga server terbesar.

Diet
sumber
Ok, jadi reputasi buruk lain datang dari GUI toolkit. Tentu saja saya berasumsi bahwa, karena JVM modern menggunakan widget asli, mereka menghubungkan ke perpustakaan OS, kan? atau apakah mereka menggunakan AWT / Swing untuk membuat tampilan dan nuansa yang sama dari platform host?
Stefano Borini
Stefano: Swing sebenarnya didasarkan pada gagasan render widget universal yang bukan asli, jadi anggapan Anda agak salah. Ini memang mekanisme "pluggable look & feel" yang memungkinkan komponen Swing untuk meniru penampilan komponen asli. Jika Anda mencari sesuatu seperti itu, Anda mungkin ingin memeriksa SWT ( eclipse.org/swt ), yang memang akan menghubungkan ke OS asli dan menggunakan widget asli menggunakan JNI (yang dikatakan sebagai hambatan).
Dieter
Java2D (digunakan untuk Swing) sangat cepat akhir-akhir ini, dan menggunakan widget asli (SWT) tidak memberikan manfaat kinerja. Setidaknya, itulah yang saya baca ketika saya memutuskan apakah akan belajar Swing atau SWT 6 bulan lalu.
Luigi Plinge
4

Palu jauh lebih lambat dalam mengeluarkan adonan daripada banyak alat lainnya. Tidak membuat palu "lebih lambat", juga tidak kurang berguna untuk tugas yang dirancang untuk dilakukan.

Sebagai bahasa pemrograman umum, Java setara dengan banyak (jika tidak sebagian besar) untuk beragam tugas pemrograman. Ada tes khusus dan sepele yang Java tidak akan mengungguli solusi kode tangan dalam bahasa yang kurang canggih, yang "lebih dekat dengan logam".

Tetapi ketika datang ke "aplikasi dunia nyata", Java sering adalah Alat yang Tepat. Sekarang, yang mengatakan, tidak ada yang akan menghentikan pengembang dari membuat solusi berperforma lambat menggunakan alat APA PUN. Penyalahgunaan alat adalah masalah yang sudah diketahui (lihat saja reputasi PHP dan VB). Namun, desain dan sintaksis Java (kebanyakan) memang melakukan banyak hal untuk mengurangi penyalahgunaan.

mobiGeek
sumber
3

Java adalah bahasa tingkat tinggi dan reputasinya saat ini adalah memiliki kinerja yang setara dengan bahasa tingkat tinggi lain yang sebanding.

  1. Ini memiliki semantik yang mengikat dinamis . Dibandingkan dengan C ++ di mana metode non-virtual dikompilasi sebagai pemanggilan fungsi, bahkan kompiler Java terbaik di dunia harus menghasilkan kode yang kurang efisien. Tapi ini juga semantik yang lebih bersih dan tingkat tinggi.

  2. Saya tidak ingat detailnya, tetapi saya mendengar di masa-masa awal Jawa bahwa ada mutex per objek Java, yang akan diperoleh dan dirilis oleh masing-masing metode. Itu cenderung membuatnya lebih baik diadaptasi ke konkurensi, meskipun sayangnya hanya sebuah mutex per objek tidak akan melindungi Anda dari ras atau kebuntuan atau hal-hal buruk yang dapat terjadi dalam program bersamaan. Bagian itu, jika benar, sedikit naif, tetapi itu datang dari niat baik. Silakan mengisi saya dengan detail jika Anda tahu lebih banyak tentang aspek ini.

  3. Cara lain di mana Jawa adalah bahasa tingkat tinggi adalah dengan memiliki Koleksi Sampah . Pengumpulan sampah mungkin lebih lambat daripada mallocdan freeuntuk program yang mengalokasikan sekaligus semua memori yang mereka butuhkan dan bekerja dengannya. Masalahnya adalah, dalam bahasa yang tidak memiliki Pengumpulan Sampah, programmer cenderung menulis hanya program yang mengalokasikan semua memori yang mereka butuhkan sekaligus dan gagal jika ternyata beberapa konstanta ukuran maksimum sewenang-wenang telah dilebih-lebihkan. Jadi perbandingannya adalah apel dengan jeruk. Ketika programmer membuat upaya untuk menulis dan men-debug program dengan alokasi dinamis dari struktur dirantai dalam bahasa non-GC, mereka kadang-kadang menemukan bahwa program mereka tidak lagi lebih cepat daripada dalam bahasa GC, karenamalloc danfreetidak gratis! Mereka memiliki overhead juga ... Plus, tidak memiliki kekuatan GC untuk menentukan siapa yang membebaskan apa, dan harus menentukan siapa yang membebaskan apa pada gilirannya kadang-kadang memaksa Anda untuk membuat salinan - ketika beberapa fungsi akan membutuhkan data dan tidak jelas mana yang akan menggunakannya terakhir - sedangkan penyalinan tidak diperlukan dalam bahasa GC.

Pascal Cuoq
sumber
1. Mungkin tidak benar dengan HotSpot. 2. Hanya jika Anda menandai metode sebagai disinkronkan.
Winston Ewert
1
1. Kompiler tidak mengoptimalkan kode, tetapi JVM cukup pintar untuk secara dinamis menentukan hanya satu atau dua metode virtual yang biasa dipanggil dan dapat memanggilnya secara statis atau bahkan sebariskan. Saya cukup yakin C ++ tidak bisa sebaris metode virtual. 2. Setiap Objek Java memiliki kunci. Ini memiliki overhead kecil (sekitar satu byte) pada setiap objek tetapi memiliki dampak kecil jika tidak digunakan. 3. Di Jawa Anda dapat mengalokasikan sekaligus semua Objek yang Anda butuhkan. Ini bisa memberi Anda aplikasi kaleng yang tidak GC sepanjang hari. ;) Java GC secara implisit multi-threaded, sesuatu yang membutuhkan libraires khusus di C ++.
Peter Lawrey
C ++ dapat sebaris panggilan virtual, tetapi Java dapat melakukannya dalam lebih banyak kasus, dan juga lebih kuat dengan mengoptimalkan situs panggilan megamorphic.
Piotr Kołaczkowski
2

Pada pertengahan tahun sembilan puluhan ketika Jawa mencapai arus utama, C ++ adalah bahasa yang dominan, dan web masih cukup baru. Juga, JVM dan GC adalah konsep yang relatif baru dalam pengembangan arus utama. JVM awal agak lambat (dibandingkan dengan C ++ yang berjalan pada logam kosong) dan juga menderita dari pengumpulan sampah yang kadang-kadang lama, yang menyebabkan reputasi Jawa lambat.

Ken Liu
sumber
apakah ini karena teknologi di balik GC? Saya tahu mereka memiliki beberapa strategi (seperti lapisan generasi untuk objek) agar lebih efisien dalam fase GC. Apa strateginya saat itu?
Stefano Borini
1
IANA JVM ahli, tapi saya pikir pada saat itu ada satu tanda ulir / algoritma sapuan yang digunakan untuk GC, yang mengharuskan seluruh JVM untuk berhenti sementara GC sedang dilakukan. Saat ini ada tanda bersamaan / sapuan dan juga ada banyak peningkatan kinerja lainnya di JVM.
Ken Liu
2
Algoritma GC modern bagus tetapi saya pikir peningkatan terbesar adalah JIT.
Pascal Thivent
1

Banyak aplikasi desktop Java (saat ini: hal-hal seperti Eclipse) memiliki respons GUI yang buruk, mungkin karena konsumsi memori yang tinggi dan fakta bahwa classloader dapat melakukan banyak IO. Ini membaik tetapi lebih buruk beberapa tahun yang lalu.

Banyak (kebanyakan) orang suka melakukan generalisasi sehingga mereka mengatakan "Java lambat" karena mereka menganggap aplikasi lambat ketika mereka berinteraksi dengan mereka.

Wojciech Kaczmarek
sumber
apakah menurut Anda konsumsi memori tinggi berasal dari alat atau dari perpustakaan java?
Stefano Borini
Dalam kasus Eclipse - dari infrastruktur Eclipse itu sendiri. Sama untuk GUI "berat" di masa lalu (JBuilder seingat saya). Saya punya firasat bahwa itu karena banyak objek boilerplate diperlukan untuk menggunakan arsitektur plugin (seperti Eclipse) dalam bahasa yang diketik secara statis. Emacs juga memiliki plugin dan konsumsi memorinya 10-20x lebih sedikit dari Eclipse ketika melakukan pengkodean tipikal. Emacs Lisp code dikompilasi untuk bytecode dan dimuat ke instance emacs, kemudian jalankan - mirip dengan Java classloader. Saya kira di Jawa ada banyak objek antara yang dipakai untuk memungkinkan beberapa plugability.
Wojciech Kaczmarek
1

Masalah utama dengan aplikasi java adalah bahwa hal itu sangat besar karena ukuran besar perpustakaan saham runtime. Program besar mengisi banyak memori dan cenderung untuk bertukar, yang berarti mereka menjadi lambat.

Alasan mengapa Sun JVM besar adalah karena ia memiliki interpreter kode byte yang sangat bagus yang berfungsi dengan melacak banyak hal. Itu berarti banyak data, yang berarti memori.

Anda mungkin ingin melihat mesin virtual jamvm yang merupakan juru bahasa yang cukup cepat (tidak ada kode asli) dan sangat kecil. Bahkan dimulai dengan cepat.

Thorbjørn Ravn Andersen
sumber
1

Seperti kata Pascal, Java setara dengan bahasa tingkat tinggi lainnya. Namun, sebagai seseorang yang bekerja dengan JVM asli pada Windows 98 , pada saat itu tingkat abstraksi yang disediakan oleh mesin virtual Java adalah, harus kita katakan, menyakitkan.

Pada dasarnya, itu adalah persaingan perangkat lunak dengan sedikit atau tanpa optimasi yang kami terima hari ini di JVM.

caskey
sumber
0

Orang-orang biasanya memotong garis "itu ditafsirkan". Karena pada suatu waktu, itu, dan pers yang buruk akan diturunkan oleh orang-orang yang menganggap Jawa 'terlalu lambat' dan tidak pernah kembali untuk menguji versi yang lebih baru.

Atau mungkin "orang bodoh" adalah jawaban yang lebih baik.

Pak Boy
sumber
0

Saya pikir suatu hari, mungkin tidak dalam waktu dekat, bahasa yang dikompilasi JIT akan mengungguli bahasa yang dikompilasi dalam aspek apa pun (yah, mungkin bukan waktu startup / konsumsi memori) karena fakta bahwa kompiler JIT dapat menggunakan runtime secara berat perilaku dan platform yang mereka jalankan.

metode helpermet
sumber
6
Saya pikir apa yang Anda maksudkan adalah bahwa kode JIT yang dikompilasi (tidak ditafsirkan) akan mengalahkan kode AoT. Interpretasi akan selalu lebih lambat daripada menjalankan kode yang dikompilasi. Inilah sebabnya mengapa kompiler JIT digunakan. Tangkapan: ada sedikit perbedaan antara compiler sebelumnya dan kompiler JIT dalam hal output, kecuali bahwa kompiler JIT harus mengkompilasi lebih cepat, dan dapat menggunakan info runtime untuk mengisyaratkan optimasinya. Kompiler AoT khusus platform dengan optimasi platform spesifik hampir selalu mengalahkan JIT karena tidak ada batasan berapa banyak waktu yang dihabiskan untuk optimasi.
BobMcGee
Terima kasih atas jawabannya, tidak pernah memikirkan sedikit waktu yang dimiliki oleh kompiler JIT.
helpermethodhod
maksud Anda, seperti optimisasi adaptif hotspot?
Stefano Borini
2
@ BobMcGee: Sangat benar. Program C ++ dapat dibangun untuk berjalan lambat dengan umpan balik profil untuk semua operasinya. Kemudian kompiler bebas untuk membangun kembali versi yang sangat cepat menggunakan waktu CPU setengah jam dan 2 GB RAM. JIT yang melakukan ini akan membuat pengguna pergi.
Zan Lynx
1
Waktu kompilasi JIT dapat diabaikan untuk aplikasi yang berjalan lama seperti server. AOT dengan PGO lebih terbatas dibandingkan dengan JIT untuk setidaknya 2 alasan. Pertama, sebagian besar perbedaan kinerja dicapai dengan optimisasi ringan. Bandingkan gcc -O2 dengan gcc -O3. Sebagian besar waktu tidak ada perbedaan , kadang-kadang -O3 bisa sedikit lebih baik, kadang-kadang sedikit lebih buruk, tetapi saya tidak pernah mengalami perbedaan> 2x dari ini. Kedua, menggunakan AOT bahkan dengan PGO, Anda hanya bisa menebak profil apa yang akan digunakan di situs-penggunaan. Tebak salah, dan Anda jauh di belakang JIT. Dan profil sebenarnya bisa sangat bergantung pada konfigurasi.
Piotr Kołaczkowski