Otterbrix — опенсорс-система хранения и обработки
Здравствуйте, дамы и господа.
Сегодня попробуем поговорить скорее про такую немножко жизненную историю, как немножко с детективным заворотом, потому что так оказалось, что вроде ты такой сидишь, вне работы.
Занимаешься, ну, как бы, улучшаешь мир с помощью open source, как сказали, до этого, а при этом как бы
А ты как бы пишешь такой солидный код, вроде все хорошо, вроде тестов много, но все время бывает прикол.
И вот сегодняшняя история, она очень с одной стороны жизненная, с другой стороны, если вы захотите на это вживую посмотреть, на это можно будет вживую посмотреть, потому что это все выложено.
Вот.
И поэтому начнём немножко с того, что когда я не пишу Open Source, я пытаюсь всяческими способами читать разные умные вейтпейперы, статейки и так далее, и когда у меня сил хватает, я как бы читаю, ещё overview пишу на его.
Но вервью у меня хватает максимум на 5 строк, поэтому не надейте, что там такое.
Прочел статью на 50 страдей, сейчас на целую страницу вервью нет.
Там в лучшем случае пара строк.
Хорошая статья, плохая статья и стоит не стоит.
Вот, я, как сказали выше, лучший мир с помощью open-source, поэтому про все то, что я сегодня буду рассказывать, можно будет посмотреть как раз-таки в open-source-ном проекте, у нас там по комитикам разбита немножко потерли историю, потому что я фанат сквоши, что одна фича в одном бронче, за это меня коллеги не любят по open-source-у, но скоро исправимся.
Поэтому детективность будет чуть лучше разрабатываться.
Вот, давайте попробуем... Некоторая предыстория от Жены была рассказана, давайте попробуем теперь представить, что вот мы все здесь и плюс-плюс программистами.
Вот мы каждый день ходим, пишем на си-плюс-плюсе, кто-то на Кононе, кто-то на Симейках, кто-то еще как.
Ну такая насыщенная жизнь.
А есть другой параллельный мир.
Есть параллельный мир даты инженеров.
Вот эти даты инженеры как бы, они как бы пишут там или на ямлах, или на инструментах, и еще на самом деле вокруг этого ямла накручивают.
И вот большая часть отробликса, это то, как умея работать с кучей форматов, да, то инженер пытается там собрать как-то свой код и жить с ним.
Почему я вообще про это рассказываю?
Потому что нам приходится весь... Мне пришлось в какой-то момент во всем слов разобраться, потому что я просто улучшить мир и... Я придумал, короче, тулов.
Она классная, вот верьте мне, это же так не работает, надо разобраться все-таки немножко.
И вот люди, как обычно, даты инженеры там работают своими другими форматами, делают много разных страшных выборок.
А почему нас это волнует?
Ну, потому что мы умеем работать с колонками их форматами, мы умеем работать с Джейсоном и документа подобными структурами.
Мы умеем работать с классическими строками.
И все это запихнуто в документ.
Прошу прощения, запихнуто это в отрабрикс, а работает это на самом деле вот такая магия, конвертация формат на документах.
И для нас документы в каком-нибудь этой степени, если мы с ходу не смогли определить, что ЦСВ, этот ЦСВ-файл в нем колонки, то на самом деле мы очень хитро, в помощи в ритик запихаем это все в хитрые документы, а потом дата инженера придется сказать, конвертними это.
Поэтому на документы накладываются много требований по производительности.
Поэтому я не разрешаю коллегам по Open Source закоммитить что-то, если у меня происходит выбивание перспособлённых сенсоров на документах.
Вот видим проблемы на документах, мы не можем такой умерть.
Документы в целом выглядят достаточно примитивно.
Не поверите, есть класс, в нем есть некоторые такие абстракты в данный момент как Jason Pointer.
Jason Pointer, по сути, это флотилизация путей в Джейсоне.
Но в специальном формате, по нему есть RFC, все красиво, люди с этим как-то живут.
Удобно.
В большей степени все наши абстракции хранения сводятся к юник-поинтеру, массиву и сайзу, сколько там лежит.
В целом это большая часть наших абстракций, потому что мы пытаемся все очень или плоскими сделать, или очень однородными.
Для того, чтобы была некоторая динамика, потому что если ты пытаешься сделать плоским, то нужна какая-то магия динамики, чтобы это было быстро добавлять элементы, удалять, потому что ты не можешь посерединки разведать.
Поэтому у нас есть некоторые деревцы, которые по миксам между Radex 3Splay 3, которые позволяют быстро-быстро добавлять элементы или быстро удалять.
И делать другие действия очень быстро.
У нас есть некоторые магии того, как мы балабы кодируем.
И есть немножко магии про то честно подсмотренному позгрессу, как правильно в балабе разместить инт, чтобы балаб с диска быстро поднять.
Когда мы создаём, читаем или ещё что-то делаем с документами, с диск или ещё где-то, у нас, в принципе, вот такой очень простой и понятный интерфейс.
Под капотом у нас есть блоб, к блобу добавлены немножечко абстракции про наши динамические деревья, которые с месерадикс, eSplay.
Которые, по сути, это очень быстрый доступ, чтобы каждый раз по большим баллобам не искать.
И каждый раз, когда мы хотим что-то обновить в нём, мы пытаемся сделать это in-place.
Вот если мы число можем подменить не персадовый блок, прекрасно.
А вот если нам не повезло и нам строчек надо поменять, да, мы создадим ещё один блок правильного размера, раздвинемся, используя статистику и аналитику сбоку, мы как бы подгадаем размер.
Если, ну, и соответственно, или мы ищем старым блобей, или в новых блобах, ну ищем свободное место, куда добавить новый элемент.
Дальше самая частая операция для нашей — это merge-split-delete.
Почему это так?
Потому что через merge-split и на самом деле update можно выразить практически все наши действия, потому что, ну, когда у тебя система, которая перебирает данные, в целом выражается всё через это.
И в данной задачке нам надо очень компактненько смёрзнуть объекты по полям.
И мы всячески делаем следующую магию.
Когда мы создаем новый документ, мы всячески пытаемся сняться.
Вот мы до последнего была бы пытаемся переспользовать всякие логические связи и максимально защищаться от этого.
Не всегда получается, но бывает.
Вот.
И в целом интерфейс, который мы тут используем, тоже очень простой и лаконичный.
За этой лаконичностью скрывается какое-то количество проблем, но мы сейчас начнём с того, что будем, так сказать, клубочек... Вот мы такие умные, красивые, специально к этому конференции делали релиз.
И где-то полгода назад, может быть, примерно, мы как бы...
Я заставил все по бенчмарке, именно то, что касается документов.
Потому что документы для нас это важно, потому что они являются с нами в точке входа, и если мы типа не понимаем колонки строки или еще что-то, то мы в документе пишем это хитрыми способами.
Вот.
Наш бенчмарк логический разбит на то, что у нас есть 40% флукапов, мерзжи сплиты по 30%, апдейты и делиты по 15%.
Мы полагаем, что это наиболее частое использование, потому что мы некоторую статистику собрали от тех людей, которые пришли и сказали, мы попользовались вашим ампансорством инструментом, он ни фига не работает, но вот как мы с ним работали, мы такие, о, круто, фитбек, фитбек это работали, придумали бенчмаркез, используя именно то поведение, которое наиболее популярное и частное.
и получили некоторые непонятные цифраки.
Некоторые непонятные цифраки практуют, так, 900 операций в секунду.
Вот как раз тех, про которые я говорил.
И 900 операций в секунду — это не 900 тысяч, это просто 900, там 900 плюс операций в секунду.
Это маловато, очень маловато.
И мы задались двумя вопросами.
точнее одним вопросом и одним утверждением вопрос первый а кажется наш кот ну судя по тому что мы там посмотрели в перф а все же тут пользуется перфом нет ну какой же перф анализатор то есть есть я вижу ручки неправда вот есть разные способы как профилировать мы как бы все любим профилировать мы в диасемблер можем посмотреть как бы мы вроде очень умные как бы
Мы на всякие ядерные каунтеры смотреть, на все посмотрели, выяснили первое.
Наши функции недостаточно местами оптимизированы там, где они оптимизируются.
Это первая проблема.
Вторая проблема.
Мы неправильно работаем с аллокатором, потому что мы можем попросить там, где, не знаю, нам надо 16 килобайт, мы почему-то против, или наоборот, меньше, или наоборот, больше.
И вот с этим вопросом и этим утверждением мы пошли изучать.
Давайте попробуем немножечко подумать сначала про вопрос.
и посмотрим на маленький кусок бенчмарка, читать его бесполезно, я его лучше голосом не расскажу.
В первой части мы просто тупо читаем что-то в документе.
Во второй части мы или апдейтим, или пишем новые поля.
А в последней части мы или что-нибудь удаляем, или что-нибудь модифицируем.
И после нехитрого анализа оказалось, что на самом деле в секции 2 у нас очень много Нью, в секции 3 у нас очень много Делетов.
Мы это посмотрели, потом начали использовать технологии, которые нам предпогонялись с нулевых, пристально посмотрели в код.
Нашли там на самую функцию почти по 1000 строк, мы творчески предактировали их на ресурс, самое интересное.
Там есть какой-то начальный интересный payload, есть New, и потом еще какой-то полезный payload.
Мы так смотрели долго на этот код и думали, что вся функция оптимизируется.
Мы долго смотрели, потом посмотрели в диасемблер, потом еще раз посмотрели правильнее, оказывается, что функция оптимизится сначала и до Нью, и после Нью она оптимизируется.
Мы так думаем, наверное, О3-то поможет, мы же знаем все святое О3.
Мы всегда знаем, что если что-то плохо работает, надо О3 добавить.
Потом, как бы ловить баги, потому что оптимизация не такие.
Мы так не сделали, мы как бы пошли и дальше посмотрели.
А мы же хитрые ребята.
Мы как бы и свои операторы Нью написали.
Мы там разгребли эту страшную портянку странного кода.
И нашли, что вот там всё равно честно вызывается молок с хитрым набором параметров не всегда, поэтому перст страдает не всегда.
Мы нашли, вот там есть молок где-то.
Мы потом так долго пристально подумали, подумали, что вот такого может быть у молока и заглянули в ман.
А в мане как бы крас, черным или крас, ну как
Вообще, формально, это красный, но тут, наверное, это чёрный.
Чёрным, по-красному, белым, на синим написано, что молок, фри, колок и реолок, вообще-то они третсейф.
Потом мы такие подумали, ага, они третсейф.
Пойдемте посмотрим, что стандарт говорит про барьеры памяти.
Такие полистали, стандарт немножечко, часика полтора.
Нашли интересный момент, что вот как бы, если что, компилятор не разрешит вам, если вы его неправильно расставили, он не позволит вам переупорядочить.
Для нас, как бы, мы вроде умеем при алгоритме писать, но вот как бы, мне пришлось за свою жизнь три очереди написать и один буфер-пул.
Кстати, последние два года я в нем нашел бак.
Но не важно, это не означает, что я умею писать код или не умею писать.
Это все не важно.
Важно, что компилятор не позволяет перепределять последовательность.
Если у него расставлено таким образом барьеры, и если вы что-то делаете, то это как бы ватер-линия.
оптимизирует стоп две части.
Мы такие подумали, а что есть в стандарте, чтобы решить эту проблему?
То есть, чтобы молок, на самом деле, не звался.
И нашли часть решения.
Но перед тем, как сказать его, мы долго смотрели на вызовы, которые бывают.
И нашли два самых интересных.
Два самых интересных оказалось в том, что позволяет поверь уже существующего куска памяти.
создать объект.
Мы сразу иной к сэпты там получаем, бесплатно.
И мы получаем кучу разных плюшек.
Мы сказали, да, победа.
Давайте немножко разберемся, как этим пользоваться.
Написали простой классец.
Экземпл, бла-бла-бла, самый интересный последний его срочек.
Да, написано.
Олигнов, бла-бла-бла, массив байтов с правильным размером по сайзову и позвать нью на уже существующий буфер.
Все, прекрасно.
Только что мы создали объектик, с которым мы можем существовать.
Есть нюанс с таким массивчиком.
Массивчик, самое главное, чтобы сначала умер ваш класс, а потом умер ваш массивчик на стеки, иначе будут проблемы.
Но, если вы, так как это всего лишь пример, вы так, надеюсь, реально в коде не поступаете, так и все-таки некоторые демонстрации о логике, а не продовый код.
Помечу, не продовый код.
Поэтому там можно и по-другому получить буферочек.
И кажется, мы нащупали часть решения проблемы.
Мы знаем, как из нее выкинуть молок.
Мы знаем, как правильно получить много на халяву в интересных моментах.
Остается другая проблема.
Мы неэффективно работаем с молоком.
Тут мы как бы не пальцем делаем, мы как бы вспоминали, что вообще-то есть ареналокатор.
Его придумали там еще, кажется, когда там версия линукса.
Было чуть ли не первые они сказали, что аллацировать впрямую плохо, надо аллацировать по-умному.
И придумали какую-то разновидность.
Ну вот там есть какая-то эволюция всех арен алкаторов.
Но вот я, мы примерно вот такую накопали, нам как бы с ней хорошо, что арена делится на некоторые сабклассы.
Сабклассами являются слабы.
У слабов есть чанки, чанков может быть много.
И чанк это некоторые или управляемые, или неуправляемые существа.
которая живет в зависимости от того, какие критерии вы дали слабу.
Если вы в виде говорите, что у вас ревкаунтная база, значит под капотом будет немножко ревкаунтной базы, будет немножко дорогой ареналокатор.
Но мы не очень любим ревкаунтной базы, потому что с ними больно обычно.
Обычно лучше прямого управления.
И в целом мы как бы начали думать, как нам с этим совсем жить.
Мы знаем, что у нас уже часть решения про Нью.
У нас есть идея, что нам нужен ареналокатор.
И дальше мы как бы начинаем смотреть C++ и вспоминать, что до C++ 17-го
не было такой особенности у аллокаторов, что они вообще-то были без стейта.
Кто про это знал, кстати?
Просто что у аллокаторов нет стейта.
Блин, не 50%.
А мы просто при подготовке доклада мы долго спорили, надо про это рассказать, или нет, я победил.
Так вот, у аллокаторов не было стейта, и самый главный момент в этом во всем, а все, кто пытались у аллокатора донести стейт, это обычно был сингл-тон, ну, чаще всего сингл-тон.
И самое главное, в 90...
Процент в имплементации я видел UB, а адрес UB Sanitizer показал, что там топ-удова есть.
Ну, просто потому, что для него это как колдунство было, надо специально размечать его, чтобы UB Sanitizer короче не страдал.
И в целом до C++17 очень было больно.
Потом пришел C++17.
И, как вы думаете, правильно.
Они там, если что, в 11 стандарте аллокаторы переделали в 14.
И в 17.
переделали и теперь слава богу у нас у аллокаторов есть стейт и у нас юбиса не так будет чуть меньше ругаться адрес санитайзер будет хорошо работ надо его немножко будет размечать но кроме того себе приходится плюс-плюс 17 к нам кроме аллокаторов пришли memory ресурсы memory ресурсы чудесная вещь это чуть ли не первый интерфейс который существует который в стандартную библиотеку добавили виртуальные методы причем
Люди, когда добавляли интерфейс, они потратили кучу денег для того, чтобы доказать, что все почти что виртуальные методы будут средны, если там сделал парочку простых действий.
советую почитать в интернете, чтобы я это творчески не пересказывал, но не пугайте, что у вас там четыре виртуальных метода, они на самом деле срезаются, а не срезаются за счет того, что они или в протекте, или в приват части находятся.
А если у вас там не три уровня наследования, то и на самом деле будет резолвский деструктор.
Там надо чуть-чуть пошваманить,
Версию компилятора с выше 14 кланга вообще все хорошо.
На GTC11 и выше проблем не замечено.
Мы просто активно тестироваемся против разных компиляторов.
Про MVC ничего не знаю, но знаю, что MVC, которая поддержит 23-й стандарт более чем, тоже решает эту проблему.
Так вот, очень простой интерфейс.
В чем его простота?
У него есть аллог и сравнить и деструктор.
Нам больше ничего не надо.
Все остальные методы, они лежат, вызываются или в приваре протекции у нас ледников.
Все прекрасно.
Самое главное, главная точка кастомизации этого всего конструктора, нам абсолютно доступны.
Тот, кто придумывал этот инфрей, реально очень много вложил силы времени в это.
Но в стандарт не только интерфейси завезли еще какое-то количество разных институтов, чтобы не только так сказать, не с нуля им плементить.
Что интересного?
Memory Resource Unsynchronized Pool.
В целом, это ничто иное, как пулы, лог, фри листы и так далее.
Ничего умного.
Но ваш момент, который надо заметить здесь, кроме того, что он управляет разными объемами объектов, умеете туда-сюда превращать, он работает в Сингл Тредде.
Мульти Тредда нет.
Поэтому я обещал вам пулы фрелесты и немножко магии фрелесты, пулы фрелесты и так далее, и манипуляции с разного размера объектиков.
Есть синхронайст пул, который просто.
Самое главное, что смотришь в код и видишь, что там, что правильно.
Эта версия не самая эффективная.
Однопоточные гораздо более эффективные, но в целом норм.
Дальше, нам завезли такую штуку, как монотик-буфер.
Монотик-буфер прекрасен.
Во-первых, он однопоточный, а мы любим однопоточные оптимизации, на что их просто и дешево и легко.
Он не диалацирует объекты, он выдает объекты максимально быстро.
Почти умеет работать со стеком, умеет работать без стека, но самое главное ты ему можешь выдать буфер, поверх которого он будет работать, а он будет туда максимально эффективно и быстро запихивать объекты и доставать объекты.
Самое важное, что надо.
Но кроме этого завезли немножечко полезных функций.
А первых добавили memory-ресурс, который ведет себя как просто нью-иделет, в котором запихнули его в новую интерфейс.
Удобно, удобно.
Нужно ли это?
Иногда, когда ты дебаш сложный случай, да.
Для чего нужен new memory-ресурс?
На самом деле, он нужен для нового итога.
Чтобы проверить, что ресурс был проинициализирован, потому что если он не проинициализирован, то его начало проверить с new memory-ресурсом,
А если он проницелизирован, значит, он будет неравенным.
Все просто.
Дальше.
Дальше завезли немножко в стандарт, как я считаю, немножко бесполезные вещи.
Это GetDefaultResort и SetDefaultResort.
Что это такое?
Одно из глобального установлено на все приложения, зависимость от компилятора или дешевым месте, или дорогому, возможно, это сингл-тон, возможно, и сингл-тон.
лежит memory-ресурс, который вы можете получить.
Другим способом вы просто можете на все приложение установить этот memory-ресурс.
Я лично предпочитаю явно в коде «пробрасывать» и не использую вот эти две проклятые функции, но, к сожалению, на них можно подорваться.
Дальше, чтобы объединить два мира в один, добавили полиморфолокатор, в том числе.
Что это такое?
По сути, это некоторая прослойка, которая позволяет объединить мемори ресурсы и объединить все весь остальной мира.
Естественно, нам завезли стандартные TypeDef для Vector, StringList, а нет там не уникальной имплементации.
Зачем нам не уникальной имплементации?
Все просто понятно, просто TypeDef подменили аллокатор.
Но есть ниванс, что-то там забыли со Smart Pointer'ами.
А эти попробуем про смарт-поинтер и немножко поговорить в двух часах.
Но мы начнем с того.
А все знают, кто видел внутри юник-поинтеру встроенный или шарит-поинтер?
Ой, прекрасная аудитория, мне прям нравится.
Давайте попробуем начать с одной стороны простого, но при этом с самого сложного.
Это Шарит Пойнтер.
Если пристально посмотреть, я ничего нового не рассказываю, там есть Пойнтер, есть Control Blob, там есть Riff Counter на Strong, Vick и Riff, но есть подстава, которую неявная.
Так как он пытается быть Type Rager,
то там есть и, во-первых, кастом дилитер, а, во-вторых, там есть аллокатор.
И если вы, как бы, явно не подложите аллокатор, то он будет попробован выведен.
И это большая часть проблемы, потому что из-за того, что там аллокатор в неявном виде просовывается и Type-Ranger отрабатывается, то баги с шарит-поинтером менее очевидны, когда вы используете ПМР.
Я советую там два раза пристально посмотреть и тесты написать.
Поэтому снимка попроще с одной стороны, а с другой стороны есть веселые баги, на которых можно подорваться.
Я думаю, что через пару лет будут веселые вопросы на собеса.
С юник-поинтером у нас произошла интересная ситуация.
У нас в команде есть я и еще пара людей.
Я не пишу большую часть кода, я пишу те части, которые за перформанс отвечают.
У нас есть коллега, который с C++ в сюжете на 11-м и 14-м перешел на 17-м.
И он написал очень понятный простой кусочек кода, который выглядит так.
Берем нью-ди-лет ресурс.
считаем сайсзов от Лонга, потом оликов от Лонга, потом алоцируем буфер, создаем этот буфер, потом мы же умные люди, мы же не хотим менеджерить у поинтера руками, мы тут как бы в умный код пишем, а не поинтер и менеджер, ну в юник-поинтер, и в принципе долгое время этот код работал, и в тестах работал, и в бенчмарках работал, а потом мы какой-то момент
кто-то у нас в команде фелл и творчески подменил.
Один memory resource, на другой memory resource.
И у нас начался double corruption.
Причем стабильно.
Как бы double frid, или там, или corruption.
В зависимости того, как нам не повезло.
Мы такие долго-долго смотрели, а потом как бы очень быстро нашли, что вообще-то в Unic Pointer имплементация отличается от Shared Pointer.
А помните, я вам рассказал, что там есть custom deleter и allocator выводится.
и это все нужно для Type-Ranger.
И оно не стреляло у нас в нашей pointer, потому что deleter был default, но аллокатор там подсовывался, и мы выносили, а в Unic pointer имплементация это проще.
И там как бы нет custom deleter, мы такие быстро-быстро посмотрели, ну ладно, быстро, суммарно мы смогли пару дней разобраться как бы в этом и всем.
Потому что ты же смотришь на этот stacktrace огромный, не понимаешь, что происходит.
Мы такие посмотрели и очень быстро написали fix, просто написали custom deleter,
У нас в коде это выражено слава тебе господи не через стедефанкшену, потому что я не очень люблю стедефанкшену, потому что внутри есть буфер, который мешает производительности.
Мы скорее это на функционной писали плюс лямда, но в целом как-то выглядит примерно вот так.
Фикс выглядит вот так.
Очень простой.
И это что означает что?
Если вы аллоцируете memory ресурсом, пожалуйста, диаллоцируйте с помощью memory ресурса.
Иначе могут быть прикольные ситуации, про которые вы не знаете.
Потому что вы позвали Deleted, у вас код почистился, а потом, когда будет убиваться пол, он за собой попробует удалить, у него есть указатели, и он попробует их дробнуть.
Поэтому что?
Правильно, диаллоцируем, только с помощью того ресурсона, с помощью которого проаллоцируем.
Давайте попробуем.
Я вам обещал арену.
Я вам все это время рассказываю какие-то байки, но мы к арене не приближаемся.
Давайте попробуем поговорить про эту простенькую арену.
Мы взяли СД Рей.
Сказали, что там 128 элементиков.
Сказали, что это бафер.
Взяли наш самый любимый, самый быстрый в мире, монотик-буфер.
Запихали его туда.
И взяли полиморфалокатер.
И полиморфалокатер запихали в сторочь, которая на самом деле векторинтов.
Самая простая арена, правда она не расширяемая, но мы это сейчас поправим творчески.
Самое главное, что вот самая простая арена, написано там 4 или 5 строк, все работает прекрасно быстро.
Но нам надо как-то расширять арены.
Мы не можем, конечно, пойти, взять у системы 32-гега и жить с ними, но на практике это не очень хорошо.
Потому что иногда бывают и другие приложения на машине, надо как бы уважать людей.
Поэтому мы долго посмотрев и увидели несколько нужных нам конструкторов.
Эти конструкторы называются параметром обстрим.
Если присмотреться в код одного из них, то можно увидеть, что на самом деле в тот момент, когда мы расходовали, так сказать,
наше external буфер, то мы можем пойти попросить более большой буфер, дай нам еще буфер, но точнее в данном случае memory resource.
По default там опять стоит new delete resource, но как бы мы же нормальные люди, мы-то знаем, что надо туда просунуть правильный memory resource, который вам будет давать на арене.
И тем самым благодаря тому, что у нас есть upstream memory resource, мы можем строить более сложные аренки.
Более сложная аренка, у нас есть все еще три наших буфера, только уже разные размерности.
У нас есть монотики, мы пытаемся так сказать строить.
И у нас получается, что есть большая аренка, маленькая и средняя аренка.
И все это запихивается.
Простой код, написанный не пятнадцатью синюр-инженерами за пять лет, а моим коллегой за пару часов.
Долго посмотрели и говорили, в целом, это норм.
Вопрос, как нам теперь жить с тем, что у нас там статические буфера, надо что-то придумывать.
Но мы придумали, мы как бы честно пошли, отнаследовались от СДП лиморского ресурса, назвали его честно ареной, заимлементировали три метода, немножко доложили логики в конструкторы, потому что там иногда бывает ситуация, когда надо арену...
с гигабайта.
Потом создали арену, в нашу простую конструкцию из монотик буферов подложили арены, задали правильные чисто, подложили в вектор.
Все, профит.
Больше степени было использовано все из стандартной библиотеки и немножечко расширили, но нам же дали возможность дешево расширить.
Мы дешево расширились.
Давайте попробуем.
У меня есть веселый следующий слайд.
Давайте быстренько.
Кто думает, что количество уменьшилось?
Ладно, хорошо.
Не смог продать в этой идее.
Кто думает, что увеличил много раз?
Ну хорошо, в два.
Нет, в три.
Количество операций выполняю в секунду, да.
Ну ладно, не смог вам идею продать, я просто покажу.
Практически мы это сделали с полтора, при этом как бы код был не самый гениальный.
Легким переписыванием и добавлением фрилеста на локфришная имплитация, фрилеста подаренные, переписыванием, нам еще пара штуков позволило еще раз в два ускориться.
Но надо объяснить, что это писал человек уровня Junior Plus.
Он это написал буквально за три дня.
смог пройти кучу тестов, и у него получилось вырваться вперед чуть ли не в два раза, это 1600, против 900, которая была в лоб написана.
Поэтому я считаю, что это некоторая победа и вот меморий ресурс, я надеюсь, что это не первая ласточка, которая умерла, это некоторая ласточка, которая продолжит, что будут появляться дибкие управляемые абстракты в стандартной библиотеке.
Давайте попробуем к выводам.
Читать стандарты полезна, особенно вдумчивая, еще иногда перечитывать.
Но надо, к сожалению, экспериментировать, потому что комбинация фичей может стрелять.
Очевидно, очевидно.
Часто ли мы так делаем?
Не всегда, но бывает.
Особенно, если это конкарренция, локация памяти, мне приходится достаточно часто перечитывать стандарты, там бывают подводные камни.
А дальше, я советую использовать бенчмарки большие.
Не надо пытаться.
Вот то, что мы искусственно сделали такой бенчмарк, нам очень сильно повезло.
Лично мой совет, старайтесь в бенчмарк такой, как почти приложение или почти приложение.
Потому что как бы комбинация с шеей, плюс процессоры, плюс
Куча разных аспектов может в вашей бенчмарке выкручивать в разные стороны.
В принципе этим и занимался, допустим, компания которая монополизировала джаву.
Таким образом, что как бы они там десятилетиями занимались бенчмарк военными.
Я советую лучше брать приложение как бенчмарк, в крайних случаях выделять максимально большие куски.
Неожиданно мы смогли сделать релиз к этой конференции, и у нас есть свежий релиз, который можно на нем посмотреть и попробовать найти интересный момент, связанный с тем, как мы не правильно работали с ресурсами и так далее.
За всеми непонятными штуками можно последить на нашем гитхабе.
А если вам все это было интересно, новости тянетесь простить, можно взять мои контакты и просто написать мне в личку, я подскажу, что, зачем, как и почему.
Спасибо за внимание.
Давайте начнём с самого весёлого.
Именно стандарт перечитывать или себе переференция?
Это подстава, потому что некоторые части не написаны себе переференции.
Как раз такие проповедения барьеров, я как бы знал, потому что локфрини алгоритмы, но как бы мой коллега нашёл это, именно читая стандарт.
Поэтому тут скорее от ситуации к ситуации.
Так, вопрос по самому старту презентации, почему данные хранятся текстом, а не в бинарном виде.
Бинарные же будут компактны.
данной или наше внутреннее представление?
Ну нет, у нас бинарное, у нас всё хорошо, мы как раз, Б дерево почти допилили, а всё остальное у нас и так бинарное.
У нас документы имеют такой формат специальный, почему у нас там так много блобов?
У нас блобы ровны, потому что у нас кодирование плюс специальные касты позволяет без диссерализации поднимать диск, поэтому очень дешево и понятно.
Окей, вопрос.
Получается, во все места, где алоцируют память, умную казать ли векторы, мапы и прочие, нужно прокидывать в кастомный стейт фуллокатор?
Ну да.
К сожалению, без этого никак.
Нам комфортно.
А почему нет?
Я думаю, что в крупном рефакторинге внитрять это дело, где уже код написано и сложно.
Ну, у меня есть позитивный опыт, где я в одну библиотеку, которая занималась парсингом очень странного, предпередитарного формата, спустя окажется код в ИБАЗе лет 5 где-то.
Ну, я смог, короче, за пару недель туда добавить.
Потому что там главная проблема, ты, когда парсил файлы в этом страшном формате, типа припилитарным, он просто как ни в себя жрал партии.
Ну, потому что там нью-идель по месту сделано.
А за две недели я справился, а я не очень быстро программил.
Мне надо 20 зончиков сходить, потом у меня прошло 8 часов сазонов, потом у меня еще 8 часов пропрограммировать.
Поэтому я не очень быстро.
У меня получилось.
Понятно.
Вопрос.
Как хранится глобальный стейт аллокатора, кроме как через что-то типа синглтона?
У меня есть классные ответы, не используйтесь на глутом, пожалуйста.
Ну то есть я не просто так специально сделал ремарку на одном из слайдов, что, пожалуйста, вы можете для простоты использовать сет default ресурс и get default ресурс, но так делать не надо, потому что, к сожалению, вот эти диффункции, они немножко паразитные.
Если вы их слишком часто, то есть полеморф, аллокатор, если что, под капотом,
если ему не передать ресурс, он все еще пойдет и позовет гет-дефолс что-то там.
Поэтому у нас коде запрещено, у нас есть свои TypeDF на фектора, где запрещено обращение к этим функциям.
И необязательно синглотон, ну как бы я люблю прямое прокидывание, как бы я хочу знать, где я пролоцировался.
Это то же самое, как в concurrency коде, я хочу знать, на чем я исполняюсь.
Ну как бы логично же.
Тут такая же логика.
Вопрос про шейф ПТР, почему в стандартной имплементации шейф ПТР, который конструктор объявлен как дефолт?
Он же должен увеличивать референскаунт.
А это точно, вот я себе и думаю.
Хороший вопрос.
Да и так, я подумаю, отвечу, потом передай контакт.
После этого в чате ответишь на этот вопрос.
Хорошо, договорились.
Так, как лучше управлять временем в жизни полиморфного локатора и меморью ресурс, чтобы не разрушить их до контейнеров, которые они используют?
У меня есть глобальные правила, мы стартуем их в старте приложений и как бы всячески пытаемся в приложении сделать Grays of Shutdown, чтобы это было максимально беззависимым.
Других способов не завезли еще пока.
Но это лично то, как я считаю нужным.
Понятно.
Почему именно три уровня на арене?
На самом деле есть какая-то статья или PDF, в которой написано, что классический ареналокатор работает по принципу.
Большие объекты, средние маленькие.
Мы как бы эту логику попробовали максимально просто переложить на STL и чтобы сбалансировать.
Ой, мы пишем суперэффективный код против того, что этот код может им писать Junior Plus разработчик с подсказками.
Понятно.
И есть ещё вопрос по той самой функции, где Ю был посередине.
Что с ней всё-таки случилось, как она оптимизирована?
Не поверите, выкинули неё, заменили... Там документы у них появились, указатель на memory-ресурсы.
Мы просто на memory-ресурсе пролоцировали кусочек.
Просто каждый документ — это как бы комбинация чанков.
Это практически мини-флап.
Поэтому мы там, а каждый чанк — это почти что филд, потому что пытаемся это аккуратно сделать.
Поэтому там просто вместо New появилось... Там есть две вариации.
New, который на самом деле завез внутри этого класса с Allocation и Dialocation, потому что там есть перегрузка на New и Delet.
Это один лайфхак.
Второй лайфхак мы честно пошли, позвали Alloc и Dialoc на мою ресурсию.
Ох, чую, мне надо будет пересмотреть, еще раз стрелять заклад.
Вопрос.
Используются ли полиморфные аллокаторы вложенными в контейнер типами, если аллокатор передан только в контейнер?
Тут есть подстава не всегда явно.
То есть, там можно так научиться с таким набором перегрузок сделать, чтобы это работало.
Но лучше явно.
Потому что там есть как раз подстава полиморфолокатора.
Он может пойти взять гет-дефолта и всё пойдёт не так.
Поэтому лучше явно, чем не явно.
Понятно.
Ну, давай заключительный вопрос.
С крутинами эта штука нормально отработает?
О, нет.
Там целые исследования по трёп-гайдам, как собрать это в кучу, чтобы это просто заработало.
Не всё гладко.
Там надо переопределить, как оно отциривается.
Переопределить нью.
Там столько частей надо переопределить.
Но это можно сделать.
После меня будет чудесный спикер, который будет рассказывать про крутины.
Если его доклад объедини и из десяток статей, которые объясняют, как это смешать, то в день за пару недель можно разобраться.
Это одна из частей стандарта, которую ты читаешь.
Вот, короче, вот смотришь в код стандартной библиотеки, смотришь в стандарт.
Вот так, потому что объедините, а оно не объединяется, оно как магнитики такие.
Одинаковые полюса, её поразбегать.
Там немножко надо суперклееб, скотча, и нормально будет.
Короче, видимо, надо сделать просто доклад, как это сделать.
Обязательно.
Ну что ж, на этом спасибо.
Это было Александр Павлович.