voidlizard.online
116 subscribers
160 photos
6 videos
5 files
105 links
Haskell, распределённые системы.

Разработка P2P CAS hbs2 и приложений для него

Распределенный git aka hbs2-git

hbs2.net

Прочее https://t.me/genedrd47r (мото, EUC, скайдайвинг, дайвинг)
Download Telegram
Заняться ли приведением в порядок TCP PEX (сейчас не очень) или нарезанием лога операций git на сегменты, что бы он мог, наконец, прожевать большие репозитории? btw, добиться приемлемой скорости работы при импорте объектов в гит удалось крайне извращенным способом, который я вообще не имел ввиду. Я думал, что смогу генерировать дампы в формате fast-export, но нет. git, конечно, чудной. Есть команда, которая импортирует объект в гит в его нативном формате, git hash-object. так вот, у неё есть batch режим! но в нём ей в stdin можно пропихнуть только имя импортируемого файла, а не его контент. После разбития на сегменты, кстати, возникнет частичная дедупликация, хотя бы с на уровне сегментов и их частей. Остаётся подобрать размер сегмента. 10Mb? 50? 100?
Короче, чат гпт говорит, что надо hbs2-git допиливать, раз с кривым пексом всё работает, то глядишь, и еще поработает, всегда потом починишь. ну штош.
Вот что еще заметил: сейчас пишу в логи операции в порядке: (коммит, зависимости). Поскольку так удачно сложилось, что гит новые коммиты делает не дельтами, а все объекты целиком пишет, то что бы там разработчик не мутил - сквошил, мержил, ребейзил - итоговые блобы и деревья (снапшот проекта) — выглядят довольно константными. таким образом, если сначала в лог писать деревья и блобы, а в конец - коммиты, то есть шансы, что префикс лога будет более константным, что ли. т.е при последующем разбиении на сегменты есть шансы, что сегменты в начале лога будут лучше дедупиться.
huge-repo-import-2-2023-06-27_18.18.08.mkv
3.2 MB
Жуёт очень большой репозиторий nixpkgs. Около 4G в хорошо упакованном гитом виде, и очень много - в не особо хорошо упакованном. Жуём - в смысле успешно экспортировало в ссылку, а теперь делает git clone из неё
nixpkgs оказался очень классным стресс-тестом для hbs2-git и hbs2-peer, буду его и в дальнейшем использовать,
пока не станет всё хорошо. Вчера экспорт этого репозитория прошёл нормально и довольно быстро, а вот импорт (git clone)
поставил систему на колени (я не дождался и пристрелил, с течением времени скорость всё замедлялась). В частности потому,
что делается через файловую систему / tmpfs, и при распаковке миллиона
объектов на tmpfs - последней поплохело. Кроме того, написанный чатом гпт хаскельный кодик породил где-то мемори лики,
надо будет посмотреть. Правда, то при экспорте, и основным гадом оказывается haskell-language-server который жрёт 60% RAM,
если параллельно с тестами где-то у меня открыты редакторы. Что могу сказать по результатам. Кажется, логи hbs2-git ждёт
еще одно ломающее обновление. Но может быть, сделаю его неломающим. Сегментированный-то лог ничего не сломал, просто
порядок объектов поменялся на более правильный (блобы, деревья, коммиты) - всё примерно в топологическом порядке,
более поздние объекты ближе к концу. А вот целиковое сжатие потребует доп. обработки, но кажется, инфу о сжатии можно
добавить в метаданные и не делать изменение ломающим.

FIXME: mandatory-compress-whole-log
Эксперимент показал разницу в размере репозитория git и
соответствующего ему стейта hbs2-git приблизительно в 10 раз (!!).

Очевидно, что git сжимает даже лучше, чем мы бы просто сжали его
объекты архиватором, он проделывает еще некоторые дополнительные
манипуляции, к которым шёл годами.

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

Вопрос, ломать или не ломать при этом совместимость, т.е оставить ли
возможность несжатых логов.

Указывать ли информацию в аннотации дерева, либо же завести секцию
лога, указывающую, что за ней следуют сжатые данные.

Сжатие на уровне лога целиком нужно обязательно, т.к. сейчас мы
имеем стейт размера 36G вместо 3.5G на тестовом примере репозитория
nixpkgs.

Сжатие лога внутри секций неэффективно и, кажется, бесполезно.

Если его дропнуть, то поломается совместимость.

Если оставить, но поставить нулевую компрессию --- то будет
бесполезное замедление работы.

Сжимать на уровне лога целиком --- правильно.

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

На сжатии в памяти, кроме того, мы можем исчерпать память.

#hbs2 @hbs2git
Извините, что к вам обращаюсь. Поделитесь ссылкой на гит на репозиторий мегабайт на 100 - 200, или хотя бы идей, что бы это могло быть. Как-то в гитхабе нету опции "найти любой проект мегов на двести"
Клонируем openwrt из hbs2. 43M объектов, 57915 коммитов, размер до gc - 2.9Gb, после - 197M, клон (импорт) занял 4 минуты. Клон по https с гитхаба - 30 секунд. Ну то есть да, многое можно пооптимизировать, но надо учитывать, что когда git клонирует - он делает только свою работу. Когда clone по hbs2 - то там hbs2 делает работу, и git делает работу, т.е эти 30 секунд добавляются. С одной стороны — да, надо многое пооптимизировать. С другой стороны жить вроде уже можно.
FIDO ведь была DAG, вроде? можно прямо щас запиливать. Только решить - положить гипертекстовый векторный фидонет в гит. Или прямо поверх рефлогов делать
Forwarded from Dmitry Zuikov
fixme: hbs2://Fujv1Uy4W5d9Z7REEArMxbXSJ8nLLn4dYuvaAs8b86hr
Forwarded from Dmitry Zuikov
suckless-conf hbs2://JAuk1UJzZfbDGKVazSQU5yYQ3NGfk4gVeZzBCduf5TgQ
Forwarded from Dmitry Zuikov
ссылка в новом формате: сжатие всего сегмента gzip + указание этого факта в метаданных. надеюсь, теперь надолго

hbs2://BTThPdHKF8XnEq4m6wzbKHKA6geLFK4ydYhBXAqBdHSP
Есть вопрос на подумать. Что бы зависимости проектов завести тоже на hbs2-git, нужно сделать http адаптер. существующие сервят с какого-то репозитория (что логично), но мне кажется прям как-то не очень круто - клонить репозиторий и из него раздавать файлы. В прошлой итерации, когда каждый объект гита соответствовал объекту в hbs2 - была тривиальная реализация http сервера для гита. Сейчас это сжатый лог объектов. То, что он сжат целиком - не даёт, например, возможность ссылаться на на объект по смещению в файле. Есть какие-то предложения, как можно аккуратно решить вопрос, желательно без избыточного использования диска (ну не тупо клонить репозитории и их отдавать - хотя можно и так)
Forwarded from Dmitry Zuikov
пока мне не даёт покоя моя идея - скрестить CRDT и PBFT-подобнй подход + нашу терминологию (рефлоги).

1. раунд начинается по наступлению события - лучше всего времени, как в OTP. UPD: прошло N секунд с предыщуего раунда (или что? откуда мы знаем вообще, сколько времени прошло с прошлого раунда, если мы только что стартовали).

2. участники представляют свой мемпул (пишут в лог)

3. участники ждут, пока все или большинство из шага (2) - отпишутся в лог или наступит второй таймаут

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

обновляем наш стейт. ждем события начала раунда
Статья: Финальная стадия опердени как распределенная свёртка журнала транзакций. Сиквел и окончательное окончание историй про динамическую опердень и статическую опердень
А помните, был такой openstack. У меня по нему ещё было два сертификата и худи с катышками
Заставляем nix flake тащить исходники флейка из hbs2-git. И он тащит. Где мои цыгане с медведями?
тестируем шифрование. мы находимся здесь:
... -> Protocol Encryption -> Fast Large Git Repos -> Git Repo Encryption -> MVP
Введение: рефлоги это журналы транзакций, где идентификатором журнала является публичный ключ, а показательством права записи — подпись приватным ключом этого публичного ключа. Таким образом, писать в такой журнал может только владелец ключа. Мы можем раздать ключ всем, но тогда невозможно будет управлять метаинформацией.

Зарекалась же свинья. Не хотел делать "мультирефлоги", а именно такие, в которые могут постить несколько участников, т.е. с ACL и управлением ACL на текущем этапе. Но для решения проблемы рантайм консенсуса, который нужен, что бы можно было поднять несколько нод одновременно и они договаривались что делать, что, в свою очередь, нужно для текущего проекта, куда удалось впихнуть hbs2 при отсутствии сопротивления заказчика. И встал неприятный выбор: или сделать нормальные рефлоги с многими писателями и возможностью онлайн-консенсуса, или закостылить. Закостылить вроде бы можно, но тоже непросто. Т.е разница между закостыленным и нормальным решением будет дня три - четыре, короче неделя. Текущее решение с рефлогами в своём роде законченное, т.е то, что в них пишется - представляет собой подписанные владелцем рефлога записи, что даёт возможность даже взять плоский лог и проиграть его, выкидывая левые записи, даже если они туда попадут. Но там в транзах предусмотрен нонс, что бы они были гарантированно уникальными и подпись в каждой записи от известно чего (см. введение). Можно это обойти, и если транза типа A - то проверять так, а если B - то сяк (смотреть в ACL), но это начинает попахивать костылями, как раз. А если сделать полностью новый протокол и формат, где ответственность за уникальность транзакции возложить на клиента — то это попахивает большим дублированием кода, ведь обработка на 80% одинаковая. Неприятные вилы, надо сказать. Допстим, правильный путь это всё-таки добавление нового протокола и сущность нового формата, и обобщить дублицирующийся код, может, чат гпт сможет. Но я даже название для нового формата не могу придумать, так как рефлог было удачное и уже занято
а еще меня мучают два подозрения: 1) мало кто вообще в курсе, как устроен гит 2) судя по реакции, никто вообще не понимает, о чём я пишу. А ведь по сути сейчас такая захватывающая ведь происходит, как совмщение CRDT с онлайн консенсусом и распространение этого всего по P2P протоколу. 3) кажется, это особо никого не захватывает ахаха
(погода вроде сомнительная, никуда не еду (?), значит, пилим). #haskell есть такая статья "The ReaderT Design Pattern", Сноймана. "Суть такова", что если стейт разных частей программы делать как Reader, а внутри, если надо — мутабельные переменные, TVar или там IORef — то внезапно части программы начинают неплохо композиться. Например, если мы хотим запустить два вычисления в одном стейте, в разных непредсказуемых местах с любым рандомным монадным стектом в любом месте — то всегда можно запустить вычисление при помощи liftIO и пропихнуть туда актуальный стейт. Таким образом, глубина и особенности монадного стека в каждом конкретном месте перестают иметь значение, а нужные тебе вещи можно позвать в любом месте, просто дав контекст. Вот бы, блин, с людьми было так. Потому, что серию выводов и решений, к которым пришел в результате какой-то проделанной работы — никак не донести до других, особенно если это синтез практик из разных областей. Причем, хоть статью пиши. Хоть не пиши. Всё бесполезно. Ведь нужно не только понять, но и прочувствовать.

Вторая тема, которую донес то ли Снойман, то ли не Снойман — это про то, как писать код, который работает в любой монаде, а нужные ему вещи он объявляет через констрейнты, соответственно, если коду нужно что-то, мы это что-то втаскиваем через констрейнты и просто их реализуем для конкретной монады, если не хватает. Кажется, в той же статье. Я всю эту историю по широкой дуге обходил, RIO в частности. Но вот правда оказалось крайне полезным.

Или вот CRDT, например
В текущем hbs2 есть "рефлоги", так вот reflog это grow only set транзакций. Согласно литературе, grow only set является CRDT. А это значит, что за нас доказали все свойства, а структура это eventyally consistent при наличии gossip или другого способа обмена. Это хорошо работает, когда у нас один писатель и нам не надо управлять писателями (добавлять новых, отзывать права у старых). На таком можно сделать много - например, распределенный git когда у каждого свой форк, или вот твиттер, или вот каналы в телеграмме. Веселье начинается, когда нам нужно несколько писателей и добавить управление правами. Казалось бы: всё тот же grow-only set - CRDT + ACL - grow only set + сумма - казалось бы, тут CRDT, тут CRDT - все хорошо. На деле получается, что поскольку на транзакциях нет явного порядка (порядок приводит к DAG или требует рантайм консенсуса), мы не можем определить момент, в течение которого действовал "старый" набор ACL. ACL действуют только в "сейчас", Когда нода стартует с нуля - то читая лог, она никак не может понять, какие транзакции были валидны, а какие нет. Даже если сделать связь между ACL и транзакцией. Какая-то нода может остаться "в прошлом" и слать транзакции со старым ACL, например, в котором ей было можно. Таким образом, она не сможет портить view в настоящем, но может фальсифицировать историю. И что бы эту самую историю как-то зафиксировать - нужен либо онлайн консенсус какого-то рода, либо подход с trusted owner, который будет фиксировать историю при переходе на новый HEAD блок (который содержит ACL). Такие вот дела. Подход в принцие годный, кроме того, что на owner канала возложена теперь обязанность фиксировать историю при смене ACL. Предполагалось, что owner просто держит ключ в сейфе, раз в какой-то период достаёт, что бы добавить или убрать автора. А теперь ему придётся еще и историей управлять, ну вот ничего лучше не придумалось пока