Skip to content

Latest commit

 

History

History
249 lines (207 loc) · 15.1 KB

README.md

File metadata and controls

249 lines (207 loc) · 15.1 KB

ENG RUS

IndexBuffers

Data serialization-deserialization tool. Allows you to prepare data for transfer/storage in the internal IndexBuffers format with minimal overhead and a convenient API. Supports tool generation for C++.

Principle of use

  1. Writing a *.ibs text file with a data scheme.
  2. Generating of source code by using the IndexBuffers compiler.
  3. Inclusion and use of the generated source code in your project.

Benefits and features

  • The most simple and intuitive API of the generated code.
  • Minimum of source code - one per schema, without external dependencies other than STL.
  • Minimum of memory allocations - you can use previously allocated memory or use the only internal buffer based on std::vector for the packet.
  • Zero memory overhead if all fields are fixed.
  • Packages are ready for use at any time after the call create or from.
  • Native C-like schema description language.
  • Support for optional fields, namespaces, constants, enums, structs, unions.
  • Schemes must be UTF-8 encoded.
  • Alignment is not currently implemented, but you can manually arrange the schema's fields in the desired order.
  • Converting Little-Endian <> Big-Endian is not currently implemented.

Schema format

IndexBuffers schema language supports:

  • specifying of namespaces
  • inclusion of other schema files
  • enums with specific values, as well as the use of enums parameters as constants (min, max, count)
  • constants of different formats (bin, dec, hex, float, scientific float)
  • structs with regular fields, optional fields, fixed and variable length arrays, default values
  • unions for storing one of the fields in one cell

The detailed description of the schema format you can see here (TODO).
IndexBuffers schema example:

//File: "cheat_sheet.ibs"

include "additional.ibs" // Has namespace AdditionalNS
namespace ExtNS::IntNS

enum Color: uint8 {
    RED       // 0
    GREEN = 3 // 3
    BLUE      // 4
}

struct ScalarTypes: uint8 {
    int8            a
    uint16          b
    optional int32  c
    optional uint64 d
    float32         e
    float64         f
}

struct Vec3f: no_header
{
    float32 x = 0 // When specifying a default value, "optional" is not allowed
    float32 y = 0
    float32 z = 0
}

const uint32 fixedSize = 16 // Atomic types only, including enum

struct Arrays: uint16 {
    optional uint8 f[16] // Fixed size array
    bytes          b[fixedSize] // Fixed size array of bytes
    // Dynamic size arrays are always "optional"
    int16          m[] // Dynamic size array of integers
    Vec3f          v[]: uint8 // Dynamic size array of structs
}

union Variant: uint8 {
    Color  color // Inside "union", "optional" and a default value are not allowed
    Arrays data
    int64  arr[]
}

struct AnotherOne {
    bytes                   string[]
    optional Variant        variant
    Color                   colorChannels[Color.count] // Also exists ".min", ".max"
    Color                   colorMask = Color::BLUE
    AdditionalNS::SomeType  someData // From "additional.ibs"
}

Comparison with alternatives

Tool Time1, mcs % Time2, mcs % Size of packet, B Size of code, KB
Protocol Buffers v2 1.411 215 43.979 328 106 external + 96.4
Protocol Buffers v2 lite 1.407 214 37.225 278 106 external + 85.8
Protocol Buffers v3 1.527 233 42.778 319 106 external + 90.6
Protocol Buffers v3 lite 1.527 233 42.611 318 106 external + 90.6
FlatBuffers 0.656 100 13.379 100 296 external + 19.8
Cap'n Proto 1.084 165 151 external + 52.0
IndexBuffers 0.523 80 15.621 116 (uint8) 104 45.5
IndexBuffers 0.517 79 15.586 116 (uint16) 132 45.5
IndexBuffers 0.512 783 14.617 109 (uint32) 188 45.54
  1. Time for one serialization+deserialization, Zen 3 "Vermeer", 4.5 GHz.
  2. Time for one serialization+deserialization, i.MX6 armv7l, 1 GHz.
  3. To make IndexBuffers more faster, need to work out the issue of aligning the fields.
  4. Unlike alternative tools, the generated IndexBuffers code has no dependencies
    on either additional tool header files or additional static tool libraries
    (like Protocol Buffers and Cap'n Proto).

IndexBuffers

Инструмент сериализации-десериализации данных. Позволяет подготавливать данные для передачи/хранения во внутреннем формате IndexBuffers с минимальными накладными расходами и удобным программным интерфейсом. Поддерживается генерация инструмента под C++.

Принцип использования

  1. Написание текстового файла *.ibs со схемой данных.
  2. Генерирование исходного кода с помощью компилятора IndexBuffers.
  3. Включение и использование сгенерированного исходного кода в своём проекте.

Преимущества и характеристики

  • Максимально простой и интуитивно понятный API сгенерированного кода.
  • Минимум файлов с кодом - по одному на схему, без внешних зависимостей кроме STL.
  • Минимум выделений памяти - можно использовать заренее выделенную память или использовать единственный для пакета внутренний буфер на std::vector.
  • Нулевые накладные расходы по памяти, если все поля фиксированные.
  • Пакеты готовы к использованию в любой момент после вызова create или from.
  • Собственный C-подобный язык описания схемы.
  • Поддержка опциональных полей, пространств имён, констант, перечислений, структур, объединений.
  • Схемы данных должны иметь кодировку UTF-8.
  • Выравнивание на данный момент не реализовано, но можно вручную располагать поля в нужном порядке.
  • Конвертация Little-Endian <> Big-Endian на данный момент не реализована.

Формат описания схемы данных

Язык описания схемы данных IndexBuffers поддерживает:

  • указание пространств имён
  • включение других файлов со схемами данных
  • перечисления с указанием специфических значений, а также использование параметров перечисления в качестве констант (min, max, count)
  • константы разных форматов (bin, dec, hex, float, scientific float)
  • структуры с обычными полями, опциональными полями, массивами фиксированной и переменной длины, значениями по-умолчанию
  • объединения для хранения одного из вариантов полей в одной ячейке

Подробное описания формата схемы данных можно увидеть здесь (TODO).
Пример описания схемы данных IndexBuffers:

//File: "cheat_sheet.ibs"

include "additional.ibs" // Имеет namespace AdditionalNS
namespace ExtNS::IntNS

enum Color: uint8 {
    RED       // 0
    GREEN = 3 // 3
    BLUE      // 4
}

struct ScalarTypes: uint8 {
    int8            a
    uint16          b
    optional int32  c
    optional uint64 d
    float32         e
    float64         f
}

struct Vec3f: no_header
{
    float32 x = 0 // При указании значения по-умолчанию, "optional" запрещён
    float32 y = 0
    float32 z = 0
}

const uint32 fixedSize = 16 // Только атомарные типы, включая enum

struct Arrays: uint16 {
    optional uint8 f[16] // Массив фиксированного размера
    bytes          b[fixedSize] // Массив байт фиксированного размера
    // Массивы динамического размера всегда являются "optional"
    int16          m[] // Массив целых чисел динамического размера
    Vec3f          v[]: uint8 // Массив структур динамического размера
}

union Variant: uint8 {
    Color  color // Внутри "union", "optional" и значение по-умолчанию запрещены
    Arrays data
    int64  arr[]
}

struct AnotherOne {
    bytes                   string[]
    optional Variant        variant
    Color                   colorChannels[Color.count] // Также есть ".min", ".max"
    Color                   colorMask = Color::BLUE
    AdditionalNS::SomeType  someData // Из файла "additional.ibs"
}

Сравнение с альтернативными инструментами

Инструмент Время1, мкс % Время2, мкс % Размер пакета, б Размер кода, Кб
Protocol Buffers v2 1.411 215 43.979 328 106 внешний + 96.4
Protocol Buffers v2 lite 1.407 214 37.225 278 106 внешний + 85.8
Protocol Buffers v3 1.527 233 42.778 319 106 внешний + 90.6
Protocol Buffers v3 lite 1.527 233 42.611 318 106 внешний + 90.6
FlatBuffers 0.656 100 13.379 100 296 внешний + 19.8
Cap'n Proto 1.084 165 151 внешний + 52.0
IndexBuffers 0.523 80 15.621 116 (uint8) 104 45.5
IndexBuffers 0.517 79 15.586 116 (uint16) 132 45.5
IndexBuffers 0.512 783 14.617 109 (uint32) 188 45.54
  1. Время на одну сериализацию+десериализацию, Zen 3 "Vermeer", 4.5 ГГц.
  2. Время на одну сериализацию+десериализацию, i.MX6 armv7l, 1 ГГц.
  3. Чтобы сделать IndexBuffers ещё быстрее, нужно проработать вопрос
    выравнивания полей.
  4. В отличии от альтернативных инструментов, у сгенерированного кода
    IndexBuffers нет зависимостей ни от дополнительных заголовочных
    файлов инструмента, ни от дополнительных статических библиотек
    инстумента (как у Protocol Buffers и Cap'n Proto).