Java Yavaş mı? : Java’nın Performansı Üzerine – III
Bir önceki yazıdan devam edelim ve şimdi de Monte Carlo simulasyonu ile PI’ye yakınsamayı ele alalım.
Önce MonteCarloPI.cpp
/* * File: MonteCarloPI1.cpp * Author: akin * * Created on October 7, 2015, 12:39 AM */ #include <iostream> #include <stdlib.h> #include <ctime> namespace MonteCarloPI1 { using namespace std; int n; int main() { cout.precision(10); int dotsInCircle = 0; cout << "Number of points: " << endl; cin >> n; clock_t start = clock(); for (int i = 0; i < n; i++) { double x = static_cast<double> (rand()) / static_cast<double> (RAND_MAX); double y = static_cast<double> (rand()) / static_cast<double> (RAND_MAX); double distance = x * x + y * y; if (distance <= 1.0) dotsInCircle++; } clock_t end = clock(); int time = (int) (1000 * (end - start) / CLOCKS_PER_SEC); double myPi = (double) 4 * dotsInCircle / n; cout << "My PI is: " << myPi << endl; cout << "Time is: " << time << " ms." << endl; return 0; } }
ve şimdi de MonteCarloPI.java
package org.javaturk.performance.algorithm.pi; import java.util.Scanner; import org.apache.commons.math.random.BitsStreamGenerator; import org.apache.commons.math.random.MersenneTwister; /** * Monte Carlo simulation to get closer to PI. It uses MersenneTwister to * produce random numbers. The implementation of this algorithm comes with * Apache's commons Math library. * * @author akin * */ public class MonteCarloPI { private static long n; private static BitsStreamGenerator randomData = new MersenneTwister(); public static void main(String[] args) { System.out.println("*** MonteCarloPI2 ***"); System.out.print("Number of points: "); Scanner in = new Scanner(System.in); n = in.nextLong(); calculatePI(); } public static void calculatePI() { int dotsInCircle = 0; double start = System.currentTimeMillis(); for (int i = 0; i < n; i++) { double x = randomData.nextDouble(); double y = randomData.nextDouble(); double distance = x * x + y * y; if (distance <= 1) dotsInCircle++; } double finish = System.currentTimeMillis(); double seconds = (finish-start); double myPI = (double) 4*dotsInCircle/n; System.out.println("My PI is: " + myPI + " and Java's PI is: " + Math.PI); System.out.println("Time is: " + seconds); } }
Monte Carlo simulasyonu ile PI’ye yakınsamak görüldüğü gibi çok daha basit ama çok güzel bir algoritmadır. Random veri oluşturmak dışında son derece basit bir for bloğu içinde bir if cümleciğinden oluşuyor. Random veri için Java’da Apache Commons Math’de bulunan MersenneTwister gerçekleştirmesini kullandım. Buna karşın C++’daki random veri üretimi ise standart kütüphanedeki gerçekleştirmeyi kullandım. Bu farklılığın performansa etkisinin ne kadar olacağını pek kestiremiyorum şu anda, daha fazla araştırmak gerekli.
Bu programın MacBook Pro’mdaki ölçümleri ise şöyle:
Program | 10^6 | 10^7 | 10^8 | 10^9 | 2*10^9 |
MonteCarloPI.java | 38 | 296 | 1,637 | 24,329 | 50,486 |
MonteCarloPI.cpp | 21 | 214 | 2,404 | 33,898 | 81,899 |
Bu ölçümlerin de bir önceki SieveOfAtkin‘deki ölçümleri destekliyor olduğu açıktır.
Bu ölçümlerde bir şey dikkatinizi çekiyor mu? Girdi sayısı artarken performans ölçümlerinin Java lehine değişiyor olması bir tesadüf müdür acaba?
Toplam görüntülenme sayısı: 636
İslam Yaşar
27 Ekim 2015 @ 17:03
Öncelikle elinize sağlık, sonrasında C++ kodunu derlerken hangi derleyiciyi kullandınız, optimizasyon yaptınız mı ? Bu tarz ince nüanslar çok farkediyor C++ dünyasında java gibi tek bir JVM üzerinden dönmüyor bütün numaralar hocam ufak nüanslar çok farkediyor.
C++ kodunuzu derledim ve çalıştırdım sonuçlar şöyle: Kodunuzu g++ 4.8.4 ile derledim:
g++ -O3 -std=c++11 -o montecarlo main.cpp
10^8 için 1.481 s
10^9 için 14.885 s
2 * 10 ^9 için 29.286 s
Görüldüğü üzere ciddi farklar var. C++ ‘ ın performans gücünün önemli bir kısmı derleyicilerinin çok güçlü olmasından kaynaklanıyor. Ve sonuç olarak Java hala çok yavaş 🙂
java değerlerini de paylaşıyorum:
10^8 -> 2.310
10^9 -> 22.994
2*10^9 -> 45.921
Neredeyse Java yarı yarıya yavaş, bence bu tarz tartışmalar yerine programlama dillerinin kendi alanlarında güçlü olduğu konularda pazar olarak dünyayı hedefleyen yazılımlar için efor sarfetmek daha faydalı olacaktır. Türkiyeden örnek olarak Hazelcast verilebilir Java konusunda.
Akin
27 Ekim 2015 @ 18:11
İslam bey ilginiz için teşekkür ederim. Ama şunu belirtmeliyim ki eğer benim Java’nın C++’tan daha hızlı oldugunu göstermeye çalıştığımı dusunuyorsanız yazılarımı okumamıssınız, sdece iki tane tablodaki sonuclara bakmısınız demektir. Ben dil olarak Java’nın yavaş olmadıgını iddia ediyorum, C++’tan daha hızlı oldugunu degil. Zaten ben yazıda elde ettiğim sonucların “durumsal” oldugunu da ifade ettim. O sonuclardan yola cıkarak Java C++’tan hızlıdır denemeyeceği gibi sizin sonuclarınızdan yola cıkarak “Java hala yavas” da denemez. Kaldı ki aslolan uygulamanın performansıdır ki oraya henüz gelmedim.
Ote taraftan “bence bu tarz tartışmalar yerine programlama dillerinin kendi alanlarında güçlü olduğu konularda pazar olarak dünyayı hedefleyen yazılımlar için efor sarfetmek daha faydalı olacaktır. ” diyorsunuz. Sanırım siz bu dunyada yenisiniz. Bu tartışmalar taa Java’nın ilk günlerinden bu yana vardır ve hala da devam eder. Bazı şirketlerin “Java yavas o yuzden Xxx’e gectik” dedikleri bir ülkede bu konuya kapsamlı ve uygulamalı bir sekilde yaklaşmak gereklidir diye düşünüyorum.
Selamlar,
Orhan Ozalp
28 Ekim 2015 @ 01:47
Merhaba,
Kodları ben de kendi bilgisayarımda çalıştırdım, her durumda C++’ın daha iyi sonuç aldığını gördüm. Hatta eşit olması için C++11’de gelen mersenne twisterı kullanarak da denemeler yaptım ama Java her seferinde daha yavaş çıktı. Bu sonuçları aldığınız konfigürasyonları da yazabilir misiniz? (hangi jvm, c++ derleme flaglari gibi)
Akin
05 Kasım 2015 @ 12:57
Orhan bey ilginize tesekkür ederim. Yakında devam eden yazılarda bu bilgileri daha ayrıntılı bir şekilde yayınlayacagım. Ama su an için 2. yazıda kısaca bahsettiğim configurasyon bilgisini bir daha vereyim:
16 GB RAM ve 8 çekirdekli i7 CPU’ya sahip, üzerinde El Capitan OS çalışan MacBook Pro
8 GB RAM ve 8 çekirdekli i7 CPU’ya sahip, üzerinde Windows 10 çalışan PC
Bu iki programı çalıştırmak için Mac’de Java için JDK 1.8.0_25 JVM, C++ için de XCode 7.1 kullanılmıştır. (XCode 7.1 varsayılan durumda C++ derleyicisi olarak gcc (GCC) 4.2.X kullanıyor. Ben bgunlerde en son surume yukselttim dolayısıyla artık gcc (GCC) 4.9.2 var ama bu surumle olcumleri tekrarlamadım.)
Çalışma zamanı için tamamen varsayılan yapılar kullanılmış, hiç bir parametre/flag verilmemiştir.
şamil
13 Kasım 2015 @ 23:48
İkisinin de yeri farklı, karşılaştırmanın pek doğru olmadığını düşünüyorum ben.
Akin
02 Aralık 2015 @ 17:42
Şamil bey selam,
Java performans açısından devamlı C/C++ ile karşılaştırılır. Java’nın ilk çıktığı günden bu yana bu böyledir.
Zaten yaptığımız karşılaştırma “ikisinin de yeri farklı” ile itiraz edilemeyecek bir karşılaştırma. Genel olarak sorualcak “Java ile C++’ı karsılastıralım mı?” sorusuna “İkisinin de yeri farklı, karşılaştırmanın pek doğru olmadığını düşünüyorum ben.” diye cevap verebilirsiniz. Ben de aynı fikirdeyim, ikisinin de yeri ayrı. Ama benim cevap aradığım soru bu değil, “Java yavaş mı?” sorusuna cevap veriyorum ben.
İlginize teşekkür ederim.