Подтвердить что ты не робот

Почему это решение GoLang быстрее, чем эквивалентное решение Java?

Недавно на работе мы играли со следующим вопросом викторины, заданным IBM https://www.research.ibm.com/haifa/ponderthis/challenges/May2015.html

После нескольких усилий коллега и я пришли к двум решениям: один в GoLang https://gist.github.com/walesey/e2427c28a859c4f7bc920c9af2858492#file-main-go-L57, а другой в Java https://gist.github.com/boyter/42df7f203c0932e37980f7974c017ec5#file-puzzle-java-L63 с критическим для производительности способом как для игр в Java, так и для игры в GoLang (оба связаны выше).

Программа Go - это почти буквальная копия Java, но ее время выполнения составляет ~ 6 секунд, тогда как Java составляет около ~ 26 секунд (на моей локальной машине). Аналогичные номера были воспроизведены на нескольких других машинах с программой Go примерно на 5 раз быстрее.

Программа Go скомпилирована с использованием 1.7.5 и Java с использованием версии 1.8.0_65, работающей на macOS Sierra 10.12.3 на сетчатке MacBook Pro конца 2013 года с процессором i5 с частотой 2.6 ГГц.

Почему программа Go в 5 раз быстрее, чем Java, когда большинство тестов указывают на то, что Java должна иметь одинаковую рабочую среду? Это просто базовая математика в цикле, поэтому кажется, что они должны работать примерно в одно и то же время. Я мог понять секунду или около того для начала запуска JVM, но это кажется выключенным.

Обе программы используют почти тот же цикл. Все возможные перестановки результатов игры создаются и повторяются для каждой начальной суммы денег. Просто кажется, что для любого числа циклов в основном цикле, что Go запускает кольца вокруг Java.

Я понимаю, что это "микро" бенчмарк, но мне интересно, почему именно код Go значительно превосходит Java-код. Это просто, что Go для простых циклов/математики более эффективен и, следовательно, быстрее? Может ли он развернуть цикл, возможно (хотя это вряд ли приведет к такой огромной разнице)?

Если не так, как вы должны структурировать Java-программу, чтобы получить максимальную производительность из простой операции цикла и математики?

EDIT. Благодаря Dolda2000 я изменил версию Java. Теперь это примерно такая же скорость, как и версия GoLang. В самом деле, проблема заключалась в том, что игры были созданы, в результате чего версия Java должна была имитировать больше игр, чтобы определить, достаточно ли продолжилась игра. С изменениями он работает примерно через ~ 6 секунд и восстановил мою веру в Java.

Обновить. Вот расширенный эссе в котором более подробно обсуждается предыстория этого вопроса.

4b9b3361

Ответ 1

Как оказалось, ваши программы не настолько равны, как вы полагаете. Я измерил их, чтобы посмотреть, сколько игр (то есть отдельных раундов ставок) имитировали, а в то время как версия Go смоделировала 1 612 629 805 игр, версия Java смоделировала 12 323 903 502 игр, почти на порядок больше.

На моей машине, отключив многопоточность для получения более предсказуемых результатов, программа Java начала работать примерно на 75 секунд, а программа Go - на 12,5 секунды. Сопоставив это с общей продолжительностью выполнения, кажется, что Java-программа на самом деле немного быстрее для имитируемой игры примерно на 6,1 нс по сравнению с 7,8 нс для программы Go.

Не уверен, почему они имитируют такое огромное количество игр. Возможно, способ, которым генерирует раунд, просто случается, чтобы найти гораздо более быстрые окончания.

EDIT: На самом деле, это последнее предположение имеет большой смысл. Версия Go начинается с модуляции начальных раундов игры, в то время как Java-версия начинается с модуляции последних раундов игры (другими словами, просмотр списка раундов в виде списка увеличивающих 11-значный base-3 номера, версия Go малозначительна, в то время как версия Java является, как говориться, большой, так что Java-версия должна будет имитироваться через намного более идентичные начала, чтобы добраться до вариантов, которые заканчиваются. Я не пытался проверить эту гипотезу, но я уверен, что я не чувствую необходимости.