2015-01-04 4 views
1

Я работал над проблемами проекта Эйлера, когда я наткнулся на this problem. Я написал программу, которая решает ее правильно в Ruby On Rails (новое в языке):Почему Ruby намного медленнее, чем Java?

class Collatz 
def search 
    counter = 0 
    storage = 0 
    amount = 0 
    (1..1000000).each do |i| i += 1 
     temp = i 
     while temp != 1 
     temp = temp & 1 == 1 ? 3 * temp + 1 : temp >> 1 
     counter += 1 
     end 
     if counter > amount 
     amount = counter 
     storage = i 
     end 
     counter = 0 
    end 
    puts storage 
    end 
end 

start = Time.now 
collatz = Collatz.new 
collatz.search 
ending = Time.now 
puts "Time: #{ending - start}" 

я понял, что это занимает очень много времени, 15.185317 секунд, чтобы быть точным. Когда я пытаюсь Java, однако, время гораздо короче:

public class Euler{ 

    private static void problem() { 
     long a; 
     int j; 
     int max = 0; 
     int maxnr = 0; 
     for(int i = 1; i < 1000000; i++) { 
      a = i; 
      j = 1; 
      while(a != 1) { 
       a = ((a & 1) == 1) ? (3 * a + 1) : (a >> 1); 
       j++; 
      } 
      if(j > max) { 
       max = j; 
       maxnr = i; 
      } 
     } 
     System.out.println(maxnr); 
    } 

    public static void main(String[] args) { 
     long ct = System.currentTimeMillis(); 
     problem(); 
     long nt = System.currentTimeMillis() - ct; 
     System.out.println(nt); 
} 

В конце концов эта программа приобрела 769 миллисекунд. Я использую RubyMine для Ruby и Intellij IDEA для Java. Я не могу понять, почему это так долго, и я не уверен, нормально это или нет. Задача не кажется слишком сложной, поскольку я просто зацикливаюсь.

+1

Я не знаю много о рубиновом исполнении, но для Java JVM имеет JIT (Just In Time), который улучшает производительность исполняемого кода и улучшает его больше, когда код выполняется несколько раз. –

+0

Вы не можете сравнивать один аспект языка, измеряя его (плохо). Сравнение тестов двух методов в одной и той же программе (и языке) уже достаточно сложно сделать правильно. –

+0

Какие реализации Ruby и Java вы использовали? Существуют огромные различия в производительности между различными реализациями Java и Ruby. Вы объяснили разминку JIT? (Это не похоже на ваш тестовый код.) Вы убедились, что ваши результаты статистически достоверны и значительны? Обратите внимание, что есть причина, по которой тесты написаны профессиональными разработчиками тестов: потому что * невероятно трудно писать хороший ориентир и, по крайней мере, так же трудно правильно интерпретировать его результаты. –

ответ

3

Ваше решение этой проблемы довольно плохое. Это предполагает выполнение огромного количества дублирующих работ. Видимо, JVM намного лучше оптимизирует эту избыточную работу, чем Ruby.

Однако, если вы напишете правильное решение, которое явно использует предыдущую работу, вы обнаружите, что неважно, запустите ли вы его на Ruby или Java. Вы можете сделать это, используя массив или карту для хранения предыдущих результатов. Этот метод также известен как динамическое программирование.

+0

Одна из вещей, на которой работает JVM, - оптимизация избыточной работы. –

Смежные вопросы