Java Yavaş mı? : Java’nın Performansı Üzerine – V (Binnur ve Yaşar’ın Yorumları)
Bir önceki yazıda, bu günlüğü takip eden C++ severlerin, C++’ın performans ölçümleriyle ilgili olarak yaptığı itirazlar üzerine, benim ve C++ uzmanı bir arkadaşımın yaptığı yeni ölçümleri yayınlamıştım. Bu son yazıya bilgin ve yetkin arkadaşım Binnur da yorumda bulundu. Bu seriden daha önce yayınlanmış bir başka yazıya yine bilgin ve yetkin bir başka arkadaşım Yaşar da yorumuyla katkıda bulunmuştu. Ben bu yorumları bu yazıda bir araya getirip size topluca sunmak istedim.
Binnur’un Java Yavaş mı? : Java’nın Performansı Üzerine – IV yazısına yorumları:
İlk yorumu:
1. Java kodunun başarımını jmh ile ölçmek daha doğru olurdu. Güzel bir haber: jmh, jdk 9’un içinden hazır çıkacak.
2. -O3 seçeneği ile derleyici kodu en iyiler ancak artık hata ayıklayamazsınız. Kullanılan en iyileme teknikleri durağan tekniklerdir. Derleyici kodun ancak durağan analizini yapabilir ve hızlandırmak için yapabilecekleri bu nedenle kısıtlıdır. Ancak java’da en iyileme kararları yürütme zamanında dinamik olarak verilir. JIT derleyici metodun tek şekilli, iki şekilli ya da çok şekilli olmasına göre değişik en iyileme tekniklerini uygulayabilir. Örneğin tek şekilli bir metodu inline edebilir. Bir metoduntek şekilli, iki şekilli ya da çok şekilli olması yürütme zamanında uygulamanın aldığı şekle göre zamanla değişen bir durumdur. C++’da derleyici virtual tanımlı metodun tek şekilli mi, iki şekilli mi yoksa çok şekilli mi olduğunu bilemez. Bu nedenle virtual tanımlı bir metodu her zaman virtual table üzerinden bağlamak zorundadır. Açıkçası bunu c++ geliştiricisi de bilemez, hatta kaliteli bir nesneye dayalı tasarımda bilmemelidir de. Bu JIT derleyicinin yapabildiklerine ilişkin basit bir örnek. Daha başka bir çok dinamik en iyileme tekniği bulunuyor.
Benim “Ben C++’ın da run-timeda performansını arttırıcı, senin dynamic iyileme (optimization) yapan yapıların geliştirildiğini okumuştum bir yerlerde. Senin bilgi var mıdır? Paylaşabilir misin?” şeklindeki sorum üzerine ikinci yorumu:
1. Profile guided optimization
https://msdn.microsoft.com/en-us/library/e7k32f4k.aspx
2. Burada Java’da yazılmış bir uygulamanın, C++’da yazılmış bir uygulama kadar hızlı koşabildiğini ve bazen de şartlar oluşursa daha hızlı koşabildiğini bilmek gerekir. Kötü bir algoritma seçimini, yanlış bir mimari kararı hangi dilde kodlarsanız kodlayın yavaştır.
3. Tüm popüler diller (Java, C#, Objective C gibi) altta LLVM kullanır: http://llvm.org
Debug jvm edinebilirseniz, LLVM IR’leri konsoldan okuyabilir ve neler olup bittiğini izleyebilirsiniz.
4. C++ tarafında derleyici olarak clang ve intel compiler’ın performansına bakabilirsiniz. Muhtemelen hem VS hem de gcc’den daha iyi sonuç verecektir. C++’da hızlandırma için daha çok eğer algoritma elverişli ise paralelleştirme çözümlerine bakmak gerekir: OpenMP, Cilk, CUDA, OpenCL.
Binnur’un daha önce yayınlamış olduğum Java’nın Performansı: Java Yavaş mı? başlıklı yazıya yaptığı yorumlar:
İlk yorumu:
Selam Akın,
Performans ile ilgili olarak C++ ve Java karşılaştırmanda, tam tersini düşünüyorum. Deneyimsiz C++ ve Java geliştiricisinin yazdığı iki uygulama için, Java uygulamasının daha yüksek başarımla çalışması beklenmelidir. C++11 soyutlama konusunda çok yol aldı. Üstelik seçimlik bir çöp toplayıcımız var. C++’ın dil olarak en üstün tarafı Template ve STL ile sağlanan üretken programlama. Her ikisinin de ortak problemi Heap. Birinde bellekten yer almak yavaş (c++), diğerinde temizlemesi. Java’nın en güçlü yönü, Java dilinin kendisi değil, uygulamaların üzerinde çalıştığı JVM. C++ derleyicisi en fazla durağan en iyileme yapıyor (-O3), Jvm ise devingen en iyileme yapıyor. Dolayısı ile yapabildikleri çok daha fazla.
İkinci yorumu:
Burada ironik bir durum var: JVM, C/C++’da yazılmıştır. Java başarımını bir ölçüde C’ye ve deneyimli C geliştiricilerine borçlu
Şimdi de Yaşar’ın yazdıklarına geçelim. Yaşar’ın bu seriden Java Yavaş mı? : Java’nın Performansı Üzerine – II başlıklı yazıya yaptığı yorum.
Yazdığınız çok doğru. Ufak iki şey yumurtlayasım geldi ama:
1. “Yorumlanan” deyince, doğru, ama yorumlama bir ara seviyede oluyor. Yani, “bytecode” dediğimiz, aslında var olmayan bir makinanın (bir ara yaptılardı sanki ama) komutları (instruction) çalıştırılıyor. Yani, direkt olarak kaynak kod yorumlanmıyor. Çok bir şey farkedeceğinden değil; ancak tamamen yorumlanarak çalışan dillerde, bir derleme adımı olmuyor. Javada ise, işimize de gelen bir derleme adımı var ki, bizi belli açılardan vaktiyle hizaya sokuyor.
Yorum yazıya doğru gidiyor ama, şunu da belirtmek lazım: Dilin yorumlanması veya derlenmesi, bir gerçeklenme problemi. Mesela, Javascript’in tanımında “yorumlanan” lafı geçiyor. Ancak mesela V8 önce derlemeyi tercih ediyor.
2. “Java yavaş mı” sorusunun cevabı, biraz “hadeleyn” civarında. Gerçekten de bu sözlerin doğruluk payı taşıdığı zamanlar, geçen yüzyıldaydı.
Saf Java koduna karşı, saf C kodu durumunda, verdiğiniz örnekler durumu gösteriyor.
İlginçlik, enteresan donanımlarda çıkıyor ortaya. Mesela, GPU kullanımı meselesi var. Paralel veri parçaları üzerinde hesaplama ağırlıklı işler için, GPU, CPU’yu dövüyor. (Bitcoin mining ile uğraşan var mı?) Öyle bir mesele için, JVM içinde bir şey yapmak mümkün olmayabiliyor. Elbette bu tip şeyler için de Java projeleri var. Ancak nihayetinde birinin o “native code”u yazması gerekiyor bir noktada.
Java’nın bugün ulaştığı bu yüksek verimlilik de, yıllar içinde hem derleme optimizasyonları (JIT derlemeden bahsediyorum) hem de muhtelif platformlardaki JVM’lerin daha kaliteli ve altta yatan donanımı daha iyi kullanmasının eseri.
Bunu, zamanında C kodu içine assembler yazılması durumuna benzetiyorum. Linux’un ilk kernel kodlarında, bunlar bol miktarda vardı. Esas sebep, derleme için kullanılan (o zaman tek opsiyon) GCC’nin, o kadar da iyi optimizasyon yapamamasıydı. Modern GCC versiyonlarında, optimizasyonlar o kadar kudretli hale geldi ki, elle GCC’nin ürettiği koddan daha hızlı kod üretmek neredeyse imkansız hale geldi. Kernel kodundaki pek çok assembler kısmı da bu sebepten sökülüp atıldı.
Şimdi aynı vaziyet, Java için gerçekleşiyor. Yani, çok da şaşılacak bir durum yok aslında.
Binnur Kurt veYaşar Safkan’ın yazdıklarına bloglarından ve twitter hesaplarından ulaşabilirsiniz:
- Binnur Kurt’un blogu: http://binkurt.blogspot.com.tr/ ve Twitter hesabı: https://twitter.com/bnnrkrt
- Yaşar Safkan’ın blogu: http://www.safkan.org/blog/ ve Twitter hesabı: https://twitter.com/yasarsafkan
Okumak güzeldir. Bileni okumak daha güzeldir.
Bol okumalar 🙂
Toplam görüntülenme sayısı: 909
Volkan Kalpakçı
04 Aralık 2015 @ 22:33
Verdiğiniz eğitimlerden birinde paylaşmıştınız. JVM’de çalışabilir Java dışında dillerde de yazmak mümkün demiştiniz. Java harici dil ile bu tip bir yazımın hıza olumlu olumsuz etkisi olur mu sizce?
Akin
06 Aralık 2015 @ 11:52
Doğru söylüyorsunuz Volkan bey. En bilinenleri Groovy ve Scala olmak üzere pek ok JVM dili var. Ama bu dillerin performansları, o dillerin bazı özelliklerinen dolayı Java seviyesinde değil genelde. Çok da gerekli mi tartışılır çünkü dilleri kullanarak baştan sona bir sistem geliştirmek yerine, muhtemelen büyük bir sistemin bazı ihtiyaçlarını gidermek için kullanırsınız.
Ufak bir örnek için şu linklere bakabilrisiniz:
http://wiki.jvmlangsummit.com/images/8/8c/Theodorou_Groovy.pdf Bu linkteki malzeme Groovy’nin performansı üzerine ve detaylı bilgi veriyor.
https://dzone.com/articles/java-7-vs-groovy-21 ve http://www.drdobbs.com/jvm/the-groovy-conundrum/240147731 ve ilk cümlesine bakın: “Groovy is one of the most interesting JVM languages, but its longtime performance issues kept it confined to narrow niches.” Bu yazıda iddia edilen şey, kötü bir çocukluk geçirmiş olan Groovy’nin performans gibi kötü çocukluktan gelen problemleri aşılırsa daha büyük rollerde yer alabileceği.
Teşekkür ederim.