Experimental chill
9.3K subscribers
12 photos
1 video
2 files
109 links
Algorithms, libraries, C++, Linux, Distributed Systems, maybe Rust

Donate: https://xn--r1a.website/experimentalchill/222

Author: @Danlark

Nothing in this blog is an opinion of my employer
Download Telegram
1. Интересно почитать о том, насколько быстрой можно сделать коммуникацию по памяти между процессами в Linux

https://mazzo.li/posts/fast-pipes.html

Если коротко, то используется [vm]splice системные вызовы с большими страницами. Интересный факт заключается в том, что эти вызовы в какой-то степени "дарят" страницы другим процессам и тот, кто их создал, не имеет к ним доступа. Бывают полезные кейсы, несколько раз слышал трейдинг их использует, чтобы правильно отдавать память процессам для обработки. Но правильно их использовать замучиться надо ещё. Поэтому я чаще видел как делают shared memory, контролируя весь стек.

Интересный вопрос, а можно ли что-то придумать, чтобы эти страницы помечались copy on write. Мое знание Linux говорит, что да, такой флажок есть, наверное, что-то даже можно сварить из select+poll, но уже становится достаточно тяжело. Отличная идея для io_uring, как по мне :)

Тем не менее, написано понятным языком, и можно узнать много нового.

2. https://www.forrestthewoods.com/blog/benchmarking-malloc-with-doom3/

Проводят benchmark и гистограммы вызовов аллокатора памяти. Не приводят аргументов, но цифры очень похожи на правду. Медиана в 25 наносекунд, 99.9 где-то 20 микросекунд, а когда ядро решает потормозить, уйти в себя, все 500 микросекунд. Отлично почитать, чтобы понимать, насколько быстро современные аллокаторы отдают память.

3. https://arxiv.org/pdf/2205.05982.pdf

Мы тут выложили SIMD сортировку. Честно? Мне не понравилось, идея ок, сравнение и ускорения только для чисел. Невозможно задеплоить в прод адекватно, сортировка чисел не так много цпу занимает. В итоге ни в стандартную библиотеку не включить, ещё и требует зависимости большой SIMD библиотеки. Я не в восторге, так как результат никогда не пойдет в масштабный прод, но если хочется почитать и проникнуться очередными трюками SIMD, welcome.

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

4. Возможно в ближайшее время будут посты попроще или поменьше. Точно есть ещё на пару недель и один огромный пост, а дальше как-то список закончился. Я расту в Google, мне тяжело, я едва успеваю делать что-то вне работы, плюс ещё полно интересных вещей в обычной смертной жизни происходит. Никогда не думал, что это будет настолько тяжёлая проблема, скейл команды и продукта (а ещё и себя самого), мы растем по количеству пользователей, всем метрикам, а из-за этого количество всех corner case багов увеличивается, нагрузка на support увеличивается и просто уже не хватает ни времени, ни сил. В прошлый раз, когда я чувствовал себя так, я уходил из проекта. На этот раз хочется встретиться с этим и попытаться вытащить продукт на следующий уровень хотя бы 2х по всем параметрам. А 2х по меркам Google это, конечно, очень сложно, и, наверное, самое сложное это community и поддержка проекта, технически уж справимся. Новые испытания, uncomfortably exciting! :)
👍73🔥1710
Вообще иногда нахожу какие-то моменты в своей инженерной практике магическими. Я выпал из реальности на пару дней и совершенно не мог двигаться. Последний ~месяц ничего хорошего не происходило в моей жизни в работе.

Зато вчера я занёрдснайпил экспертов ARM и лида Apple одним коммитом :)

Вообще интересный тред от Хектора про Розетту и эмуляцию x86 на Apple M1 (уже и M2)

https://mobile.twitter.com/marcan42/status/1534053625110351872

Коротко: Rosetta хорошо работает не потому что Apple сделали фичей под себя, а потому что хорошо написали розетту и заимплементировали первыми FEAT_* стандарты (в том числе для флагов FEAT_AFP)

А коммит оказался тот самый из наших хеш-таблиц.

Потом Dougall внимательно прочитал и предложил ещё более лучшую версию:

https://twitter.com/dougallj/status/1534213050944802816

Итог: я показал как можно использовать редкие инструкции под ARM, Dougall нашёл ещё более оптимизированный способ, мы сконтачились, созвонимся в ближ пару дней и возможно познакомлюсь с Хектором (легенда же!)
🔥155👍12👏1
И в добавок ко всему этому: на работе коллега доделал очень крутую штуку, которую мы не знали как сделать 3 месяца, а один очень талантливый разраб из соседней команды захотел поработать с нами.

Почему хорошие вещи происходят в один день, особенно когда я на полном дне? Я чувствую какой-то подвох/закономерность, что чтобы приключения происходили вокруг тебя, надо обязательно себя кинуть в стену желательно на несколько недель. Хорошие вещи происходят очень хаотично, очень часто в один день как будто что-то прорывает. Weird

P.S. Я в этом году сижу в програмном комитете C++ Zero Cost Conf. Эта конференция про перформанс C++ и любые практические вещи. Мы ищем доклады, подавайтесь, это простой способ поработать со мной над материалом. Даты ещё не определены, где-то июль, насколько я понимаю.
👍34🔥4👏1
Одна из самых сложных задач для меня в последнее время это рост нашей инфраструктуры. Очень забавно за этим наблюдать, потому что я обычно люблю что-то строить с нуля, а поддерживать намного все сложнее, но менее важным оно не становится. В том же Гугле просто невероятное количество сил убито на поддержку, но, наверное, так в каждом инженерном деле. Вещи ломаются, тут должны быть умные слова про энтропию, а их надо чинить. И надо сильно верить, что вещи должны работать постоянно, чтобы уметь поддерживать продукт. Не как мой провайдер, который решает раз в 3 недели отключить меня на 4 часа.

Для меня в инфраструктурных командах есть 3 стадии: построение, поддержка и неизбежный рост или смерть. Когда вы строите, но у вас нет пользователей, это самое блаженное время, его надо ценить и беречь. Вы можете ошибаться, экспериментировать и знать, как лучше что-то сделать.

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

Мы закопали MapReduce, об этом даже говорили на одной встрече Cloud, потому что невозможно было поддерживать. Продукт умер, вкопано десятки тысяч часов, но оно закопано. Написали новый движок, и... до сих пор растем.

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

Но количество пользователей то растёт. И мы вот достигли точки нашей инфраструктуры, когда уже человек не справляется.

Дальше интересный вопрос, что с этим стоит делать. Можно двух человек ставить на ротации, а потом и трёх и так далее. Только вот команда так не растёт экспоненциально. А ещё люди меняются, экспертиза во многих местах может быть потеряна.

Это тончайший баланс, как растущую инфраструктуру поддерживать, потому что когда одного человека в день на поддержке становится не достаточно, то на самом деле уже поздно.

Хоть это и показывает, что продукт достаточно успешен, но дальнейший рост ограничен пропускной способностью команды, это в итоге выльется, что все будут только на поддержке. Экспонента покажет, что это наступает ой как быстро.

Это сложный вопрос, что надо делать. Я работаю в Гугле, у нас были такие очень сложные эксперименты роста.

* Документация документацией, но практика показала, что намного лучше читают "best practices", советы, написанные человеческим языком о том, как использовать инфраструктуру. Примеры, tips of the week, testing on the toilet -- позволяют намного больше репликации знаний и снижают фактор вопросов экспоненциально. Документация нужна экспертам, чтобы знать все гарантии, но ее нельзя игнорировать.
* Office hours, кейсы дебага онлайн на аудиторию позволяют погрузиться, посмотреть как стоит подходить к проблемам, это тоже понижает фактор вопросов.
* Процесс построения community. Это так называемые readability -- когда чтобы вкоммитить код, нужно получить зелёную галочку от эксперта по языку, а ещё лучше, когда эксперты меняются. Каждый новый эксперт -- multiplicative фактор, он учит много других многим знаниям, оно передается дальше. Получается иерархия, на верху команда, ответственная за продукт, дальше лучшие эксперты, потом чуть похуже, но все они распространены в командах, и значит на верхушку доносятся намного меньше проблем.
* Self-debug. Когда инфраструктура позволяет анализировать проблемы сама -- лучше компиляторные ошибки, понятные логи, интуитивные инструкции. Это самая инновационная и богатая на идеи тема, помогает хорошо, но иногда сложные вещи просто сложные :(

Я начинаю чувствовать, что если всем этим не заниматься одновременно, видя, что инфраструктура растет, в один момент будет поздно. В целом он произошел, сейчас я много времени провожу, чтобы начать создавать community, потому что нас не хватает. Ещё интереснее, как скейлить Cloud, внутри то мы можем все правильно сделать, а снаружи...

Мне страшно, потому что это фундаментально человеческое, страшно, что нет достаточно authority. Страшнее только команду растить :)

Все ещё читаю Google SWE book, там мы об этом много писали.
🔥44👍264🤔2🎉2
This media is not supported in your browser
VIEW IN TELEGRAM
На дворе 2022 год

Мы находим оптимизации в mem*/str* функциях на мажорных платформах в 20%, которые были доступны как лет 10

Да, это патч в glibc.

В целом история такая: на x86 достаточно легко переходить из векторного кода в скалярный -- если есть вектор сравнения на gif, то на x86 есть PMOVMSKB инструкция, дающая скалярную маску

На ARM такого нет, и все ломали голову как же так сделать. Даже в glibc инженеры Arm делали через 4 цикла и просаживая latency.

Поизучав NEON SIMD, я нашёл инструкцию shrn -- shift right and narrow. На гифке представлен shift right and narrow на 4. Теперь у нас есть маска, не 16 битная, но хотя бы 64, с которой уже можно скалярно работать.

Что произошло в итоге:

1. ZSTD на 5%
2. Хэштаблицы гугла на 3-8%
3. glibc на 10-20% для размеров <=128
4. ClickHouse -- string comparison and sorting на 15%
5. Через 2-3 недели ждите статью, да, это software optimization guide. 3 года назад я студентом увлёкся армами, а вот сейчас я буду писать гайды совместно с вендорами

Mic drop
🔥433❤‍🔥31👍24🤯16🐳14😱3💯2🙏1
Я тут обнаружил забавную историю, о которой не так много говорят. В Itanium ABI -- у Unix* подобных системах есть пункт про конструкторы и деструкторы классов, чтобы они возвращали void. Оно логично, конструкторы и деструкторы классов ничего не возвращают, зачем им вообще возвращаемые значения.

К сожалению, это приводит к достаточно интересным проблемам при конструировании базовых/деконструировании классов

void destroy(TObject* object) {
delete object;
}


Выглядит как:

Remember pointer to another register
call destructor of TObject
Move pointer to %rdi
call free memory

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

Вот в ARM и (внимание!) Fuchsia, WebAssembly ABI практически такой же как и Itanium кроме того факта, что конструкторы и деструкторы возвращают указатель на объект. Из-за этого можно делать tail call оптимизации:

call destructor of TObject
Move return value to %rdi
call free memory

И не надо сохранять никаких объектов до этого

Последняя операция возможна, так как регистры уже подготовлены и все объекты, память готовы к использованию. В первом случае такая операция невозможна, так как ABI не ждёт возврата. Это экономит код, немного перформанса.

С конструкторами чуть интереснее: оно позволяет экономить на перекладывания регистров в случае наследований

class B { B(int) {...} }
class A : public class B { A(int x) : B(x) {...} }


Fuchsia ABI позволит делать tail call из B сразу в A, так как все регистры уже подготовлены и указатель на память на начало B тот же, что и на начало A.

В clang вы можете включить опцию -fc++-abi=fuchsia -target x86_64-unknown-fuchsia, но будут проблемы, чтобы скомпилировать что-то большое.

Поэтому, я конечно же, предлагаю пропатчить clang одной строчкой здесь, чтобы разрешить использовать Fuchsia ABI. (просто return true;)

А сам код максимально приятный.

class FuchsiaCXXABI final : public ItaniumCXXABI {
public:
explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
: ItaniumCXXABI(CGM) {}

private:
bool HasThisReturn(GlobalDecl GD) const override {
return isa<CXXConstructorDecl>(GD.getDecl()) ||
(isa<CXXDestructorDecl>(GD.getDecl()) &&
GD.getDtorType() != Dtor_Deleting);
}
};


Итог: бинарь кликхауса в релиз режиме был 539854128, стал 520550564 байт, 3.6% размера. Запустился и вроде даже какие-то тесты прошёл.

Перф тесты надо бы запустить, но компилятор патчить и вставлять для этого пока лень. clang на 0.5-1% по тестам стал быстрее компилировать всё после его же бутстрапа.

Какие у этого проблемы? Если вы используете динамическую линковку с C++ библиотеками, будут проблемы, поэтому это работает только если вы контролируете статическую сборку.

Даже в ARM через gdb видны эти вещи

class A {
public:
A() {}
~A() {}
};


(gdb) ptype A::A
type = class A {
public:
A(void);
~A(int);
} *(A * const)
(gdb) ptype A::~A
type = void *(A * const)


Такие вот проблемы с Itanium ABI, которые мы навряд ли уберем из-за legacy :)

[1] ARM ABI constructor/destructor return values
[2] Itanium ABI constructor/destructor return values note
👍47🔥17🤔3🤯1
Оооо, мы наконец-то довыкладывали тут Google Fleetbench

https://github.com/google/fleetbench

Это бенчмарки важные для нас в Google (репрезентативные насколько это возможно). Там сейчас только хэшмапы и протобуфы, но мы со временем добавим больше всякой всячины, типа стандартной библиотеки, компрессоров, в том числе и видео. Возможно пару бенчмарков распределённых систем in a long run :)

Зачем? Мы считаем, что наш стек должен быть быстрым, мы платим деньги за CPU/RAM/Latency. Хотите написать статью/предложить оптимизацию в протобуфах/хэшмапах? Сравните с этим репозиторием, и мы с намного большей вероятностью посмотрим и включим ваш патч (а может даже и наймём)

Если вы из Intel/AMD/ARM/$ВАШ_ЛЮБИМЫЙ_ВЕНДОР и хотите сделать чип, чтобы мы заинтересовались и его купили? Сравнивайте перформанс в этом репозитории. Придумали большую controversal макро компиляторную оптимизацию в LLVM? Возьмите наш репозиторий как ещё одну точку для сравнения.

Ну и в целом мы достаточно хорошо настроены на то, чтобы делиться тем, что нам важно в плане перфа, OSS и мы сильно выигрываем от более оптимизированных библиотек/програм. Как и все остальные тоже.

Из забавного, вы можете посмотреть на самые прожорливые обезличенные схемы протобуфов.
🔥65👍13❤‍🔥5🌭2
Релиз: Arm машинки в Google Cloud. Учитывая, сколько я тут писал про Arm (и я себя ещё останавливал), то, наверное, не сложно было догадаться :). Но это штука важна, прочитайте, пожалуйста, тут и про Apple будет.

https://cloud.google.com/blog/products/compute/tau-t2a-is-first-compute-engine-vm-on-an-arm-chip

Мы третьи (AWS, Azure), мы отстаем. Мне стыдно за это, почему так получилось не хочу говорить, мы просто дураки, вот и все. Пытаюсь оправдать себя тем, что если мы просто будем достаточно зарабатывать на этом, то не важно, третьи мы или нет.

И в целом Google никогда не был hardware компанией, понятное дело, мы плохо продаем и делаем железки, как тут говорят: "Google's DNA is software". Чип, который мы релизнули это Ampere Altra на Neoverse N1. Страшные имена, но это чип пока не наш.

Что делаю я в этом проекте? Занимаюсь перформансом и изредка нахождением всяких багов внутри чипа, деплоем на внутреннем облаке и вообще смотрю в будущее software-hardware codesign. Получилось занять нишу, где я общаюсь с обеими группами и перевожу один язык на другой. Оказывается это тяжело, поэтому мало кто занимается.

А теперь мое полотно и мнение:

Никто из Amazon/Microsoft практически не занимался software перфом на армах. Без шуток, учитывая, что я находил, рыская по форумам и git blame, кто что коммитил, я видел только несколько амазоновских коммитов в JVM, но они практически даже не притронулись к компиляторам или софту.

А кто, впрочем, занимается перфом Arm? По факту, сами Arm, Apple и ... Android люди из Google/Samsung (достаточно лениво, телефоны другая задача совершенно). Я видел ещё порой интересные коммиты от Huawei, Alibaba и Tencent.

То есть Китай, Apple и теперь мы подключились. Учитывая, что чип из коробки приносит достаточно сильно perf/$ экономию (10-20%), я был ОЧЕНЬ удивлен, увидев практически ноль вложений в софт.

Мы серьезно улучшили некоторые открытые бенчмарки, потому что мы пришли и пооптимизировали какие-то стандартные вещи по типу сравнений строк, компрессоров, хэштаблиц, собрали ядро правильно. Я сильно погрузился в ассемблер, SIMD, компиляторы, memory models, concurrency protocols, LLC eviction policies и тому подобное.

Я точно могу сказать, что gap в софте огромный. x86 уже 15 лет учит своих пользователей писать код через гайды, когда как Arm не учил практически никого. И это один из факторов, в который я верю, что он будет только расти. Выиграть ещё 2-3% в perf/$ каждый год в течение 2-3 лет из-за софта реально. Наш известный lemire выкладывает всякие проверки на utf8, ваш верный господин @Danlark приходит и поправляет имплементации на Arm https://github.com/simdutf/simdutf/pull/145 на пару десятков процентов.

Apple сделала некоторые вещи по-другому, меня это и удивило, и заставило задуматься. Нет, они не шаманы, нет, они не сделали свои инструкции или спец Memory model (но M1 с TSO), они лишь отошли от гайдов Arm, зная какие инструкции им нужны для крутого перфа, как впаять память поближе к сокетам. Самое важное изобретение -- Rosetta 2, настолько хороший JIT написали действительно знающие компиляторы люди -- команда J.F. Bastien. Они чуть чуть поиграли грязно, отойдя от гайдов, но и в х86 у нас полотно различных железок. M1/M2 чип, сделанный хорошо с хорошим софтом, но чтобы сделать хорошо, надо начать лет 10 назад. Apple смогли сыграть в долгую, и за это им уважение.

В Google мы пока можем предложить историю софта. Мне плевать, если мы соптимизируем для всех (e.g., OSS), конкуренция вендоров поможет развиться всем.

Если будут вопросы по нашим виртуалкам, или вы клиент и хотите перфа на Armах в нашем клауде, автор к вашим услугам, дропните сообщение @Danlark, и мы все устроим, официально и с моим энтузиамом, чтобы ваш софт работал нормально.
👍74🔥56❤‍🔥23🌭3
https://www.meetup.com/clickhouse-london-user-group/events/286891586/

Буду выступать на митапе ClickHouse в среду 20 июля в Лондоне, расскажу про оптимизации Arm для CH, и в целом про Arm чуть чуть

(Опять меня легко купили на рекламу ClickHouse)

Приходите, если можете
👍68❤‍🔥3🔥2😁2😢1
https://github.com/carbon-language/carbon-lang

Выложили мои коллеги из Google новый язык, совершенно в проекте не участвовал, но очень интересно приживется ли такой язык и нужен ли он обществу

Идея: есть С++, его все не любят. Есть Rust, его как-то все настойчиво любят, но у него приоритеты больше по safety и отсутствия багов. Из-за этого страдает перф

Carbon хочется втиснуться посерединке. Он все ещё небезопасный, зато с коробочными санитайзерами. Такой же быстрый, как и С++, но с модулями, без исключений, c дженериками, без ABI совместимости, с тулингом от LLVM, *с тулзой для миграции с С++* (почти рабочей 🙃).

Можете называть его форком С++, можете называть его неудачной попыткой в Rust. Мне будет интересно, приживется или нет. Может он умрет через полгода, а, может, и будет процветать. Деталей сам знаю мало, пошел читать
🤔88🔥22👍14👎11💩11😁3
Ваш PlayStation 5 умножает числа на три в два раза медленнее, чем ваш ноутбук

После релиза Arm машин я попал в дофаминовую яму из которой я стараюсь выходить всякой рутиной, где я помогал разным проектам (в том числе и всякими оптимизациями в Arm). За последнее время я решил перечитать много литературы, писал много документов и мало кода. It's fine, sometimes there are weeks when you understand completely nothing. Две истории, одна стратегическая, другая практическая, но они связаны.

Я понял, что когда делаю свою работу, я очень мало времени уделяю тулингу в перформансе. Скажем, я делаю процентов 20 анализа данных, что медленно, почему медленно, процентов 40 как это соптимизировать, остальные 40 на то, а как эту историю можно обобщить. Скажем, я недавно писал, как одна доп кешлиния в AMD не выучивается процессором, что она не так уж и важна, дальше вопрос, а в чем различия AMD и Intel, если уж посмотреть глобально. Бенчмарки делались на Intel долго, интересно, есть ли пробелы у AMD, можно ли унифицировать, чтобы всем было хорошо. Нашёл ещё одну историю, но она сильно другая:

На x86 умножение на 3 устроено через старую иструкцию LEA (Load Effective Address). Если коротко, эта иструкция умеет вычислять выражения REG1+X*REG2+Y, где X -- 0, 1, 2, 4, 8, а Y не очень большая константа. В итоге чтобы умножить на 3 надо взять REG1==REG2, X = 2. То есть это сумма X и (X << 1), вполне логично и legacy, которое мы за собой оставили. Инструкции mul/imul работают дольше.

Посмотрев на таблицу инструкций я нашёл, что AMD Zen 2 имеет latency 2, когда как абсолютно все Intel latency 1. Proof.

Нашёл пару мест в коде и поправил на что-то более унифицированное, выиграл немного.

Я назвал этот пост ваш PlayStation 5 умножает числа на 3 в два раза медленнее, чем ваш ноутбук для лайков и хайпа. Вопрос, который мне задали несколько раз:

$AUTHOR_NAME, как ты эту херню находишь?

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

* pclmuldqd -- Zen2-3 имеет latency 4, Intel 7. Это означает, что CRC чексуммы надо вычислять по-другому, Erasure кодеки работают медленнее, нашёл CRC вычисление, сравнил, действительно медленнее
* Ещё некоторый SIMD Memory load, но паттерн доступа к памяти проявился и тогда

OH MY GOD, ИСТОРИЯ ПРО КЕШЛИНИЮ MAKES SOME SENSE. Конечно, не сразу, конечно, чтобы её найти съесть много всего, внимательно смотреть. Главный вопрос, который я себе задаю -- а может ли это быть важно? И да, очень часто можно найти на скейле любую историю.

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

Большой человек из Netflix (а сейчас из Intel) не зря занимался визуализацией через flame graphs, это тулинг, позволяющий что-то понять, мультипликативный фактор новых открытий и понимания. В Google мы семплируем весь прод каждый день, чтобы открыть понимание, происходит ли что-то (а что-то вообще происходит?).

В ближ время хочу заняться двумя вещами в тулинге: иллюстрация всех ассемблерных инструкций, а также хочу написать свой сжимающий кодек отсортированных с random access и поиском, работа Lemire про FastPFor мне кажется слишком простой, а я слишком много знаю про эту тему. Посмотрим, насколько я загорюсь. Сил не хватает, автор походу постарел, гореть чем-то почему-то стало тяжелее за последний год.

След статья про распределённые системы, обещаю :)
👍112🔥5010😱5🐳3💯3👏1🤩1🥱1
Опять наврал, но на этот раз, пусть будет, #челоперф, продуктивность людей тоже сильно влияет

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

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

1. Я разломал прод.

2. Я почему-то начал бояться, что не вывезу одну задачу. И если честно, я её реально не вывожу. Она важная, а я не знаю как её решить уже несколько месяцев, хотя я придумал идею аж два года назад. Страшно увидеть, что идея не работает :)

Казалось бы, мелочи, кто не ломал, и бывают сложные задачи. Притворяться, что у меня идеальная карьера не хочется и это, как бэээ, не правда. Успецкий мужицкий патриархальный успех с промо каждые 6 месяцев приправленный L7 до 28 лет и хатой в центре Лондона это не про меня. И меня, кстати, скорёжило недавно от вопроса, мол, когда следующее промо. Почему это логично меня спросить, что я как будто, должен этого хотеть, я не знаю. Всё само придёт, я просто это знаю, я не оптимизирую свою карьеру очень сильно, и никому не советую, это опасный риск.

Короче, я просто херовенько переживаю неудачи. Помогают народные методы, как

* Поговорить с менеджером
* Притормозить
* Взять отпуск
* Пописать код на Rust
* Починить прод, который сломал, хотя бы откатить
* Покушать вкусной еды

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

* Мне очень комфортно работать в командах 2-3 человека. Проект/задача включает в себя 5 человек, кто-то да работает не так, как хочу, не делает чего-то. Мне не хватает ни сил, ни желания руководить этим хаосом, когда люди не очень стабильны. Среди 5 людей очень часто кто-то не очень стабилен.
* Люблю близкое общение. Меня похвалили за менторство джунов. В команде на много людей работаю плохо. Check
* Когда у меня отнимают код и заставляют писать много псевдотехнических доков/рисовать презентации, хочется прям выбросить ноутбук и не приходить на работу. Check

Поболтали, поняли, что на самом деле брать много людей пока не надо. Можно расти работая близко с парой людей над проектами. Хочешь Individual Contributor Track -- пожалуйста, дорога посложнее, зато ты счастливее.

Да, счастливее. Буквально за полдня температура снизилась, завтра отдохну до конца и пойду снова херачить, может, дам проекту провалиться. It's fine. Пусть горит, я знаю как ещё в ста местах принести пользы. Пока бизнес позволяет это, это нормально.

Я давно замечаю, что люди самые продуктивные, когда всё в порядке с ментальным ощущением себя в мире. Никаких "через себя", "да ты что не мужик/слабый". Да, мир сложнее, и это утопия, если все такими будут. Тем не менее, искать пути сделать себя спокойнее по жизни важны. Расту, учусь, как ладить с собой.

А теперь учу как разломать прод:
203👍24❤‍🔥10👎1👏1😁1
В C++, вы можете создавать объекты в классе и объекты, которые задекларированы последними, могут принимать себе параметры предыдущих.

state_ зависит от dep_ в примере. При деструкторе state_ разрушится, потом dep_ разрушится. Всё хорошо. Объекты разрушаются в обратном порядке. Так учили ... всегда и везде, да? :)

Так вот, при default move операторе мы сначала делаем move на dep_, потом на state_ и между move мы получаем state_ с вероятно некорректной зависимостью (вектора или умные указатели вызывают деструктор при move dep_).

Бабах, пруф https://gcc.godbolt.org/z/xG14Wj3E7

Фикс: писать свой move оператор, где вы сначала делаете move на state_, потом на dep_, то есть в обратном порядке.

Скажите же, очень легко написать = default здесь, думая, что язык сам делает всё правильно?

Пойду попишу на расте, что ли
👍88😱30🤡24🌚9🔥5🤯4😁3🌭3👎2😢2
Далёкая память

В датацентрах давным давно уже проблемы с тем, чтобы закупать память -- она очень дорогая. Мы по сравнению с 2011 годом в Борге хоть и видим увеличение утилизации на 5-20%, но медианная утилизация остаётся на уровне 60% [1].

Из-за этого в статьях прошлых лет (года с 2018) сильно развивалось понятие далёкой памяти -- давайте мы абстрагируем память ещё, теперь будем забирать данные с помощью сети из других машин. Самые известные -- Hydra [2], мы на OSDI'22 в Google вышли с Carbink [3]. Обе статьи решают нужные нам задачи:

* Можем достигать лучшей утилизации и уменьшить простой
* Приложения могут аллоцировать больше памяти, чем одна машина

Проблемы очевидны: забирать по сети намного тяжелее, отказоустойчивость не так просто сделать (хранить память на SSD не подходит из-за ещё более медленных восстановлений), модель _памяти_ становится не очень ясной.

Для того, чтобы достигнуть репликации фактора два, можно реплицировать на три узла. Память дорогая и так делать не стоит. Поэтому лучше взять Erasure Coding: в самом простом случае это выглядит как поделить данные пополам, взять xor, теперь у нас есть 3 части, при выпадении любой, можно восстановить все данные. В итоге занимаем x1.5 места, но фактор репликации можно достигнуть любой. За Erasure Codes стоит большая теория, но основная идея, что мы делим данные на N несколько частей, считаем M дополнительных через линейное преобразование. При выпадении любых M, мы можем посчитать обратное линейное преобразование. Математика говорит, что матрицы существуют при почти всех разумных N и M, которые обладают таким свойством. Обычно выбирают что-то из пар (3,2), (4,3), (12,9).

Проблема в том, что когда вы аллоцируете память, её поделить даже на 3, 4 или 12 частей тяжело, так как аллокации объектов не очень большие и erasure codes начинают тормозить. Мы в Google вышли со статьёй о TCMalloc, где мы храним такие объекты в так называемых spans, много мелких объектов хранятся в одном чанке в пару мегабайт. Мы решили делать так же -- мы будем синхронизировать spans объектов (а также erasure codes на множество spans, что мы назвали spanset), а не каждый кусок. Это разгружает сеть, так как объекты в erasure codes находятся внутри спанов, а не разделены. Если ничего не выпало, из одного узла возьмутся данные, в худшем случае при падении узлов читать надо всё.

Изменения происходят в background тредах, если память становится холодной, она помещается в span, инвалидируется по сети, замещается. Узлы, которые отвечают за саму память, время от времени делают compaction, чтобы удалить ненужные spans. Если приложение memory intensive, это увеличивает нагрузку на сеть.

Использовать spans в пару мегабайт имеет лишние ненужные байты. В Carbink мы в итоге насчитали, что используем на 35% больше памяти, чем в Hydra, но зато сильно уменьшили 50 и 99 квантили (в ~1.2-1.5 раз) доступа и throughput.

В статье много интересных деталей -- например, как помечать биты в указателях, как брать RCU lock на указатели, которые приходят по сети и тд.

Меня, конечно, больше интересует вопрос о том, когда это можно ждать в датацентрах? Ну, в худшем случае никогда, в лучшем через 2-3 года, когда software и hardware stack будет к этому готов, потому что использование памяти по сети требует

* Писать немного кода, чтобы использовать такие указатели, прозрачно через аллокатор пока тяжело это сделать. Это кстати не особо большая проблема, сервисы обычно имеют понятное использование больших буфферов
* Perf будет страдать, надо будет аккуратно выбирать пользователей для этого, которым важен throughput, инфраструктура типа MapReduce/Spanner может подойти
* Можно сжимать холодую память в этой далёкой памяти, как делает, скажем, zswap, экономить ещё

Хорошая статья о том, как можно увеличивать утилизацию памяти, когда вы очень большие, ну и мы наконец-то поделились, что думаем о far memory и инвестируем research туда :)

[1] Borg: the next generation
[2] Hydra : Resilient and Highly Available Remote Memory
[3] Carbink: Fault-Tolerant Far Memory
👍52🤯42🔥12
Забавный рисёрч вышёл от нас про Code Efficiency

"Learning to Improve Code Efficiency"
https://arxiv.org/pdf/2208.05297.pdf

Если написать очень много кода одной и той же задачи разными людьми (скажем, на LeetCode или как в статье, на Google Code Jam), можно встретить много разных подходов: кто-то напишет цикл, а кто-то вызовет функцию стандартной библиотеки. Всякие такие оптимизации и хинты это всегда знание, которое собирается кумулятивно. Такие вещи обычно делают через AST matchers и статическим анализом, но всё не написать, а обучить людей более быстрым (которые часто и более правильные) конструкциям хочется.

Предложили обучить VQ-VAE (Vector-Quantized Variational Autoencoders) модельку, которая пытается найти как подсказать человеку на какую конструкцию стоит заменить тот или иной участок не самого быстрого кода.

Результаты, конечно, игрушечные, но интересные. Так можно в целом обучать людей конструкциям языка на задачах LeetCode или competitive programming, потому что кто-то да умный найдётся как написать красиво и элегантно (или не очень, как уж пойдёт). Перформанс и корректность можно померить в отличие от красоты кода. Хорошо, что эти вещи иногда коррелируют.

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

Просто красиво, как использовать -- пока непонятно
👍70🔥9🤔6
https://www.usenix.org/system/files/osdi22-huang-lexiang.pdf

Я как-то тут писал про метастабильные падения с конференции HotOS. Как и ожидалось, академия тоже играет в индустрию, и по старой доброй традиции, если статья появляется на HotOS, то её решение или расширенная версия на OSDI. Одна статья на 2 конференции, как удобно!

Напомню, что про метастабильные падения можно думать как о падениях, из которых тяжело выйти откатив изменение -- вы что-то поменяли, откатываете, а проблема всё ещё осталась, так бывает из-за проблем retry, сброса кеша, который не может набраться, каскадные падения, невозможность обработать спайки ошибок (jitter).

В новой статье из интересного добавили группировку по реальным падениям в Cloud провайдерах, опыту твиттера и тд. Например, примерно половина из всех инцидентов возникла из-за плохой политики перезапросов, 35% из-за спайка ошибок. В статье хорошо разобраны тригеры таких состояний, которые можно применять как эвристики для их детекции и понижения нагрузки.

Хочется рассказать подробнее о _деградации_ (в статье её нет, в старом посте я её упомянул):

Что такое деградация? Деградация это достаточно редкий, но полезный трюк для того, чтобы сделать вашу систему неубиваемой, но для этого надо написать немного кода и иметь одно свойство -- возможность неполно читать данные. Иногда её ставят в ряд с congestion протоколами в сети, но редко тема выходит в сервисы.

В поисковых системах, в рекомендательных системах, в мониторинг системах, в не strongly consistent файловых системах вы можете придумать такие свойства

1. Искать по части поискового шарда
2. Задерживать показ viral постов/твитов/ютуб видосов или варьировать количество кластеров в поиске ближайших
3. Читать чуть-чуть старые данные, скажем, не для real time аналитики или mostly read only fs, a.k.a. stale reads
4. Увеличивать размеры временных корзин для сбора аналитики в мониторинг системах

Коэффициенты частичной обработки можно варьировать от очень консервативных чисел до очень неконсервативных. Можно сделать от 0 до 1 такой коэффициент.

Когда машина/система начинает испытывать трудности, коэффициент деградации можно понижать до нуля (в самом простом случае, выбирать бинпоиском число, более умно использовать всякие экспоненциальные формулы из congestion протоколов (об этом как-нибудь в другой раз)) и если есть много перезапросов или jitter из ошибок, то деградация поможет:

1. Плавно вытащить сервисы из типичных проблем перезапросов
2. Выиграть время для реагирования
3. Не сделать сильно плохо пользователям, искать по 80% поискового шарда не так уж и плохо
4. В случае критических глобальных проблем с датацентрами, мисконфигурацией, переживать неожиданное увеличение нагрузки намного легче

Другой пример, который мне пришёл на ум после прочтения статьи это time to live в файловых системах: хочется давать возможность людям ставить time to live на папки, но иногда бывает так, что кто-то решит удалить 3 миллиарда файлов и происходит следующее

1. Начинаем удалять папку
2. Не справляемся за сутки
3. Другие пользователи жалуются, что их файлы не удаляются

В итоге 3 недели удаляем 3 миллиарда файлов, другие файлы не удаляем. Чтобы сделать какой-то честный garbage collection, надо хитрить на клиентах (не показывать им файлы) или удалять в зависимости от редкости -- люди готовы подождать 3 недели для удаления 3 миллиардов файлов, но 3 недели для одного не очень. Тонкий баланс метастабильности как UX. И всё таки данные удалять надо, privacy, все дела.

Приятная для чтения статья, много всяких примеров можно придумать в голове
👍49👎2😁1
Рубрика: интересные компиляторы

Поговорим просто про сложение. На x86 сложение имеет 2 операнда addq %reg1, %reg2, что означает reg2 += reg1. На ARM сложение имеет 3 операнда add x3, x2, x1, что означает x3 = x1 + x2.

Когда вы складываете несколько чисел подряд (скажем, для простоты 4 числа x1 = x1 + x2 + x3 + x4), то это делается в 3 инструкции

x5 = x1 + x2
x6 = x3 + x4
x1 = x5 + x6


Такие оптимизации называются tree reduction, чтобы первые две операции исполнялись параллельно в процессоре, так как у них нет зависимости. В итоге такие операции занимают 2 цикла вместо 3.

К сожалению, так как в x86 сложение принимает только 2 операнда, так сделать не получится, либо надо складывать числа как x1 += x2, x3, x4 (цепочка из 3), либо складывать x3 += x4, что не всегда хочется или можно (скажем, менять x2, x3, x4 не хочется). Есть инструкция lea, но на x86 не всегда хватает регистров, чтобы сделать это быстро, поэтому в целом tree reduction не очень применяется.

Так вот, так как clang слишком сильно и годами оптимизировался Долиной под x86, такие сложения редко оптимизировались в целом и оставались просто через add.

И да, clang как-то слишком топорно оптимизирует сложения 4 чисел на Arm, где у нас 16 регистров вообще

        add     x13, x13, x9
add x13, x13, x10
add x13, x13, x12


То есть цепочка из 3, когда увидел, прям ощутились оптимизации, на которые забили, когда смотрели на код x86. И такие вещи забавно прослеживаются, когда смотришь декомпиляцию clang под Arm -- много оптимизаций или их отсутствие как на платформе x86.

GCC, кстати получше это делает

        add     x1, x4, x1
add x6, x3, x2
add x1, x6, x1


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

Поиграться: https://gcc.godbolt.org/z/1nozoz1M4
👍109😱27👏7🔥5🌭5🤡3
Для выполнения работы (goodput от good and throughput/output) на CPU программам необходим доступ к RAM. Скорость, с которой программы могут передавать данные в/из оперативной памяти, не растет так быстро, как производительность процессоров, получающие новые фичи на каждое ядро и большее количество ядер.

В 95-2000 все много рассказывали про Memory Wall, что мол, DRAM не будет расти так быстро. Это уже реальность, не растёт.

В целом доступ к RAM остался в около 100ns, даже если вы меняете один процессор на другой, вы получаете меньше преимуществ, если вы постоянно промахиваетесь по кешам. L1/L2/L3 растут, да, но и там есть предел, и вряд ли они будут больше сотни мегабайт. Поэтому когда вы оптимизируете программу, очень полезно посмотреть на так называемые LLC (Last Level Cache) Misses.

Советы тут какие-то дурацкие, мол

1. Никогда не используйте структуру linked list, это промах по памяти на каждую итерацию
2. Не используйте бакетные хеш таблицы, они очень плохи, так как промахиваются постоянно. Используйте хэш таблицы с открытой адресацией
3. Лишний раз не копируйте объекты и тут языки вроде C/C++/Rust выигрывают, потому что там явно указываешь, что копировать, а что нет
4. Делаете по возможности структуры более компактными

struct Data {
int id;
std::string name;
};


Если будете итерироваться и использовать id в векторе/слайсе чаще, процессор хуже будет класть данные в кеши, по возможности, когда это очень важно, делаете два отдельных вектора id и name.

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

6. Если объекты логически большие, структурные как json или protobuf, создавайте арены/memory pool, когда вы кладёте много объектов на один и тот же кусок памяти. Самый простой пример -- вектор строк, если строки разбросаны в памяти, то даже банальные операции типа сортировки будут в разы медленнее не потому, что строки надо больше сравнивать, а потому, что всегда есть плата пойти в память. Поэтому строки со Small String Optimization и пишут в библиотеках, плюс они выигрывают на скейле.

7. Если вы можете утилизировать память, делать более предсказуемой доступы, то вы будете выигрывать у других приложений. Пример -- ClickHouse хорошо понял историю поколоночного формата, потому что памяти так удобнее: утилизация всего сервера в итоге растёт. Библиотеки вроде ZSTD просто напичканы software prefetches, а процессоры Intel/AMD/ARM делают отдельные инструкции для копирования памяти произвольного размера.

8. Обрабатывайте меньше данных в памяти. Сжатие как минимум, как максимум -- слежка сколько вы тратите на пользователя/entity данных. Я находил на своём опыте какие-то огромные пробелы в том, зачем мы храним столько данных. Хоть и бизнесы скейлятся, как правило начинается бардак в схемах/логах. Детектить такие вещи тяжело. SQL со своими селективными предикатами здесь побеждает обычные языки программирования и MapReduce, в последнем надо писать код -- ставить трекеры на форматы в компилируемых языках тяжело.


Развитие SIMD, больше правильных структурированных форматов, подстройка парсеров под данные, самокорректирующиеся под data оптимизации вроде JIT будут доминировать в ближайшее время развитие data proc. Истории с прорывами происходят вроде SIMDJSON и тд, но никакого систематичного решения пока не видно, эта область имеет шансы сильно развиться или умереть, принимая, что это в какой-то степени предел и надо думать в других направлениях типа GPU/TPU/Quantum/FPGA/etc.

В Google мы репортим среднюю утилизацию сервера в 60% и проблемы с памятью одни из самых противных -- данных просто тьма, решения вроде использовать flat_hash_map, а не unordered_map помогают лишь держать это число на плаву. Тот, кто поймёт эту историю лучше всего, будет платить за датацентры меньше всего денег.

В эпоху рецессии кажется это может быть ещё более важно. Постараюсь сделать серию из постов про то, как увеличивать полезность при помощи уменьшения процессинга памяти. Тут много нетривиальных компромиссов.
🔥122👍3110👏2
1. Выложили Silifuzz https://github.com/google/silifuzz/

Теперь у нас есть open source тулы как фаззить процессоры. Одно дело у нас есть свой зоопарк железа, другое -- может пригодиться многим другим. Напомню коротко, что идея брать корпусы у эмуляторов и, о вау, это уже достаточно, чтобы находить баги в процессорах. Новость получила слишком мало охвата. Пока x86, над Arm'ами работают коллеги

2. У меня полностью отменилась поездка в США и вообще чёрт знает, когда я встречусь со своей командой. Google какие-то решения сверху выдал непонятные, посмотрим, куда это приведёт, но зато у меня есть целая неделя вне саммита. Попишу кода.

3. На процессорах Arm оказалось, что парсить протобуфы можно даже быстрее, чем на x86. Всё это благодаря иструкциям ubfx (bit field extract) -- оно может брать любое количество бит внутри регистра и делать из этого число. Так как у протобуфов каждый из байтов имеет 7 бит со значением, получается быстрее. Мы выложили эти оптимизации и теперь пост выше про tree reduction имеет больше смысла -- советую почитать описание и код. Мы замучились заставить компилятор генерировать код, нужный нам

Ещё один check, что софтом на Arm'ах занимались как-то посредственно.

4. У меня есть идея написать гайд как у Agner Fog про серверные и клиентские процессоры Arm. У маэстро всё про x86, многие пользуются им, а про Arm почти ничего нет.

5. Я не очень понимаю, как софт подвержен энтропии. Я понимаю, что всё в мире ей подвержено, но недавно мы нашли в своём проекте баг, который kept me up at night, к сожалению сломались транзакционные гарантии. Баг был в коде как минимум 7 лет. Мы его починили, но оценить, сколько пользователей просто не заметило потерянных данных непонятно как. Остаётся только разводить руки, но осознание, что никакое тестирование его не поймало просто ужасное. И что поймать такие вещи в проде худшее, что может случиться с инфраструктурой. Да и воспроизвели мы его только в проде. И починили, смотря на метрику в проде. Локально воспроизвести не получается никак.

6. Блог на community.arm получил достаточно много референсов у разработчиков (в том числе Lemire), делиться вещами надо, кажется я рассказал о том, что болело у разработчиков библиотек (раз, два, три, четыре, пять).



Я хочу стримить, как я пишу код. У меня возникает откуда-то странное желание это делать. Насмотрелся на George Hotz, наверное.

Чёт сумбурно, но продуктивность хлещет, начинается мой любимый сезон года, осень, зима, когда можно уютно что-то делать
🔥85👍2916❤‍🔥3😱1💔1
Это будет не очень технический пост.

Как человек немного олдскульного типа для которого сильно важен текст, я с огорчением смотрю, как текстовый поиск по интернету потихоньку начинает проигрывать short video based формату, а.к.а. TikTok [1]. Много репортов о том, что Gen Z начинает там больше искать информацию и меньше предпочитает стандартные поисковики типа Google или Яндекс. Да даже я тому же ютубу не сильно рад, но, видимо, мы такие человеки, что любим смотреть на людей, и это удобнее, посмотреть рецепт/упражнение/интерьер за 10-15 секунд.

К ТикТоку можно относиться по-разному -- кто-то считает это гениальным изобретением, кто-то полным сатанизмом. Про себя скажу, что TikTok на меня влияет достаточно плохо, мой attention span уменьшается, а как инженер я сильно люблю концентрироваться на чём-то. После даже 15 минут TikTok меня заставляет чувствовать тревожно. То же происходит с Instagram и Youtube Shorts. Но и позитивные вещи есть, больше видишь разнообразия, больше осведомлённость и осознания о социальных движениях. Humanitarian idea of being always connected to people воплащается в бесконечном объёме.

Да, наверное, будучи даже самим представителем вида Gen Z, я понимаю, почему TikTok или Reddit чувствуются как след шаг: аутентичность. Когда работал в поиске, одна из самых тяжелых задач -- как балансировать между качеством (релевантностью) и "кликбейтом" (можно сказать, пользовательскими предпочтениями). Первое рассказывает правду, второе заставляет людей возвращаться на платформу. Сухая правда людям не нравится, второе на долгой дистанции деградирует доверие. Баланс, проведение границы всегда невозможно тяжелый вопрос, на который нет ответа. Где накрутка Search Engine Optimization (SEO), а где реальный и полезный контент. Это были самые сложные вопросы даже для разработчика бекенда как я. Я любил и люблю шутить, что все проблемы в мире это либо scaling, либо draw the line проблемы -- как расшириться и где провести границу. Интересно, что алгоритм TikTok страдает как-то меньше в сознании людей от SEO, может быть, не успели накрутить или понять как накручивать. Я точно уверен, что со временем это будет одна из самых тяжелых проблем.

В Китае есть приложение RED [2] с очень похожими отзывыми (и какими-то заоблачными 4.9/5), что Baidu кажется скучным, а вот на RED можно делиться короткими видео и быть КРИЭЙТОРОМ, сделать сайтик самому сложнее. Понравился отзыв: Baidu is full of theoretical knowledge. On RED, you see experiences from real people. Скорее всего и Google и Яндекс ждёт что-то похожее. Пообщавшись с некоторыми людьми, слыша фразу "Google is kinda boring", волосы дыбом, мол, вы даже не представляете, что надо сделать, чтобы запустить поисковики на сотни миллиардов документов. Boring, блин :)

Тем не менее, вот Reddit люблю, но какие же не очень поиски у TikTok/Reddit/Twitter, реально надо прийти и сделать им нормально.

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

По природе мы все любим людей, теперь люди стали везде и всюду с этими платформами.

[1] https://www.theverge.com/23365101/tiktok-search-google-replacement
[2] https://apps.apple.com/us/app/%E5%B0%8F%E7%BA%A2%E4%B9%A6-%E6%A0%87%E8%AE%B0%E6%88%91%E7%9A%84%E7%94%9F%E6%B4%BB/id741292507
🔥46👍34😢7👎3🤬31