From f6126702a43288fdd932d9e28401ae4de3a8e332 Mon Sep 17 00:00:00 2001 From: Grigory Buteyko Date: Mon, 18 Nov 2024 22:34:55 +0300 Subject: [PATCH] documentation --- docs/go.md | 109 +++++++++++++++++++++++++++++++++++++++++++++++ docs/tldoc.ru.md | 5 +++ 2 files changed, 114 insertions(+) create mode 100644 docs/go.md diff --git a/docs/go.md b/docs/go.md new file mode 100644 index 00000000..be087273 --- /dev/null +++ b/docs/go.md @@ -0,0 +1,109 @@ +# Go генератор + +tlgen детерминистский и генерирует при повторном запуске один и тот же код, так что +сгенерированный код можно добавлять в систему контроля версий. + +По-умолчанию все комбинаторы генерируются в один internal пакет, плюс для каждого +namespace TL генерируется пакет с алиасами. Это сделано потому, что Go не поддерживает рекурсивные зависимости между пакетами, а TL поддерживает. + +Для очень больших TL-файлов, содержащих тысячи комбинаторов, можно передать флаг --split-internal, тогда каждый тип помещается в собственный internal пакет. +Затем пакеты для типов, рекурсивно использующих друг друга, обьединяются. +Это сделано для того, чтобы при изменении одного комбинатора TL не приходилось перекомпилировать код большинства комбинаторов. + +Также tlgen поддерживает опцию --typesWhiteList, если вам нужна только часть namespace или комбинаторов, то можно явно указать их имена. + +# шаблоны + +TL-шаблоны полностью инстанцируются (для каждой использованной комбинации аргументов). + +Так что pair pair превращаются в PairIntInt и PairLongLong. + + +# простые типы + +Отображаются в соответствующие типы Go + +Nat (#) в uint32, int в int32, long в int64, Bool в bool. + +String в string или []byte (В так называемые Bytes-версиях типов) + +# векторы и туплы + +Отображаются в массивы (если размер фиксирован), либо в слайсы. + +Отображение в массивы важно, так как позволяет 3*3*[int] отобразить в тип [3][3]int, который можно разместить на стеке и передать как знаение без аллокаций. + +Из-за этой оптимизации для следующих комбинаторов 3*[int] 4*[int] и n*[int] где n нефиксирован будет сгенрировано 3 разных Go типа. + +# структуры + +Отображаются в структуры Go. + +# маски полей + +Локальные маски полей хранятся в натуральном для TL виде uint32, если какое-то поле зависит от маски полей, то кроме поля будет сгенерированы методы +SetFieldX и IsSetFieldX который ставят и проверяют соответствующий бит маски. + +Маски полей-аргументы шаблона не хранятся в объектах, а передаются снаружи в методы Read, Write. + +Таким образом сгенерированные типы не содержат избыточных масок полей. + +# обьединения + +Генерируются в структуру Go, содержащую все варианты обьединения. +На первый взгляд это неоптимально с точки зрения памяти, но на самом деле позволяет идеально переиспользовать []byte и слайсы в +каждом варианте при повторном парсинге. Это часто перекрывает эффект от того, что сами структуры занимают немного больше. + +В качестве селектора варианта используется приватное поле номер конструктора. + +# перечисления + +Похожи на обьединения, но содержат функции MakeXXX + +# Bytes-версии и работы с минимумом аллокаций + +tlgen генерирует эффективный код на go, который поддерживает стиль +программирования с reuse, позволяющий значительно уменьшить число аллокаций и стоимость GC. + +Если комбинатор содержит TL string, то генерируется go string, так что при каждом чтении TL будет происходить аллокация каждой строки. +С помощь опции --generateByteVersions можно попросить tlgen сгенерировать в дополнение к основным также версии типов, где вместо строк используется []byte. + +При чтении соответствуюший []byte будет переиспользоваться, и если длина достаточно, то новой аллокации не будет. + +Таким образом, например, если сервер читает некий TL запрос, он может иметь sync.Pool структур, брать из пула структуру, десерилизоввать, отвечать на запрос, и затем класть структуру обратно в пул. +При работе сервера все строки и другие слайсы довольно быстро перестанут аллоцироваться, и таким образо деаллоцироваться. + +Нужно только понимать, что всеми слайсами в TL объекте владеет сам TL-объект, и при необходимости долговременного хранения нужно либо скопировать себе данные, либо сослаться на них, но тогда не класть структуру обратно в пул для reuse. + +# метаданные и фабрика + +Генерируется также пакет meta и factory. + +meta содержит метаданные для всех комбинаторов, доступные по magic или имени комбинатора. + +Если импортировать пакет factory, то для каждого комбинатора можно будет в runtime получить интерфейс, который позволит читать записывать и перекодировать TL-обьекты в другой формат на лету. + +# JSON-представление + +Все сгенерированные типы кроме методов ReadTL и WriteTL содержат также методы ReadJSON и WriteJSON. + +Также WriteJSON используется в реализации интерфейса String(), так что печать TL-обьекта на экран или в лог +выводит его в каноническом формате, который можно распарсить. + +Больше информации про каноническое представление JSON есть в документе TLPrimer.pdf + +Если передать флаг --generateSchemaDocumentation, то сгенерируется HTML с документацией и примерами JSON для каждого комбинатора. + +# RPC + +Если передать флаг --generateRPCCode, то для всех TL-функций будет сгенерирова код +для реализации сервера (Handler) и клиентов (Client) в каждом пакете соответствующем TL namespace. + +Этот код требует пакет RPC, который находится в opensource как часть проекта statashouse. +В дальнейшем есть планы пепеместить код RPC в проект tlgen. + +# random + +Если передать флаг --generateRandomCode, то у каждого сгенерированного типа появится возможность +создавать детерминистски случайный экземпляр, это важно для тестов. + diff --git a/docs/tldoc.ru.md b/docs/tldoc.ru.md index 9bb71f0c..4328089e 100644 --- a/docs/tldoc.ru.md +++ b/docs/tldoc.ru.md @@ -1,5 +1,10 @@ # TL (Type Language) +Формат md не поддерживает цвета, так что лучше всего читать +исходный документ в формате pdf. + +Этот же файл получен автоконвертером и без цветов на схемах гораздо менее понятен, чем оригинал. + ## Общие сведения TL это язык описания данных и формат хранения данных.