Как стать автором
Обновить

Комментарии 39

Лучше читать оригинал. Перевод никакой.

Я после Go пробовал посмотреть Rust. По большому счету, он мне понравился. Но его защита памяти делает его несколько медленнее в среднем чем Go. Хотя, конечно, работа сборщика мусора в GC все еще оставляет желать лучшего.

Поделитесь замерами? Просто ваше утверждение несколько спорное. Возможно что-то не так было в раст имплементации.

В расте zero cost защита памяти, так что теоретически он быстрее, если конечно это не какие то очень сложные алгоритмы на графах с персистентными структурами данных, но такие вряд ли на go пишут.

Речь не только про сложные алгоритмы, см. блогпост. Достаточно в цикле создавать мульёнами кучу короткоживущих объектов и аллокатор будет висеть гирей на растовом решении, тогда как для гц это практически no-op. Впрочем, даже в такой ситуации кастомный jemalloc неплохо себя показывает.

Ради справедливости замечу, что GC в Go тоже далеко не no-op при использовании короткоживущих объектов с указателями. Я уже натыкался на это. Вот пример от более опытного человека: syslog.ravelin.com/further-dangers-of-large-heaps-in-go-7a267b57d487?gi=2dd24cd91629

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


Впрочем, я даже не про гошный гц, а про гц в целом скорее. В JVM/Haskell, таких проблем нет, и часто бывает, что человек который приходит оттуда в раст и тащит с собой старые привычки обмазывается боксами, а потом всё тормозит как чёрт. У нас даже были внутри компании сравнения практически идентичного алгоритма, один мы написали сами идеоматично, а другой взяли у третьей стороны, написанный в стиле "а мы портировали с Java". Разница была порядка 400%.


Так что аллокации без ГЦ действительно удовольствие недешёвое, лучше им не злоупотреблять.

В Го весьма продвинутый GC из существующих.

Бггггг, нет. Там используется three-colored mark and sweep, а сборщик мусора не сжимающий и даже не поколенченский (generational).

Зато он с минимальными паузами, многопоточный и умеет работать, не останавливая выделение памяти.

Т.е трейдофф у него в сторону скорости, а не размера «грязной» памяти.

Угу, хорошая latency в ущерб troughput и общему потреблению памяти. И не настраивается толком.

Если вы не знали, у гц не 2 параметра которые настраиваются, а с десяток. Latency/Troughput/MaxMemoryConsumption/AverageMemoryConsumption/Cross-generations references/… И все они настраиваются в приличных ГЦ, хотя там офк выбраны некоторые умолчания. Оптимизировать один парметр, забив на все остальные — много ума не надо. Стоит ли считать после этого такой гц "лучшим" или хотя бы "хорошим" — большой вопрос.

Это скорее теоретически «настраивается». Четвертое колесо настройками не прикрутишь.

Так что от настроек, Cross-generations references (и барьеры) в Го не появятся, и можно ли их отключить например в дНете, где они есть — тоже вопрос.

Либо ГЦ работает и всех в общем устраивает, как он работает. Либо нужно отказываться от ГЦ. Настройки — мертвому припарки.

В Го большинство опрошенных ГЦ критичной проблемой не считают, значит он хорош.
image
Это скорее теоретически «настраивается». Четвертое колесо настройками не прикрутишь.

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

Нет сомнений, что подпирание костылями — весьма выгодное занятие, когда дом построен на песке =)

Да, такое и правда из за деструкторов будет не очень работать, как минимум. Хорошее замечание, но ведь для таких случаев можно в принципе наколеночный "gc" применить в духе такого.
https://github.com/servo/string-cache

Можно. Можно юзать heapless/smallvec и аллоцировать не в куче, можно играть с jemalloc или вообще свой сделать, можно идти по пути всяких кэшей или просто аллоцировать большой объём и руками его использовать… Варианты всегда есть, просто в момент когда вы в программу пытаетесь встроить медленный, плохо протестированный и страшненький псевдо-ГЦ это верный признак, что технология выбрана немного не верно.


Точно так же, как я вижу когда в Java/С#-приложении в начале выделяют массивчик на 2 гигабайти и MyFooIntPtr из MyFooMemoryAllocator туда-сюда развлекаться.


Каждой технологии — своё место. Уметь переключаться между разными инструментами и использовать по назначению то, что лучше подходит под задачу — важно.

Если это вот какое то специфичное место программы, то наверное все же эффективнее именно приделать частное решение проблемы.
А если там gc постоянно нужен, тогда да, но ведь это зависит от специфики алгоритмов.

Но его защита памяти делает его несколько медленнее в среднем чем Go.

Вот это странное заявление, которое ничем не подкреплено. Читаем статью "Go быстрее Rust, Mail.Ru Group сделала замеры".

Что вы хотите от Goшника? Golang изначально создавали чтобы дурачкам в гугле было сложнее существующие системы поломать. Пайк об этом прямым текстом говорит
Ну, то же был Python1. А третья версия кмк уже изначально планировался как яп широкого применения.
Существует оператор for… range для итерации по массивам и слайсам, но вы не можете перебирать другие коллекции, потому что концепция итераторов отсутствует
На самом деле, еще можно сделать range по каналам

В прошлый раз когда я так сделал у меня задедлочилось приложение. Конечно, я не эксперт в го, и даже не любитель, но переделывание на for когда я точно знаю сколько элементов в этом канале должно прийти помогло. А range продолжал ждать, хотя все писатели уже в канал написали что могли и прекратили работу.

Может канал не закрыли? Тогда он будет бесконечно на range висеть. Если же канал закрывать нельзя, то да, кроме for с конкретным количеством больше придумать нечего, range тут не поможет.

Edit: хотя, если один поток решил не отвечать или запаниковал, то for с количеством повиснет точно так же, как и range.
А также по map

Читал перевод, но после того как Map перевели как Карту просто закрыл статью. Статья — хороша, перевод — гугл транслейт. Поставил плюс за контент, но надо было хотя бы 10 минут на вычитку потратить. Выглядит как перевод "за зачёт", без особого интереса и попытки понять, что же могло означать "Никаких первичных классов" или "вы не можете использовать пользовательские типы в качестве ключей для карте". Вангую что речь-то шла про first class citizens (functions/types/...) и хэшмапы.




Глянул оригинал — почти: No first class enums. Using constants feels backwards.. То есть речь конкретно про энумы, а не какие-то абстрактные "классы".

Время компиляции быстро? Возможно, но вот время линковки ужасно, многогигабайтный результирующий бинарник — это про Го.

По этой же причине и из-за многих других накладных расходов Го не может быть системным ЯП, да и позиционируется исключительно для Веб-прикладных.
В современном Go (1.2-1.4 уж простите не застал) полная сборка (с линковкой) большинства проектов мгновенна.

многогигабайтный результирующий бинарник — это про Го

а можно поподробнее пожалуйста? в статье не могу найти про гигабайты ничего

позиционируется исключительно для Веб-прикладных

в чятах плюсовиков разве что, ну или тех, кто полностью игнорирует облака в 2020
Ой, ну приврал на 3 порядка =) Многомегабайтный конечно, 88Мб в статье.

Минимум примерно такой — берем из статьи исходник на Go и на Rust.
Ubuntu 18, go 1.14.2, rust 1.40
cargo clean
cargo build --release
Finished release [optimized] target(s) in 1.05s
размер после strip 244'056 byte
время выполнения программы для 20000 — 3.288 с
rm distance
time go build distance.go — real 0.564s
размер после strip 1'534'040 byte
время выполнения программы для 20000 — 6.554 с

Время почему то варьируется от конфигураций — лучше посмотреть у себя. Я запускал с дефолтными, т.е -О2 для обоих.
вы простите, я опять не понял…
я был немного удивлён критикой линковки в Go ("время линковки ужасно"), но даже в вашем примере видно, что Go собирает бинарь в 2 раза быстрее чем Rust (и кстати меньше секунды, т.е. мгновенно), линковка входит в сборку

что до размера в 88мб: по дефолту Go собирает статический full debug бинарь, кому не нравится, надо как раз линкеру желаемые флаги передавать. upx кстати хорошо помогает и официально поддерживается, а вот strip делать нельзя, можно потом странные сегфолты поймать.

время выполнения вполне типичное (ну +-), я где не тестировал, Go примерно вдвое и отставал от Rust (что вполне логично: авторы Go считают производительность результирующего кода делом десятым, ведь компьютеры становятся быстрее с каждым годом, а стоимость вычислений наоборот падает. на первом месте для них производительность программиста — чистый прагматизм, в развитых экономиках человекочасы программистов гораздо дороже обходятся чем железо, отсюда и многие дизайн-решения, например GC, который в большинстве случаев позволяет вообще о памяти не думать). да и Rust чертовски быстр, если сравнить со скриптотой, то Go будет быстрее в 5-10 раз (зависит от задачи)
Чтобы сравнивать время сборки, стоит сравнивать с чем то быстрым. например с чистым С. Да и пример тут слишком копеечный. Я например наблюдал 40с линковку для небольшой задачки.

У Раста медленная компиляция, о чем предпочитают умалчивать. В данном случае это нивелировало. Да и до стрипа здесь был +- сравнимый размер.

Вдвое отставание на выч.задачах — выглядит как неплохая оценка.
Я например наблюдал 40с линковку для небольшой задачки.

Звучит как баг по мне, наверное даже зарепортил бы. Я не помню даже больших проектов которые не уложились бы в 10с итого (вся сборка).

Банально, но ЯП — лишь инструмент…
В основном на Go сижу года три, если не больше…
И бывали круто и просто организованные проекты, а также, подобно одному из последних — стопицот обстракций для простого и элементарного круда… Ещё и вызовов множество неявных в перемешку с инициализациями и сетапами пакетов (внутренних, монорепа)… И все это завинчено интерфейсами… — это плата за якобы простоту Го… Ну, так проект был построен, по адски…


А по существу: статья какой-то хайп 2х годичной давности, я первый месяц кайфовал с Го, потом плакал, потом научился как ненужно писать — и вроде наладилось… Пока не встретиться дикий проект)


Го интересный, в целом не сложный и быстрый, но если бы не простота создания многопоточных и конкурентной безопасных приложений — не влез бы в него.


А ещё там есть select для каналов, контекст, интерфейсы (которыми рекомендуют не злоупотреблять), имутабельность строк, особенности работы с слайсами и много других вещей… Читайте офф доки, раз в месяц, и будет почти счастье.


Учимся делать сложные вещи просто… Когда простые вещи получаются сложно — или учите матчасть, или берите другой ЯП, на котором будет проще.


Статья вредная, вводит в заблуждение касательно простоты..

Учимся делать сложные вещи просто…
Это как познать Дзен… Бесконечен путь совершенствования
Никаких первичных классов.
Использование констант ощущается непривычно.
Вообще не понял, что тут имеется в виду.

определенно это лучший язык этого поколения

Если автор так считает, то думаю он ещё не видел Julia.
Хоть язык немного из другой области, чем Go, но раз уж пошло сравнение с Python & Co, то можно привести в пример и Julia. Все, что автору нравится в Go есть в Julia, при этом в ней есть макросы, дженерики и многие другие интересные решения, которые язык позаимствовал у лучших.
Go действительно интересный, читабельный и приятный язык, но он не один такой. И я согласен с автором по поводу его недостатков.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий