Почему Go такой медленный (по сравнению с Java)?

109

Как мы могли видеть из игры The Computer Language Benchmarks Game в 2010 году:

  • Go в среднем в 10 раз медленнее, чем C
  • Go в 3 раза медленнее Java !?

Как это может быть, учитывая, что компилятор Go создает для исполнения собственный код?
Незрелые компиляторы для Go? Или есть какая-то внутренняя проблема с языком Go?

РЕДАКТИРОВАТЬ:
Большинство ответов отрицают внутреннюю медленность языка Go, утверждая, что проблема заключается в незрелых компиляторах.
Поэтому я сделал несколько собственных тестов для вычисления чисел Фибоначчи : Итерационный алгоритм работает в Go (freebsd, 6g) со sameскоростью, как в C (с опцией O3). Тупая рекурсивная работает в Go 2 timesмедленнее, чем в C (с опцией -O3; с -O0 - то же самое). Но я не видел 10-кратного падения, как в игре Benchmarks.

Олег Разгуляев
источник
36
Честно говоря, C - это замаскированный ASM, а в Java в наши дни есть некоторые серьезные оптимизации.
Мэтью Шарли,
16
Возможно, тест также не отражает сильные стороны Go. Возможно, другие тесты на самом деле быстрее этого. Кроме того, часто важнее всего не производительность, а удобочитаемость кода.
extraneon
7
@extraneon: Согласен. Помните, что Go разработан для Google, и Google обычно запускает код на 2 миллионах ядер. Думаю, в Benchmarks Game используется всего 4 ядра.
Jörg W Mittag
4
@extraneon: Я согласен в целом, но Go был специально разработан с учетом скорости, например, «получающиеся программы работают почти так же быстро, как сопоставимый код C или C ++».
shosti
4
Ваш вопрос предполагает слишком многое: «Большинство ответов отрицают внутреннюю медлительность языка Go» - это неправильная фраза для использования в вопросе. У вас есть вопрос или заявление? Пожалуйста, посетите c2.com/cgi/wiki?HostileStudent, чтобы понять вашу ошибку.
Крис

Ответы:

102

Компиляторы 6g и 8g не особо оптимизируются, поэтому код, который они создают, не особенно быстрый.

Они предназначены для быстрой работы и создания приемлемого кода (есть небольшая оптимизация). gccgoиспользует существующие проходы оптимизации GCC и может обеспечить более содержательное сравнение с C, но gccgo еще не завершен.

Контрольные цифры почти полностью отражают качество реализации. Они не имеют большого отношения к языку как таковому, за исключением того, что реализация тратит время выполнения на поддержку языковых функций, которые на самом деле не нужны тесту. На большинстве скомпилированных языков достаточно умный компилятор теоретически может исключить то, что не нужно, но наступает момент, когда вы настраиваете демонстрацию, поскольку очень немногие реальные пользователи языка будут писать программы, которые не используют эту функцию. . Убирать вещи с пути, не удаляя их полностью (например, предсказывать назначения виртуальных вызовов в JIT-скомпилированной Java), становится непросто.

FWIW, мой собственный очень тривиальный тест с Go, когда я смотрел на него (в основном, цикл сложения целых чисел), gccgo произвел код в направлении быстрого конца диапазона между gcc -O0и gcc -O2для эквивалентного C. Go по своей сути не медленный, но компиляторы еще не все делают. Это не удивительно для языка, которому 10 минут.

Стив Джессоп
источник
7
Более того, может оказаться, что программы Go в The Computer Language Benchmarks Game не так оптимизированы, как программы C и Java.
el.pescado
А как насчет между gcc -O0 и gcc -O3? Есть ли вообще намерение, что компиляторы «все сделают»?
igouy
@igouy: ну, я почти уверен, что gccgo намерен выполнять сборку мусора, чего в настоящее время нет. Есть еще некоторые функции, которые нужно включить в компиляторы g, например, в настоящее время они не очень хорошо используют потоки хоста (в частности, планировщик goroutine не является упреждающим). Кроме того, я не знаю планов Google, будут ли компиляторы g когда-либо усиленно оптимизироваться, или только gccgo.
Стив Джессоп,
1
@xitrium: Я думаю, что цель Go состоит в том, что реализации не должны планироваться совместно, они могут упреждать, если хотят. См., Например, code.google.com/p/go/issues/detail?id=543 , который не был закрыт как «бессмысленный, исправление этой так называемой ошибки противоречило бы определению языка Go», что должно быть, если Реализациям Go запрещено упреждать :-) Проблема усугублялась тем фактом, что по умолчанию Go использовал только один поток хоста, независимо от того, сколько горутин было запущено.
Стив Джессоп,
6
На данный момент ответ может быть немного устаревшим. Недавно была выпущена первая бета-версия Go 1.1 , в которой утверждается, что производительность скомпилированных программ увеличивается примерно на 30-40%. Кто-нибудь, пожалуйста, сделайте эти тесты еще раз.
fuz
51

В следующем выпуске Go FAQ должно появиться что-то похожее на следующее.

Производительность

Почему Go плохо справляется с тестом X?

Одна из целей разработки Go - приблизиться к производительности C для сопоставимых программ, но в некоторых тестах он работает довольно плохо, в том числе в нескольких тестах / тестах. Самый медленный зависит от библиотек, для которых версии с сопоставимой производительностью недоступны в Go. Например, pidigits зависит от математического пакета с множественной точностью, а версии C, в отличие от Go, используют GMP (который написан на оптимизированном ассемблере). Тесты, которые зависят от регулярных выражений (например, regex-dna), по сути сравнивают пакет регулярных выражений Go с зрелыми, высоко оптимизированными библиотеками регулярных выражений, такими как PCRE.

Тестовые игры выигрывают благодаря обширной настройке, и версии большинства тестов для Go требуют внимания. Если вы измеряете сопоставимые программы C и Go (одним из примеров является обратное дополнение), вы увидите, что эти два языка намного ближе по сырой производительности, чем показывает этот набор.

Тем не менее, есть возможности для улучшения. Компиляторы хороши, но могли бы быть лучше, многим библиотекам требуется серьезная работа с производительностью, а сборщик мусора еще недостаточно быстр (даже если бы это было так, стараясь не генерировать ненужный мусор, может иметь огромный эффект).

А вот еще несколько подробностей об игре Computer Benchmarks Game из недавней ветки списка рассылки.

Сборка мусора и производительность в gccgo (1)

Сборка мусора и производительность в gccgo (2)

Важно отметить, что Computer Benchmarks Game - это просто игра. Люди с опытом измерения производительности и планирования мощностей тщательно сопоставляют подобные с более реалистичными и реальными рабочими нагрузками; они не играют в игры.

Питер
источник
1
И вот некоторые подробности из той же ветки,
igouy
3
Важно отметить , что «тесты являются черепок» - не только тесты , опубликованные как игровые тесты - shootout.alioth.debian.org/flawed-benchmarks.php
igouy
18
(и все ...) Конечно, это «игра» , но когда я вижу, что Go всего в два раза медленнее, чем самый быстрый в этих тестах, мое первое впечатление - «вау, Go кажется быстрым» , потому что я знаю, что эти тесты ущербный. Напротив, когда я вижу, что Ruby в 65 раз медленнее, чем самый быстрый, я думаю, что «не буду использовать Ruby в своих следующих усилиях, требующих большого количества одновременных вычислений» . Так что это может быть «игра», но в ней есть доля правды, если относиться к ней с недоверием.
SyntaxT3rr0r
Планирование мощностей имеет очень важный аспект: стоимость. Нужны ли вам коробки X или 2 * X, в конечном итоге имеет огромное значение. А поскольку никто не может точно оценить, что будет с ними работать в будущем, лучше всего взглянуть на различные рабочие нагрузки. Я проверил несколько их реализаций и обнаружил, что они в основном в порядке. Думаю, результаты можно использовать как основу для оценок.
Агостон Хорват,
Как правило, реальные системы ограничены вводом-выводом, а не процессором. Следовательно, будет ли Go в 2 раза медленнее или в 5 раз медленнее, вряд ли имеет такое большое значение для планирования емкости, как переключение при отказе, балансировка нагрузки, кэширование, топология базы данных и тому подобное. Вот почему приложения масштаба YouTube могут позволить себе запускать многие из своих систем на Python.
Суджой Гупта,
34

Мой ответ не такой технический, как у других, но я думаю, что он все еще актуален. Я видел те же тесты в игре Computer Benchmarks Game, когда решил начать изучать Go. Но я честно считаю, что все эти синтетические тесты бессмысленны с точки зрения определения того, достаточно ли быстр Go для вас.

Недавно я написал сервер сообщений на Python, используя Tornado + TornadIO + ZMQ, и для своего первого проекта Go я решил переписать сервер на Go. До сих пор, после того как сервер получил ту же функциональность, что и версия Python, мои тесты показывают мне примерно 4,7-кратное увеличение скорости в программе Go. Имейте в виду, я кодирую на Go всего неделю, а на Python - более 5 лет.

Go будет только становиться быстрее по мере того, как они продолжают работать над ним, и я думаю, что на самом деле все сводится к тому, как он работает в реальном приложении, а не к маленьким маленьким вычислительным тестам. Для меня Go, по-видимому, привел к более эффективной программе, чем то, что я мог создать на Python. Таков мой ответ на этот вопрос.

jdi
источник
3
Как вы думаете, насколько медленнее вы будете писать код Go, чем Python?
Эрик Энгхейм
7
@AdamSmith - Я бы сказал, что буду писать код Go медленнее, чем Python, только потому, что я кодировал Python более 7 лет и только немного на Go. Но что касается Go по сравнению с другими статически типизированными компилируемыми языками, держу пари, что я напишу Go быстрее, чем другие. Лично мне кажется, что это больше всего
похоже
5
У меня похожая история. Я только начал изучать Go, и, согласно Benchmarks Game, Go МЕДЛЕЕ, чем JavaScript V8. Оказывается, моя программа, которая интенсивно использует двоичные операции, работает в 10 раз быстрее с неоптимизированным кодом Go, чем в высокооптимизированной виртуальной машине V8. Go может быть медленнее, чем C во многих операциях, однако никто не пишет веб-сайты на C. Go уже является вполне жизнеспособным вариантом и должен только улучшаться по мере появления новых библиотек, фреймворков и инструментов.
если __name__ равно None
1
@ user962247 это безумное и ложное заявление. Я пишу Go уже много лет, и он очень быстро работает. Никто не утверждает, что он превзойдет C / C ++ / Java во всех возможных синтетических тестах. Но в некоторых он выигрывает (см. Сайт с тестовой игрой). Возьмите это у человека, который годами писал производственный код Go. Это быстро и продуктивно.
jdi
6

Времена изменились.

Я думаю, что текущий правильный ответ на ваш вопрос - это опровергнуть представление о том, что идти медленно. На момент вашего запроса ваше суждение было оправданным, но с тех пор go значительно расширился с точки зрения производительности. Теперь он по-прежнему не так быстр, как C, но в общем смысле он далеко не в 10 раз медленнее.

Игра компьютерных языковых тестов

На момент написания:

source  secs    KB      gz      cpu     cpu load

reverse-complement
1.167x
Go      0.49    88,320  1278    0.84    30% 28% 98% 34%
C gcc   0.42    145,900 812     0.57    0% 26% 20% 100%

pidigits
1.21x
Go      2.10    8,084   603 2.10    0% 100% 1% 1%
C gcc   1.73    1,992   448 1.73    1% 100% 1% 0%

fasta
1.45x
Go      1.97    3,456   1344    5.76    76% 71% 74% 73%
C gcc   1.36    2,800   1993    5.26    96% 97% 100% 97%

regex-dna
1.64x
Go      3.89    369,380 1229    8.29    43% 53% 61% 82%
C gcc   2.43    339,000 2579    5.68    46% 70% 51% 72%

fannkuch-redux
1.72x
Go      15.59   952 900 62.08   100% 100% 100% 100%
C gcc   9.07    1,576   910 35.43   100% 99% 98% 94%

spectral-norm
2x
Go      3.96    2,412   548 15.73   99% 99% 100% 99%
C gcc   1.98    1,776   1139    7.87    99% 99% 100% 99%

n-body
2.27x
Go      21.73   952 1310    21.73   0% 100% 1% 2%
C gcc   9.56    1,000   1490    9.56    1% 100% 1% 1%

k-nucleotide
2.40x
Go      15.48   149,276 1582    54.68   88% 97% 90% 79%
C gcc   6.46    130,076 1500    17.06   51% 37% 89% 88%

mandelbrot
3.19x
Go      5.68    30,756  894 22.56   100% 100% 99% 99%
C gcc   1.78    29,792  911 7.03    100% 99% 99% 98%

Тем не менее, он сильно пострадал в тесте двоичного дерева:

binary-trees
12.16x
Go      39.88   361,208 688 152.12  96% 95% 96% 96%
C gcc   3.28    156,780 906 10.12   91% 77% 59% 83%
tiffon
источник
Теперь он находится на одном уровне с Java, но разве Go не создавался явно для того, чтобы быть быстрее, чем Java, и при этом использоваться для тех же вещей (сетевые приложения на стороне сервера)?
MaxB
1
@MaxB нет, он не был создан с целью быть быстрее, чем Java. Он был создан с целью обеспечения хорошей производительности, более быстрой компиляции, чем C ++, а также более простого и встроенного параллелизма, чтобы позволить разработчикам быть более продуктивными. Превышение скорости выполнения других языков не было решающим фактором.
jdi
5

Несмотря на не очень хорошую эффективность Go в отношении использования циклов ЦП, модель параллелизма Go намного быстрее, чем, например, модель потоков в Java, и может быть сопоставима с моделью потоков C ++.

Обратите внимание, что в тесте thread-ring Go был в 16 раз быстрее, чем Java. В том же сценарии Go CSP был почти сопоставим с C ++, но использовал в 4 раза меньше памяти.

Великая сила языка Go - это его модель параллелизма, Communicating Sequential Processes, CSP, описанная Тони Хоаром в 70-х годах, простая в реализации и подходящая для одновременных нужд.

DLopes
источник
2

Есть две основные причины, по которым Java быстрее, чем Go и C ++, и во многих случаях может быть быстрее, чем C:

1) Компилятор JIT. Он может встроить вызовы виртуальных функций на нескольких уровнях, даже с объектно-ориентированными классами, на основе профиля времени выполнения. Это невозможно в статически компилируемом языке (хотя может помочь более новая перекомпиляция на основе записанного профиля). Это очень важно для большинства тестов, в которых используются повторяющиеся алгоритмы.

2) Сборщик мусора. Выделение памяти на основе GC почти бесплатно по сравнению с malloc. А «бесплатный» штраф можно амортизировать в течение всего времени выполнения - часто его пропускают, потому что программа завершается до того, как нужно будет собрать весь мусор.

Сотни (тысячи?) Чрезвычайно талантливых разработчиков делают GC / JVM эффективными. Думать, что вы умеете «писать код лучше, чем все они», - это безумие. По сути, это проблема человеческого эго - людям трудно принять, что при надлежащем обучении талантливых людей компьютер будет работать лучше, чем люди, которые его запрограммировали.

Кстати, C ++ может быть таким же быстрым, как C, если вы не используете и OO-функции, но тогда вы довольно близки к тому, чтобы начать программировать только на C.

Самое главное, что «разница в скорости» в этих тестах обычно бессмысленна. Затраты на ввод-вывод на несколько порядков больше, чем разница в производительности, поэтому правильные конструкции, минимизирующие затраты на ввод-вывод, всегда выигрывают - даже в интерпретируемом языке. Очень немногие системы привязаны к ЦП.

В заключение, люди называют «компьютерную игру по тестам производительности» «научной мерой». Тесты полностью ошибочны, например, если вы просматриваете тесты Java для nbody. Когда я запускаю тесты на одной и той же ОС / оборудовании, я получаю примерно 7,6 секунды для Java и 4,7 секунды для C - что разумно - а не 4-кратное замедление, о котором сообщают тесты. Это клик-приманка, фейковые новости, предназначенные для увеличения посещаемости сайта.

И последнее, последнее замечание ... Я провел тесты с помощью Go, и это заняло 7,9 секунды. Тот факт, что когда вы нажимаете Go, он сравнивает его с Java, а когда вы нажимаете на Java, он сравнивает его с C, должен быть красным флажком для любого серьезного инженера.

Для реального сравнения Java, Go и C ++ см. Https://www.biorxiv.org/content/10.1101/558056v1 предупреждение о спойлере, Java выходит на первое место по чистой производительности, а Go выходит на первое место с комбинированным использованием памяти и настенное время.

Роберт Энгельс
источник
неправильно. C ++ работает так же быстро, как C, особенно когда вы используете ООП, это его свидетельство о рождении. больше абстракции (как в классах) БЕЗ КАКИХ-ЛИБО ДЕГРАДАЦИЯ ПРОИЗВОДИТЕЛЬНОСТИ РАБОТЫ, С НУЛЕМ ДОПОЛНИТЕЛЬНЫХ БАЙТОВ ПАМЯТИ. если вы этого не знаете, продолжайте резвиться с java, c #, go, python и так далее
// Кстати, C ++ может быть таким же быстрым, как C, если вы не используете и OO // функции, но тогда вы довольно близки к тому, чтобы начать просто программировать на C //. Если вы так говорите, вы очень плохо разбираетесь в C ++, ради себя же не используйте его. c и c ++ ненавидят магию и средневековые умы, суеверные по своей природе, как о, я слышал это, прочтите это в Интернете, это должно быть правдой ... держитесь подальше от c и c ++, они вернут вам, мой друг (честный совет)
c является предком c ++. многие люди до сих пор его используют ... С ++ - лучший c, где вы можете делать больше, не платя за это. авторы java, c # и go не поняли, ну конечно получили, но что они могут поделать?!? то же самое относительно совместимости с существующим (c) кодом. настоящие океаны c кода! python - хорошая игрушка, наслаждайтесь, я бы хотел, чтобы они поняли это правильно, но нет, дзен python должен был начинаться с «компилятор - ваш друг» ...
>> показывает использование ЦП на уровне 30% для программы Java << Нет —— "1% 0% 0% 100%".
igouy
1
@igouy Я признаю, что это ошибка, которую я, вероятно, сделал - когда я увидел load, я интерпретировал термины «загрузка системы» и предполагал, что user / system / io / idle - моя ошибка, и она была существенной.
Роберт Энгельс
1

Я думаю, что часто упускается из виду тот факт, что JIT-компиляция может быть> статической компиляцией, особенно для (времени выполнения) функций или методов с поздним связыванием. JIT хот-спота решает во время RUNTIME, какие методы встраивать, он даже может скорректировать макет данных в соответствии с размером / архитектурой кеша процессора, на котором он в настоящее время работает. C / C ++ в целом может компенсировать (и в целом будет работать лучше), имея прямой доступ к оборудованию. Для Go все может выглядеть иначе, поскольку он более высокоуровневый по сравнению с C, но в настоящее время отсутствует система / компилятор оптимизации времени выполнения. Моя интуиция подсказывает мне, что Go может быть быстрее, чем Java, поскольку Go не требует так много отслеживания указателей и поощряет лучшую локальность структуры данных + требует меньшего выделения.

Р. Мюллер
источник
1

На самом деле Go не только элегантен и эффективен во время разработки, но и очень эффективен во время выполнения. Главное - использовать правильную операционную систему, например, LINUX. Результат профилирования производительности под Windows и Mac OS, если не сказать лучшего слова, на один или два порядка хуже.

Дэн Маринеску
источник
0

под linux среда выполнения go очень быстрая, полностью сопоставимая с c / c ++. среда выполнения go под windows и unix не в одной лиге

сравнение с java не так важно, go подходит как для разработки системы, так и для приложений (поскольку java больше похож на синего воротничка только для разработки приложений). не буду вдаваться в подробности, но когда такие вещи, как кубернеты, написаны на ходу, вы понимаете, что это не игрушка для корпоративных консультантов

Я не помню, чтобы Google хоть раз упоминал о компромиссе, о котором вы говорите. go - это хорошо спроектированный, простой, элегантный и эффективный для разработки программ системного и прикладного уровня, имеет указатели, эффективное распределение и освобождение памяти, избегает сложностей, возникающих из-за того, что наследование реализации, которое так легко пропустить, дает вам совместные подпрограммы и другие современные способы писать высокопроизводительные приложения вовремя и в рамках бюджета. Опять же, go работает очень быстро под linux, для чего он и был разработан (очень рад, что это так)

Дэн Маринеску
источник
-4

И Java, и C более явны с их определениями данных и методов (функций). C статически типизирован, а Java - в меньшей степени с его моделью наследования. Это означает, что способ обработки данных в значительной степени определяется во время компиляции.

Go более неявный в своих определениях данных и функций. Встроенные функции носят более общий характер, а отсутствие иерархии типов (например, Java или C ++) дает Go недостаток скорости.

Имейте в виду, что цель Google для языка Go - найти приемлемый компромисс между скоростью выполнения и скоростью кодирования. Я думаю, что они достигли хорошей золотой середины с первых попыток, и ситуация будет только улучшаться по мере того, как будет сделано больше работы.

Если вы сравните Go с более динамически типизированными языками, основным преимуществом которых является скорость кодирования, вы увидите преимущество Go в скорости выполнения. Go в 8 раз быстрее Perl и в 6 раз быстрее Ruby 1.9 и Python 3 на тех тестах, которые вы использовали.

В любом случае, лучше задать вопрос: Go - хороший компромисс между простотой программирования и скоростью выполнения? Мой ответ - да, и должно стать лучше.

Билл C
источник
20
«отсутствие иерархии типов (например, Java или C ++) дает Go недостаток скорости» - а?
Эрик Каплун
6
«Go более неявный с его данными и определениями функций». Неправильно. Вы имеете в виду, как типы могут реализовывать методы без явных объяснений? Компилятор определяет тип - членство в интерфейсе. Это быстро. «Встроенные функции имеют более общий характер» нет, встроенные функции, как и все остальное, компилируются. То же самое происходит с шаблонами C ++. «отсутствие иерархии типов (например, Java или C ++) дает Go недостаток скорости» - неверно, иерархия типов не имеет ничего общего с выполнением во время выполнения.
Малькольм