-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c0ed278
commit f612670
Showing
2 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# Go генератор | ||
|
||
tlgen детерминистский и генерирует при повторном запуске один и тот же код, так что | ||
сгенерированный код можно добавлять в систему контроля версий. | ||
|
||
По-умолчанию все комбинаторы генерируются в один internal пакет, плюс для каждого | ||
namespace TL генерируется пакет с алиасами. Это сделано потому, что Go не поддерживает рекурсивные зависимости между пакетами, а TL поддерживает. | ||
|
||
Для очень больших TL-файлов, содержащих тысячи комбинаторов, можно передать флаг --split-internal, тогда каждый тип помещается в собственный internal пакет. | ||
Затем пакеты для типов, рекурсивно использующих друг друга, обьединяются. | ||
Это сделано для того, чтобы при изменении одного комбинатора TL не приходилось перекомпилировать код большинства комбинаторов. | ||
|
||
Также tlgen поддерживает опцию --typesWhiteList, если вам нужна только часть namespace или комбинаторов, то можно явно указать их имена. | ||
|
||
# шаблоны | ||
|
||
TL-шаблоны полностью инстанцируются (для каждой использованной комбинации аргументов). | ||
|
||
Так что pair<int, int> pair<long, long> превращаются в 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, то у каждого сгенерированного типа появится возможность | ||
создавать детерминистски случайный экземпляр, это важно для тестов. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters