LINUX.ORG.RU

Почему Discord сменил Go на Rust. Блог разработчика.

 , ,


3

5

В статье автор описывает успешный проект Discord, в котором Rust используется для потоковой обработки в Go Live и их Elixir NIFs’ сервере.

Автор пишет
«Хочу отметить, что мы потратили очень мало усилий на оптимизацию реализации на Rust. Но даже только с базовой оптимизацией Rust оказался быстрее супероптимизированной реализации на Go. Это заметный плюс для Rust, показывающий, насколько легко писать эффективные программы, используя Rust, по сравнению с глубоким погружением в Go.»

>>> Why Discord is switching from Go to Rust

★★☆☆

Проверено: Shaman007 ()
Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от tailgunner

Хотя насчет «типичности» ты опять

Можешь сам на гитхабе поискать типичнее и элегантнее.

если бы ты привел эквивалентный код на, например, Go

Вполне очевидно, что на разных языках не может быть эквивалентного кода, если речь конечно не идёт о каких-то совсем базовых конструкциях или алгоритмах.

А так - тупо демагогия.

Я пытался написать, что вкус вкусом, но называть его красивым и элегантным как то перебор. А все остальное развёл ты ))

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vertexua

Вроде бы еще не сделали GC-based вариант Rust.

Rust же был (до 1.0) со сборкой мусора, потом были пара экспериментов - оказалось, что целевой аудитории это не сильно нужно. Мне вообще кажется, что с нормальной, проверямой компилятором move-семантикой, накладные расходы человеческих сил довольно умеренные (если не писать библиотек).

tailgunner ★★★★★
()
Ответ на: комментарий от mx__

Ээм. Это компилятор, написанный теми же разработчиками. Можно так использовать: gc -compiler=gccgo или как то так

sniper21 ★★★★★
()
Ответ на: комментарий от tailgunner

Ну там у людей вначале немного напряг на всяких детских вопросах, вроде ой я писал на Java и там был String. А тут тебе String, OsString, &str и так далее. Не дай бог Cow<> увидеть

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vasily_pupkin

Хотя насчет «типичности» ты опять

Можешь сам на гитхабе поискать типичнее и элегантнее.

Я видел много совершенно заурядно выглядящего Rust-кода. А ты выбрал serde.

Я пытался написать, что вкус вкусом

Так это и есть демагогия. До того, как сваливаться на вкусовщину, нужно сравнить возможности. Привести эквивалентный код.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от vertexua

ой я писал на Java и там был String

Так в Java есть (по крайней мере, был) еще и StringBuilder :)

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

А ты выбрал serde.

https://github.com/RustCrypto/signatures/blob/9df4f307641d6652321a694d8347cdf546ed6d2c/ed25519/src/lib.rs#L370

Я это рили от балды выбрал. Но сейчас прочитал что выбрал, и стало как-то особенно смешно.

Впрочем, нет никакого смысла продолжать эту дискуссию.

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vertexua

Я бы не сравнивал переход от С++ к Go тем же самым, что и переход от ассемблера к С.

Переход от ассемблера к С закономерен. И является эволюционным развитием все того же ассемблера.

Ведь как вообще выглядело программирование вначале. Есть некое число, команда процессора. У нее есть операнды, числа, записанные после нее. Первый шаг - а может мы заменим числа коды команд некими мнемоническими обозначениями? И стало уже веселее. Человеку легче читать такой код.

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

Следующий шаг, а почему бы нам не унифицировать подход к вызову таких подпрограмм? Ведь мы делаем одну и ту же работу каждый раз по вызову этих функций. Так функции написанные разными людьми стали совместимы между собой. И да? Почему бы не поручить эту работу компилятору? Отлично, сказано - сделано.

А это уже макро-ассемблер. Половина от компилятора.

Следующий шаг, как заменить выражение ADD rax, rbx; на c = a + b, уже было делом времени. Потому что ведь на самом деле программисты использовали одни и те же регистры каждый раз для схожих операций. Так почему же не вынести эту работу за скобки? Это дело времени и очередной закономерный виток эволюции.

Таким образом С не накладывает никаких накладных расходов. Все тот же макро-ассемблер.

Go - это все-таки совсем другое. Rust - не знаю. Проблема именно в отличии. Таких язычков появляется чуть ли не каждый день пачками. И умирают. А С - это старый добрый макроассемблер, который построен на соглашениях, соглашениях как вызывать функции, как использовать регистры. Это та работа, которая вынесена за скобки. Ничего не добавлено и не убавлено. Программисты на ассемблере делали все то же самое каждый день.

hibou ★★★★★
()
Последнее исправление: hibou (всего исправлений: 1)
Ответ на: комментарий от hibou

Go - конечно другое. Rust - GC нету, рантайма нету.

Просто С++ 203x. Легаси выбросили. Фичи с накладными расходами не добавляли. Хорошие практики структурирования С++ кода встроили в язык. Хороший С++ код все равно только так и написан. Написан так, как единственно возможный на Rust

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от vertexua

А как у него с совместимостью по ABI? Я могу написать библиотеку на Rust и вызывать ее код из С? И наоборот, могу из Rust свободно вызывать машинный код, полученный от С?

hibou ★★★★★
()
Ответ на: комментарий от hibou

Rust ABI - тут наверное ситуация как с С++ на данный момент.

С ABI поддерживается. Свого нету

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

На твой взгляд - что за самая важная штука в расте в сравнении с цпп? Только конкретно, самое вкусное, чтобы я прям побежал раст штудировать.

pavlick ★★
()
Ответ на: комментарий от kostyarin_

При этом если распилить сервер на микросервисы, то проблемы не будет.

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

dimon555 ★★★★★
()
Ответ на: комментарий от pavlick

Только конкретно, самое вкусное

Будишь модным смузихлёбом, а не пробзделым плюсовиком.

AUX ★★★
()
Ответ на: комментарий от pavlick

Я думаю то, что Rust Book, компилятор Раста и Clippy учать программировать на Rust, и даже на С++ нормально. Ошибки компилятора или подсказки Clippy в большинстве случаев говорят «возможно вы имели ввиду…».

Тут конечно нужно уметь перенаправлять фрустрацию от того что «не компилируется».

Еще есть несколько других фич. Доработаность в многих внезапных мелочах, которые делают программирование приятнее.

Cargo очень удобен и прост. Crates - часто простые юникс-вейные библиотеки, которые обычно без проблем собираются.

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


fn f() -> u32 { ... }

let mut x = None;   // Уже тут понятно что это Option<u32>

if ... {
   x = Some(f());
}

Еще мне нравится отход от концепции классов и что есть просто структуры и методы отдельно описываются как функции к ним. Например это еще заставляет именовать конструкторы, делать из них фабрики.

let x = Config::from_file("...");

Когда доходит до асинхронного кода, то там очень и очень много цепочек async/await вычислений трансформируется в машины состояний внутри. Futures сделаны совсем не так как везде, очень уникальный и производительный дизайн

Сложно так перечислить, просто по ходу встречаешь разные удобства и каждый раз понимаешь как все продумано

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 4)
Ответ на: комментарий от hibou

тут больше подходит вопрос, а зачем вообще этот эльбрус?)

noname_user ★★★
()
Ответ на: комментарий от vertexua

Я скорее о временах когда создание любых объектов в жабе было медленным и пулы давали значительное ускорение. Сейчас емнип только в апаче есть какие-то базовые реализации пулов, остальное удел всего что медленно создается по иным причинам типа коннектов или тредов. Имхо если ты сейчас ищешь ускорение через пулы в 99% случаев ты либо уже всё заоптимизировал по самое небалуйся и тебе нефиг делать, либо у тебя с архитектурой проблемы.

ya-betmen ★★★★★
()
Ответ на: комментарий от kostyarin_

Пагади, при чем тут сессия вообще. Вот тебе пример - надо юзеру выполнить запрос который стоит условные бабки и работает только для подписки класса X и выше.

Как оно выглядит в микросервисах:

  • пришли на гейт (rest/graphql/grpc/неважно), гейт сходил в базу проверил токен (может даже не сам, а через сервис авторизации), отправил запрос сервису, обсуживающему этот тип операций
  • сервис посмотрел что за операция, кинул запросы на баланс юзера и его тип подписки
  • сервис(ы) баланса/подписки глянули в базу что как и дали добро
  • сервис операции принял ответы и начал шуршать базой/перебирать жсоны

И это простой вариант. Сколько сетевых запросов посчитать сможешь? До базы и редиса как бы тоже по сети ходить, это не локалхост. Я даже деликатно намекнул что тип подписки и баланс можно параллельно смотреть, а то и вместе на одном сервисе, но критический путь это не сократит.

А теперь прикинь что у тебя data residency и надо ходить не на соседнюю машину в том же дц, а к черту на рога в другую страну. Вот тут вообще финиш будет, на каждый город бэкенд не раскатаешь, дорого выйдет

Часть вещей можно кешировать, но это тонко и может спровоцировать косяки.

А пихать разом всё в токен это треш и угар. Я тут только три поля для примера указал, а их может быть и 33, а то и 333. У тебя токен в пару метров будет.

upcFrost ★★★★★
()
Ответ на: комментарий от unixnik

Я всегда думал что код на С++ написанный прямыми руками всегда быстрее всего кроме асемблера.

В нынешние времена оптимизаторы настолько свирепые, что даже ассемблер в 99.99% случаев помедленнее плюсов окажется.

Тут Эльбрусы упоминали? Дык у них архитектура VLIW, максимальный размер одной команды – 64 байта. 64 БАЙТА, КАРЛ! Ну-ка, кто руками оптимально распишет параллельное использование разных подсистем процессора? Так чтобы не сойти с ума в процессе, и код выдавать со скоростью более 10 инструкций в день.

@fernandos:

Так-то между ними ещё Си.

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

Таким образом, C++ наше всё.

dimgel ★★★★★
()
Ответ на: комментарий от kostyarin_

При этом если распилить сервер на микросервисы, то проблемы не будет.

Насколько при этом возрастёт потребление памяти?

question4 ★★★★★
()
Ответ на: комментарий от hibou

Лучше один раз нормально выучить С++ и писать на нем

Разработчики D смотрят на тебя с недоумением и опаской.

matumba ★★★★★
()
Ответ на: комментарий от dimon555

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

Уверяю Вас, дебаггер нужен не для того, чтобы дебажить криво сделанную бизнес-логику. Он для другого.

kostyarin_ ★★
()
Ответ на: комментарий от upcFrost

гейт сходил в базу проверил токен (может даже не сам, а через сервис авторизации)

Да, это меня больше всего прикалывает. Чтобы проверить подпись нужно отправить сообщение сервису. Вообще-то нет. Так делается только в некоторых случаях, когда нужно отзывать JWT-токен в период времени жизни access token. Т.е. действительно, в реальном мире – в очень редких случаях. Импортнул либу. Проверил подпись. Декодировал токен. Сунул в контекст запроса.

Дальше

  • запрос к сервису подписок (+маршалинг)
  • ответ от него (+обратный маршалинг)

Две операции по сети – копейки.

При этом базу подписок никто больше не бомбит – она отдельно. Здесь прирост в производительности. Масштабируй, меняй харнилище, прикручивай кэш, если долго рожает. Если нет – нет.

kostyarin_ ★★
()
Ответ на: комментарий от question4

Насколько при этом возрастёт потребление памяти?

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

Знаешь как говрят - учиться, типа, нужно на чужих ошибках. Но это фигня полная. Учиться нужно на чужих успехах. Небезызвестный Твитор использовал XML для хранения своих твитов. И переползать на что-то другое они удумали только после очень большого кол-ва петабайт.

kostyarin_ ★★
()

Самое смешное

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

DukeNukem
()
Ответ на: комментарий от vertexua

Дак в том то и дело что шумиха поднялась. Впервые сделали язык где нет - помощь компилятора в ноль вытирается в результирующем коде. До этого в D было не так, в Go и подавно. А Rust оп, и сделали zero cost abstractions

уж сколько раз твердили миру, что тупые проверки на границы массива при доступе по индексу - это нифига не zero cost.

А расставленные вручную непонятно кем unsafe и impl Send - это нифига не «помощь компилятора».

Lrrr ★★★★★
()
Ответ на: комментарий от hibou

Круче С++ еще ничего не придумали. Остальное все чисто чтоб С++ не учить.

Всё верно, возьми с полки пирожокsegfault! ;)

X-Pilot ★★★★★
()
Ответ на: комментарий от Legioner

Тебе кажется. Rust уже давно взлетел. И вообще из последних языков он по-моему прямо таки образец популярности, возьми любой другой язык - он либо взлетал десятки лет, либо его с плёткой в руках пропихивала какая-нибудь корпорация. Rust это реальный феномен в современном IT. Его разве что с Java можно сравнить, она примерно так же взлетала в 90-х.

С Kotlin сравни. Вроде бы эти языки ровесники. С моего холма выглядит так, что Rust медленней входит в обиход.

TheKnight ★★★
()

А всего-то надо было переписать под ноду. Асинхронную часть - нативно на C++, а остальное - на JavaScript, или TypeScript

menangen ★★★★★
()
Ответ на: комментарий от Legioner

И вообще из последних языков он по-моему прямо таки образец популярности, возьми любой другой язык - он либо взлетал десятки лет, либо его с плёткой в руках пропихивала какая-нибудь корпорация.

Я так давно слежу за растом, что кажется он уже вечность взлетает. Может уже попробовать написать хелловорлд, не знаю даже. Все говорят какой он популярный, но в моей локации такого слова никто не слышал даже. А вот вот возьмем C#. Вышел он в самом начале нулевых, и уже в 2004 году я писал коммерческий код на дотнете. Дело было в том же далеком замкадье. Конечно там микрософт был за спиной, но всё же.

bread
()
Последнее исправление: bread (всего исправлений: 1)
Ответ на: комментарий от TheKnight

Так Kotlin гугл продвинул, как основной язык для самой популярной ОС в мире. Чего б не взлететь. А за пределами андроида хз, в следовых количествах.

Legioner ★★★★★
()
Ответ на: комментарий от kostyarin_

Чтобы проверить подпись нужно отправить сообщение сервису. Вообще-то нет.

Я про access token вообще-то. Авторизацию никто не отменял, в 99% сервисов у тебя будут субклиенты и тебе будет нужно их проверять

Две операции по сети – копейки

Любая операция по сети - уже довольно дорого по сравнению с локальным исполнением кода.

upcFrost ★★★★★
()
Ответ на: комментарий от hibou

Лисп - это же интерпретатор?

Лисп - это семейство языков. На момент написания Cfront компиляторы языков из этого семейства существовали.

Gentooshnik ★★★★★
()
Ответ на: комментарий от ritsufag

«Пошёл! Пошёл! Работаем, работаем, страус, пошёл! Так, так, хорошо! Эй! Эй! Эй! Куда?!»

grem ★★★★★
()
Ответ на: комментарий от Legioner

Мне кажется, ты не прав. Kotlin сначала взлетел, потом был подхвачен гуглом. Причина популярности Kotlin в Android-разработке - это возможность использовать нормальный язык вместо Java 6 и хорошее переиспользование текущей кодовой базы. Ровно так же он нынче взлетает потихоньку и в существующих Java проектах.

TheKnight ★★★
()
Ответ на: комментарий от Kroz

тогда эта зависимость выражается как функция от нескольких переменных

и даже возможна сама функция(результат от набора аргументов) хранит своё состояние :) - крч общность людей обладает прекрасными нелинейностями

qulinxao3
()

Это ли не доказательство жира Google? Открытые продукты работают быстрее. Я считаю это позором для проприетарщины.

Desmond_Hume ★★★★★
()
Ответ на: комментарий от filosofia

Писать на Го монолит —это как ссать против ветра.

Нет там никакого монолита. На Го они написали микросервис, отвечающий за сохранение и обновление состояния залогиненного пользователя, всего-то. Увидели как GC периодически выжирает процессор и переписали на Раст.

По процессорному времени выиграли немного: на Го проц потреблялся меньше Раста большую часть времени, только периодически были пики GC. На Расте проц все время потребляет процессор больше чем Го, но пиков GC нет. В среднем на Расте выиграли около 10% по процу если смотреть среднюю загрузку. Ну и плюс получили равномерную (а следовательно предсказуемую) загрузку.

Наверно, в масштабах крупных сервисов это хорошее достижение, все-таки программное решение экономит электроэнергию. Но по большей части поменяли шило на мыло: сопровождать Го может вчерашний школьник, а специалистов на Расте надо еще поискать.

Xintrea ★★★★★
()
Ответ на: комментарий от kostyarin_

При этом если распилить сервер на микросервисы

Когда кто-то произносит слово «микросервисы», у меня микротик микроглаза ничинается.

Wizard_ ★★★★★
()
Ответ на: комментарий от bread

шарпик ващет 99 как nih vs java(чей первый хайп 95-96) а потом тихий захват ентерпрайса при уходе собол-программеров на пенсию. к середине нулевых

qulinxao3
()
Ответ на: комментарий от vertexua

это такой гениальный аргумент против очевидных вещей?

Все эти разговоры про «zero cost abstractions» в расте - полная чушь, не имеющая отношения к действительности.

Lrrr ★★★★★
()
Ответ на: комментарий от Lrrr

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

hibou ★★★★★
()
Ответ на: комментарий от d09

десктопный клиент на c++/qt

что на сервере неизвестно, но вероятно тоже плюсы

десктопный клиент дискорда, если я правильно понимаю, на js/электроне

Ford_Focus ★★★★★
()
Последнее исправление: Ford_Focus (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

о том что в гугле (в целом, а не только в команде хрома) фичи > багфиксы говорилось много и часто.

У конторы нет коробочных решений, которые нужно продавать, но вот такой вот менеджмент у ребят.

Ford_Focus ★★★★★
()
Ответ на: комментарий от hateyoufeel

Так её же как раз в первую очередь в мазиллу и завозят, особливо в фаерфокс, где раст на максималочках.

А ну да, я и забыл, что раст раза в два менее читабелен, а значит, писателен, чем С++, посему лису на него вот уже лет 10 с трудом переводят, еле-еле процентов 10 перевели.

next_time ★★★★★
()
Последнее исправление: next_time (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.