Чому Go так повільно (порівняно з Java)?


109

Як ми бачили з гри The Computer Language Benchmarks Game 2010 року:

  • Перехід у середньому на 10 разів повільніше, ніж у С
  • У 3 рази повільніше, ніж у Java !?

Як це може бути, маючи на увазі, що компілятор Go виробляє власний код для виконання?
Незрілі компілятори для Go? Або є якась внутрішня проблема з мовою Go?

EDIT:
Більшість відповідей заперечують внутрішню повільність Go languge, стверджуючи, що проблема є у незрілих компіляторах.
Тому я зробив кілька власних тестів для обчислення чисел Фібоначчі : Ітеративний алгоритм працює у Go (freebsd, 6g) зі sameшвидкістю, як у C (з опцією O3). 2 timesТупий рекурсивний режим працює в Go повільніше, ніж у C (з опцією -O3; з -O0 - те саме). Але я не бачив 10-кратного падіння, як у грі з бенчмарками.


36
Справедливості, C - це маскування ASM, і Java в наші дні має серйозні оптимізації під кришкою.
Меттью Шарлі

16
Можливо, тест також не відображає сильні сторони Go. Можливо, інші орієнтири насправді швидші за це. Крім того, часто найбільше набирає не продуктивність, а читабельність коду.
екстранеон

7
@extraneon: Я згоден. Пам'ятайте, що Go призначений для Google, і Google регулярно виконує код на 2 мільйонах ядер. Я вважаю, що в грі Benchmarks використовується лише 4 ядра.
Йорг W Міттаг

4
@extraneon: Я погоджуюсь загалом, але Go був спеціально розроблений з урахуванням швидкості, як, наприклад, "в результаті програми працюють майже так само швидко, як і порівняний код C або C ++".
shosti

4
Ваше запитання передбачає занадто багато: "Більшість відповідей заперечує внутрішню повільність Go languge" - це неправильна фраза для використання у питанні. У вас є питання, яке потрібно задати, або заяву зробити? Будь ласка, перегляньте c2.com/cgi/wiki?HostileStudent, щоб зрозуміти вашу помилку.
Кріс

Відповіді:


102

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

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

Орієнтовні показники майже повністю стосуються якості впровадження. Вони не мають великої кількості спільного з мовою як такою, за винятком тих випадків, коли впровадження витрачає на час виконання функції підтримки мовних функцій, які реальним чином не потрібні. У більшості мов компіляції досить розумний компілятор теоретично може викреслити те, що не потрібно, але настає момент, коли ви сфальсифікуєте демонстрацію, оскільки дуже мало реальних користувачів мови писали б програми, які не використовували цю функцію . Переміщення речей, не видаляючи їх повністю (наприклад, передбачення віртуальних напрямків дзвінків у Java, складеній Java), починає складніше.

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


7
Більше того, можливо, програми Go в програмі The Computer Language Benchmarks не настільки оптимізовані, як програми C та Java.
el.pescado

Що щодо gcc -O0 та gcc -O3? Чи є навіть намір, що компілятори "зроблять все"?
igouy

@igouy: ну, я майже впевнений, що є намір gccgo робити збирання сміття, чого зараз немає. Є ще деякі функції входити в компілятори g, наприклад, вони в даний час не використовують особливих потоків хостів (зокрема, планувальник goroutut не має переваги). Крім того, я не знаю планів Google, чи компілятори g коли-небудь будуть жорстоко оптимізувати, чи буде лише gccgo.
Стів Джессоп

1
@xitrium: Я думаю, що намір Go полягає в тому, що впровадження не повинно вимагати спільного планування, вони можуть попередньо вилучати, якщо хочуть. Дивіться, наприклад, code.google.com/p/go/isissue/detail?id=543 , який не було закрито як "безглуздо, виправлення цієї так званої помилки суперечило б визначенню мови Go", що має бути, якщо Реалізації Go забороняються попередньо видаляти :-) Проблема ускладнювалася тим фактом, що Go за замовчуванням Go використовував лише одну нитку хоста, незалежно від того, скільки програм було запущено.
Стів Джессоп

6
Відповідь, можливо, трохи застаріла. Нещодавно вийшла перша бета-версія Go 1.1 , вони заявляють, що продуктивність компільованих програм зростає приблизно на 30% до 40%. Хтось, будь ласка, зробіть ці тести ще раз.
fuz

51

У наступному випуску Go FAQ має з’явитися щось подібне до наступного.

Продуктивність

Чому Go погано працює на еталоні X?

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

Ігри на бенчмарк виграються завдяки широкій настройці, і версія більшості тестів Go потребує уваги. Якщо ви вимірюєте порівнянні програми C та Go (зворотний доповнення - один із прикладів), ви побачите, що дві мови набагато ближчі за необробленою продуктивністю, ніж це показало б набір.

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

Ось ще кілька подробиць про The Computer Benchmarks Game з недавньої теми списку розсилки.

Збір сміття та продуктивність у гккго (1)

Збір сміття та продуктивність у гккго (2)

Важливо зауважити, що Комп'ютерна бенчмаркі - це лише гра. Люди з досвідом вимірювання продуктивності та планування потужностей ретельно узгоджуються, як, наприклад, над реалістичними та фактичними навантаженнями; вони не грають в ігри.


1
І ось деякі деталі з тієї самої
теми,

3
Важливо зауважити, що "орієнтири - це сукупність" - не лише тести, опубліковані як гра з орієнтирами - shootout.alioth.debian.org/flawed-benchmarks.php
igouy

18
(і всі ...) Звичайно, це "гра" , але коли я бачу, що Go лише у два рази повільніше, ніж найшвидший за цими орієнтирами, моє перше враження - "ух, Go здається швидким" , тому що я знаю, що ці орієнтири є недолік. Навпаки, коли я бачу, що Рубі в 65 разів повільніше, ніж найшвидший, я думаю, що "не буду використовувати Рубі для свого наступного одночасно чисельно-інтенсивного починання" . Так це може бути «гра», але в цьому є якась правда, якщо взяти її з зерном солі.
SyntaxT3rr0r

Планування потенціалу має дуже важливий аспект: вартість. Незалежно від того, чи знадобляться вам коробки X або 2 * X, це зрештою величезна різниця. А оскільки ніхто не може оцінити лише те, що в майбутньому буде працювати на них, найкраще поглянути на різні навантаження. Я перевірив декілька їх реалізацій і виявив, що вони в основному добре. Я думаю, що результати можна використовувати як основу для оцінок.
Агостон Хорват

Взагалі системи реального світу обмежуються IO, а не процесором. Тому те, чи Go є 2x або 5x повільніше, навряд чи так сильно впливає на планування потужностей, як відмову, балансування навантаження, кешування, топологія бази даних тощо. Ось чому додатки в масштабах YouTube можуть дозволити собі запускати багато своїх систем на Python.
Сухой Гупта

34

Моя відповідь не настільки технічна, як усі, але я думаю, що вона все ще актуальна. Такі ж орієнтири я бачив і в грі Computer Benchmark, коли вирішив почати навчання Go. Але я, чесно кажучи, вважаю, що всі ці синтетичні орієнтири є безглуздими з точки зору того, чи вирішити, чи достатньо швидко перейти до вас.

Нещодавно я писав сервер повідомлень на Python, використовуючи Tornado + TornadIO + ZMQ, і для свого першого проекту Go я вирішив переписати сервер у Go. Поки, отримавши сервер такої ж функціональності, як і версія Python, мої тести показують, що в програмі Go на 4.7-кратне збільшення швидкості. Майте на увазі, я кодую в Go лише тиждень, і кодую в Python вже більше 5 років.

Продовжуйте працювати лише швидше, оскільки вони продовжують працювати над цим, і я думаю, що насправді це зводиться до того, як це працює в реальному застосуванні, а не крихітних маленьких обчислювальних орієнтирах. Для мене Go, очевидно, призвів до більш ефективної програми, ніж те, що я міг створити в Python. Це моя відповідь на це питання.


3
Наскільки повільніше, на вашу думку, ви будете писати код Go, ніж Python?
Ерік Енгхайм

7
@AdamSmith - Я б сказав, що я писав би Go код повільніше, ніж Python, тільки тому, що кодую Python 7+ років і лише трохи Go. Але з точки зору Go проти інших статично набраних, складених мов, я ставлю ставку, щоб я написав Go швидше, ніж інші. Особисто я відчуваю, що це найближче до простоти Python зі швидкістю між C і C ++
jdi

5
У мене схожа історія. Щойно я почав вивчати Go, і відповідно до Benchmarks Game, Go є РІШНЕ, ніж JavaScript V8. Виявляється, моя інтенсивна програма бінарних операцій працює в 10 разів швидше з неоптимізованим кодом Go, ніж у високо оптимізованому V8 VM. У багатьох операціях Go може бути повільніше, ніж на C, проте ніхто не пише веб-сайти на C. Go - це вже цілком життєздатний варіант, і він повинен тільки покращитися, коли з'являються нові бібліотеки, рамки та інструменти.
якщо __name__ є None

1
@ user962247 це божевільне і хибне твердження. Я вже багато років пишу Go, і це швидко палає. Ніхто не стверджує, що він переможе C / C ++ / Java за кожним можливим синтетичним орієнтиром. Але це виграє на деяких (див. Сайт бенчмарків). Візьміть це у того, хто вже багато років пише виробництво Go code. Це швидко і продуктивно.
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%

Зараз це нарівні з Java, але чи не створено Go явно швидше, ніж Java, використовуючи для одних і тих же речей (мережеві додатки на стороні сервера)?
MaxB

1
@MaxB ні, це не було створено з метою бути швидшим, ніж Java. Він був створений з метою мати хороші показники, більш швидку компіляцію, ніж C ++, а також простішу і природну конкурентоспроможність, що дозволить розробникам бути більш продуктивними. Побиття швидкості виконання інших мов не було рушійним фактором.
jdi

5

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

Зауважте, що в орієнтирі нитка-кільце Go було на 16 разів швидше, ніж у Java. У тому ж сценарії Go CSP був майже порівнянний з C ++, але використовував на 4 рази менше пам'яті.

Великою силою мови Go є її паралельна модель, Communicating Sequences Proces, CSP, визначена Тоні Хоаром у 70-х роках, яка є простою у здійсненні та підходить для дуже одночасних потреб.


2

Є дві основні причини того, що Java швидша за Go і C ++, а в багатьох випадках може бути швидшою за C:

1) Компілятор JIT. Він може вбудовувати виклики віртуальних функцій через декілька рівнів, навіть із класами OO, на основі профілю виконання. Це неможливо статично складеною мовою (хоча новіша перекомпіляція на основі записаного профілю може допомогти). Це дуже важливо для більшості орієнтирів, які передбачають повторювані алгоритми.

2) ГК. Розподіл пам'яті на основі GC майже безкоштовний порівняно з malloc. А "вільне" покарання може бути амортизовано протягом усього часу виконання - часто пропускається, оскільки програма припиняється до того, як потрібно зібрати весь сміття.

Є сотні (тисяч?) Надзвичайно талановитих розробників, які роблять GC / JVM ефективними. Думати, що ти можеш "кодувати краще всіх", - це дурість. Це суть людського егоїзму - люди важко сприймають, що при належному навчанні талановитих людей комп'ютер буде працювати краще, ніж люди, які його запрограмували.

Btw, C ++ може бути настільки ж швидким, як і C, якщо ви не використовуєте і функцій OO, але тоді ви досить близькі до просто програмування на C для початку.

Найголовніше, що "різниці швидкостей" у цих тестах зазвичай безглузді. Витрати на IO на порядок більше, ніж різниці в продуктивності, і тому правильні конструкції, що мінімізують витрати на виведення, завжди виграють - навіть в інтерпретованій мові. Дуже мало систем пов'язано з процесором.

Як остаточне зауваження, люди називають "гру комп'ютерних мовних орієнтирів" як "наукову міру". Тести є повністю помилковими, наприклад, якщо ви переглядаєте тести 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, особливо коли ви використовуєте OOP, ось його свідоцтво про народження. більше абстрагування (як на заняттях) БЕЗ БУДЬ-ЯКОГО РЕГІМНУВАННЯ ДЕГРАДАЦІЇ, З ПЕРЕМОГОЮ ЗЕРО ЕКСТРА БЮТІВ. якщо ви цього не знаєте, продовжуйте гартувати з java, c #, go, python, et cetera

// Btw, C ++ може бути настільки ж швидким, як і C, якщо ви не користуєтесь функціями OO //, але тоді ви досить близькі до просто програмування на C // для початку. якщо ви це скажете, у вас є дуже мало поняття про c ++, заради вас самих цього не використовуйте. c і c ++ ненавидять магію та середньовічні уми, забобонні за своєю природою, як о, я чув, що, читайте це через Інтернет, це повинно бути правдою ... тримайтеся подалі від c і c ++, вони відкинуть вас назад мого друга (чесна порада)

c - родоначальник c ++. багато людей все ще використовують його ... c ++ - це кращий c, де ви можете зробити більше, не платячи ціну. автори java, c # and go цього не отримали, ну, звичайно, вони це зробили, але що з цим робити?!? те саме щодо сумісності з існуючим (с) кодом. реальні океани життя коду с! python - це приємна іграшка, насолоджуйтесь, я б хотів, щоб вони її правильно зрозуміли, але так, дзен python повинен був починатись із "компілятора - твій друг" ...

>> показує використання процесора на рівні 30% для програми Java << Ні —— "1% 0% 0% 100%".
igouy

1
@igouy Я визнаю, що це, мабуть, помилка, яку я зробив - коли побачив навантаження, я інтерпретував терміни "завантаження системи", і припускаючи, що користувач / система / io / idle - моя помилка, і вона була суттєвою.
Роберт ангелів

1

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


1

Власне кажучи, Go є не тільки елегантним та ефективним під час проектування, але й надзвичайно ефективним під час роботи. Ключовим моментом є використання правильної операційної системи, тобто LINUX. Результат профілювання продуктивності в Windows та Mac OS за відсутністю кращого слова поступається на один-два порядки.


0

У Linux під час роботи Linux дуже швидко, ідеально порівняно з c / c ++. тривалість руху під windows та unix не в одній лізі

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

я не пам'ятаю, щоб Google навіть колись згадував про компроміс, на який ви посилаєтесь. Хороший дизайн, простий, елегантний та ефективний для розробки програм на системному та прикладному рівнях, має вказівники, ефективне розподілення пам’яті та делокацію, дозволяє уникнути ускладнень, що виникають через о, так просто пропустити успадкування реалізації, надаючи вам спільну програму та інші сучасні способи написання додатків із високою продуктивністю у часі та бюджеті. знову ж таки, швидкий рух під Linux, саме для цього він був розроблений (дуже радий, що це робить)


-4

І Java, і C є більш чіткими зі своїми визначеннями даних та методів (функцій). C набраний статично, і Java менше, ніж за своєю моделлю успадкування. Це означає, що спосіб обробки даних в значній мірі визначається під час компіляції.

Go є більш неявним із його визначеннями даних та функцій. Вбудовані функції мають більш загальний характер, а відсутність ієрархії типів (наприклад, Java або C ++) призводить до недоліків швидкості Go.

Майте на увазі, що метою Google для мови Go є прийнятний компроміс між швидкістю виконання та швидкістю кодування. Я думаю, що вони потрапляють на гарне солодке місце при першій спробі, і все покращиться лише в міру того, як буде зроблено більше роботи.

Якщо порівняти Go з більш динамічно набраними мовами, головною перевагою яких є швидкість кодування, ви побачите перевагу швидкості виконання Go. Go у 8 разів швидше, ніж perl, і в 6 разів швидше, ніж Ruby 1.9 та Python 3 на тих орієнтирах, які ви використовували.

У будь-якому разі, краще задати питання: чи є гарний компроміс у простоті програмування та швидкості виконання? Моя відповідь - так, і вона повинна покращитися.


20
"відсутність ієрархії типів (наприклад, Java або C ++) надає недоліком швидкість" - але?
Ерік Каплун

6
"Go є більш неявним із його визначеннями даних та функцій." Неправильно. Ви маєте на увазі, як типи можуть реалізовувати методи, не будучи про це експлікацією? Компілятор виявляє тип - інтерфейсне членство. Це швидко. "Вбудовані функції мають більш загальний характер" немає, вбудовані, як і все інше, складені. Те саме відбувається з шаблонами C ++. "відсутність ієрархії типів (наприклад, Java або C ++) надає недоліком швидкість" - неправильно, ієрархія типу не має нічого спільного з виконанням часу виконання.
Малькольм
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.