Code Monkey home page Code Monkey logo

chronoxor / fastbinaryencoding Goto Github PK

View Code? Open in Web Editor NEW
798.0 37.0 82.0 153.49 MB

Fast Binary Encoding is ultra fast and universal serialization solution for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift

Home Page: https://chronoxor.github.io/FastBinaryEncoding

License: MIT License

CMake 0.04% C++ 20.65% Lex 0.07% Yacc 0.10% C# 9.86% Go 12.12% Java 11.92% JavaScript 9.09% Kotlin 11.43% Python 6.69% Ruby 6.51% Swift 11.52% C 0.01%
performance serialization binary protocol low-latency cpp csharp java javascript python

fastbinaryencoding's Introduction

Fast Binary Encoding (FBE)

Awesome C++ License Release
Linux (clang) Linux (gcc) MacOS
Windows (Cygwin) Windows (MSYS2) Windows (MinGW) Windows (Visual Studio)

Fast Binary Encoding allows to describe any domain models, business objects, complex data structures, client/server requests & responses and generate native code for different programming languages and platforms.

Fast Binary Encoding documentation
Fast Binary Encoding downloads
Fast Binary Encoding specification

Performance comparison to other protocols can be found here:

Protocol Message size Serialization time Deserialization time
Cap'n'Proto 208 bytes 558 ns 359 ns
FastBinaryEncoding 234 bytes 66 ns 82 ns
FlatBuffers 280 bytes 830 ns 290 ns
Protobuf 120 bytes 628 ns 759 ns
JSON 301 bytes 740 ns 500 ns

Typical usage workflow is the following:

  1. Create domain model using base types, enums, flags and structs
  2. Generate domain model for any supported programming languages (C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift)
  3. Build domain model library
  4. Serialize/Deserialize objects from the domain model in unified, fast and compact FastBinaryEncoding (FBE) format
  5. JSON convert objects from the domain model in order to use them in Web API
  6. Implement Sender/Receiver interfaces to create a communication protocol

Sample projects:

Contents

Features

Requirements

Optional:

How to build?

Linux: install required packages

sudo apt-get install -y binutils-dev uuid-dev flex bison

MacOS: install required packages

brew install flex bison

Windows: install required packages

choco install winflexbison3
pip3 install gil

Setup repository

git clone https://github.com/chronoxor/FastBinaryEncoding.git
cd FastBinaryEncoding
gil update

Linux

cd build
./unix.sh

MacOS

cd build
./unix.sh

Windows (Cygwin)

cd build
unix.bat

Windows (MSYS2)

cd build
unix.bat

Windows (MinGW)

cd build
mingw.bat

Windows (Visual Studio)

cd build
vs.bat

Create domain model

To use Fast Binary Encoding you should provide a domain model (aka business objects). A domain model is a set of enums, flags and structures that relate to each other and might be aggregated in some hierarchy.

Fast Binary Encoding (FBE) format specification

There is a sample domain model which describes Account-Balance-Orders relation of some abstract trading platform:

// Package declaration
package proto

// Domain declaration
domain com.chronoxor

// Order side declaration
enum OrderSide : byte
{
    buy;
    sell;
}

// Order type declaration
enum OrderType : byte
{
    market;
    limit;
    stop;
}

// Order declaration
struct Order
{
    [key] int32 uid;
    string symbol;
    OrderSide side;
    OrderType type;
    double price = 0.0;
    double volume = 0.0;
}

// Account balance declaration
struct Balance
{
    [key] string currency;
    double amount = 0.0;
}

// Account state declaration
flags State : byte
{
    unknown = 0x00;
    invalid = 0x01;
    initialized = 0x02;
    calculated = 0x04;
    broken = 0x08;
    good = initialized | calculated;
    bad = unknown | invalid | broken;
}

// Account declaration
struct Account
{
    [key] int32 uid;
    string name;
    State state = State.initialized | State.bad;
    Balance wallet;
    Balance? asset;
    Order[] orders;
}

Generate domain model

The next step is a domain model compilation using 'fbec' compiler which will create a generated code for required programming language.

The following command will create a C++ generated code:

fbec --c++ --input=proto.fbe --output=.

All possible options for the 'fbec' compiler are the following:

Usage: fbec [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -h HELP, --help=HELP  Show help
  -i INPUT, --input=INPUT
                        Input path
  -o OUTPUT, --output=OUTPUT
                        Output path
  -q, --quiet           Launch in quiet mode. No progress will be shown!
  -n INDENT, --indent=INDENT
                        Format indent. Default: 0
  -t, --tabs            Format with tabs. Default: off
  --cpp                 Generate C++ code
  --cpp-logging         Generate C++ logging code
  --csharp              Generate C# code
  --go                  Generate Go code
  --java                Generate Java code
  --javascript          Generate JavaScript code
  --kotlin              Generate Kotlin code
  --python              Generate Python code
  --ruby                Generate Ruby code
  --swift               Generate Swift code
  --final               Generate Final serialization code
  --json                Generate JSON serialization code
  --proto               Generate Sender/Receiver protocol code

Build domain model

Generated domain model is represented with source code for the particular language. Just add it to your project and build it. There are several issues and dependencies that should be mentioned:

C++

  • C++ standard is limited to C++17 in order to have the implementation of std::optional;
  • C++ has no native support for decimal type. Currently decimal type is emulated with a double type. FBE does not use GMPLib because of heavy dependency in generated source code;
  • C++ formatting is supported with {fmt} library of version started from 9.0.0. Required include headers are <fmt/format.h> and <fmt/ostream.h>;
  • JSON serialization is implemented using RapidJSON library;

C#

  • JSON serialization is implemented using Json.NET library. Therefore it should be imported using NuGet;
  • Fast JSON serialization libraty is also available - Utf8Json . If you want to try it, you should import is with NuGet and build domain model with 'UTF8JSON' definition;

Go

  • Assert testing is based on stretchr/testify package (go get github.com/stretchr/testify);
  • JSON serialization is based on jsoniter package (go get github.com/json-iterator/go);
  • Decimal type is based on shopspring/decimal package (go get github.com/shopspring/decimal);
  • UUID type is based on google/uuid package (go get github.com/google/uuid);

Java

  • JSON serialization is implemented using Gson package. Therefore it should be imported using Maven;

JavaScript

  • JavaScript domain model is implemented using ECMAScript 6 (classes, etc.);
  • JSON serialization of set, map and hash types is limited to key with string type;

Kotlin

Python

Ruby

  • Some Ruby dependencies should be installed from Gems:
gem install json
gem install uuidtools

Swift

  • Swift domain model is implemented using uses SwiftPM as its build tool;
  • JSON serialization is implemented using Codable protocol;
  • JSON serialization of set, map and hash types is limited to key with string type.

FBE serialization

Fast Binary Encoding (FBE) is a fast and compact binary format of representing single domain models in different programming languages and platforms. Also FBE format solves protocol versioning problem.

Follow the steps below in order to serialize any domain object:

  1. Create a new domain object and fill its fields and collections (proto::Account account);
  2. Create a domain model with a write buffer (FBE::proto::AccountModelFBE::WriteBuffer writer)
  3. Serialize the domain object into the domain model buffer (writer.serialize(account))
  4. (Optional) Verify the domain object in the domain model buffer (assert(writer.verify()))
  5. Access the domain model buffer to store or send data (writer.buffer())

Follow the steps below in order to deserialize any domain object:

  1. Create a domain model with a read buffer (FBE::proto::AccountModelFBE::ReadBuffer reader)
  2. Attach a source buffer to the domain model (reader.attach(writer.buffer()))
  3. (Optional) Verify the domain object in the domain model buffer (assert(reader.verify()))
  4. Deserialize the domain object from the domain model buffer (reader.deserialize(account))

Here is an exmple of FBE serialization in C++ language:

#include "../proto/proto_models.h"

#include <iostream>

int main(int argc, char** argv)
{
    // Create a new account with some orders
    proto::Account account = { 1, "Test", proto::State::good, { "USD", 1000.0 }, std::make_optional<proto::Balance>({ "EUR", 100.0 }), {} };
    account.orders.emplace_back(1, "EURUSD", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);
    account.orders.emplace_back(2, "EURUSD", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);
    account.orders.emplace_back(3, "EURUSD", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);

    // Serialize the account to the FBE stream
    FBE::proto::AccountModel<FBE::WriteBuffer> writer;
    writer.serialize(account);
    assert(writer.verify());

    // Show the serialized FBE size
    std::cout << "FBE size: " << writer.buffer().size() << std::endl;

    // Deserialize the account from the FBE stream
    FBE::proto::AccountModel<FBE::ReadBuffer> reader;
    reader.attach(writer.buffer());
    assert(reader.verify());
    reader.deserialize(account);

    // Show account content
    std::cout << std::endl;
    std::cout << account;

    return 0;
}

Output is the following:

FBE size: 252

Account(
  uid=1,
  name="Test",
  state=initialized|calculated|good,
  wallet=Balance(currency="USD",amount=1000),
  asset=Balance(currency="EUR",amount=100),
  orders=[3][
    Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000),
    Order(uid=2,symbol="EURUSD",side=sell,type=limit,price=1,volume=100),
    Order(uid=3,symbol="EURUSD",side=buy,type=stop,price=1.5,volume=10)
  ]
)

FBE final serialization

It is possible to achieve more serialization speed if your protocol is mature enough so you can fix its final version and disable versioning which requires extra size and time to process.

Protocol Message size Serialization time Deserialization time Verify time
FBE 252 bytes 88 ns 98 ns 33 ns
FBE final 152 bytes 57 ns 81 ns 28 ns

Final domain model can be compiled with --final flag. As the result additional final models will be available for serialization.

Follow the steps below in order to serialize any domain object in final format:

  1. Create a new domain object and fill its fields and collections (proto::Account account);
  2. Create a domain final model with a write buffer (FBE::proto::AccountFinalModelFBE::WriteBuffer writer)
  3. Serialize the domain object into the domain model buffer (writer.serialize(account))
  4. (Optional) Verify the domain object in the domain model buffer (assert(writer.verify()))
  5. Access the domain model buffer to store or send data (writer.buffer())

Follow the steps below in order to deserialize any domain object:

  1. Create a domain final model with a read buffer (FBE::proto::AccountFinalModelFBE::ReadBuffer reader)
  2. Attach a source buffer to the domain final model (reader.attach(writer.buffer()))
  3. (Optional) Verify the domain object in the domain model buffer (assert(reader.verify()))
  4. Deserialize the domain object from the domain model buffer (reader.deserialize(account))

Here is an exmple of FBE final serialization in C++ language:

#include "../proto/proto_models.h"

#include <iostream>

int main(int argc, char** argv)
{
    // Create a new account with some orders
    proto::Account account = { 1, "Test", proto::State::good, { "USD", 1000.0 }, std::make_optional<proto::Balance>({ "EUR", 100.0 }), {} };
    account.orders.emplace_back(1, "EURUSD", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);
    account.orders.emplace_back(2, "EURUSD", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);
    account.orders.emplace_back(3, "EURUSD", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);

    // Serialize the account to the FBE stream
    FBE::proto::AccountFinalModel<FBE::WriteBuffer> writer;
    writer.serialize(account);
    assert(writer.verify());

    // Show the serialized FBE size
    std::cout << "FBE final size: " << writer.buffer().size() << std::endl;

    // Deserialize the account from the FBE stream
    FBE::proto::AccountFinalModel<FBE::ReadBuffer> reader;
    reader.attach(writer.buffer());
    assert(reader.verify());
    reader.deserialize(account);

    // Show account content
    std::cout << std::endl;
    std::cout << account;

    return 0;
}

Output is the following:

FBE final size: 152

Account(
  uid=1,
  name="Test",
  state=initialized|calculated|good,
  wallet=Balance(currency="USD",amount=1000),
  asset=Balance(currency="EUR",amount=100),
  orders=[3][
    Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000),
    Order(uid=2,symbol="EURUSD",side=sell,type=limit,price=1,volume=100),
    Order(uid=3,symbol="EURUSD",side=buy,type=stop,price=1.5,volume=10)
  ]
)

JSON serialization

If the domain model compiled with --json flag, then JSON serialization code will be generated in all domain objects. As the result each domain object can be serialized/deserialized into/from JSON format.

Please note that some programming languages have native JSON support (JavaScript, Python). Other languages requires third-party library to get work with JSON:

Here is an exmple of JSON serialization in C++ language:

#include "../proto/proto.h"

#include <iostream>

int main(int argc, char** argv)
{
    // Create a new account with some orders
    proto::Account account = { 1, "Test", proto::State::good, { "USD", 1000.0 }, std::make_optional<proto::Balance>({ "EUR", 100.0 }), {} };
    account.orders.emplace_back(1, "EURUSD", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);
    account.orders.emplace_back(2, "EURUSD", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);
    account.orders.emplace_back(3, "EURUSD", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);

    // Serialize the account to the JSON stream
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    FBE::JSON::to_json(writer, account);

    // Show the serialized JSON and its size
    std::cout << "JSON: " << buffer.GetString() << std::endl;
    std::cout << "JSON size: " << buffer.GetSize() << std::endl;

    // Parse the JSON document
    rapidjson::Document json;
    json.Parse(buffer.GetString());

    // Deserialize the account from the JSON stream
    FBE::JSON::from_json(json, account);

    // Show account content
    std::cout << std::endl;
    std::cout << account;

    return 0;
}

Output is the following:

JSON: {
  "uid":1,
  "name":
  "Test",
  "state":6,
  "wallet":{"currency":"USD","amount":1000.0},
  "asset":{"currency":"EUR","amount":100.0},
  "orders":[
    {"uid":1,"symbol":"EURUSD","side":0,"type":0,"price":1.23456,"volume":1000.0},
    {"uid":2,"symbol":"EURUSD","side":1,"type":1,"price":1.0,"volume":100.0},
    {"uid":3,"symbol":"EURUSD","side":0,"type":2,"price":1.5,"volume":10.0}
  ]
}
JSON size: 353

Account(
  uid=1,
  name="Test",
  state=initialized|calculated|good,
  wallet=Balance(currency="USD",amount=1000),
  asset=Balance(currency="EUR",amount=100),
  orders=[3][
    Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000),
    Order(uid=2,symbol="EURUSD",side=sell,type=limit,price=1,volume=100),
    Order(uid=3,symbol="EURUSD",side=buy,type=stop,price=1.5,volume=10)
  ]
)

Packages and import

Packages are declared with package name and structs offset (optional). Offset will be add to incremented structure type if is was not provided explicit.

Here is an example of the simple package declaration:

// Package declaration. Offset is 0.
package proto

// Struct type number is 1 (proto offset 0 + 1)
struct Struct1
{
    ...
}

// Struct type number is 2 (proto offset 0 + 2)
struct Struct2
{
    ...
}

One package can be imported into another and all enums, flags and structs can be reused in the current package. Package offset is used here to avoid structs types intersection:

// Package declaration. Offset is 10.
package protoex offset 10

// Package import
import proto

// Struct type number is 11 (protoex offset 10 + 1)
struct Struct11
{
    // Struct1 is reused form the imported package
    proto.Struct1 s1;
    ...
}

// Struct type number is 12 (protoex offset 10 + 2)
struct Struct12
{
    ...
}

Multiple package import is possible as well:

// Package declaration. Offset is 100.
package test offset 100

// Package import
import proto
import protoex

...

Package import is implemented using:

  • #include "..." directive in C++
  • Namespaces in C#
  • Packages in Go
  • Packages in Java and Kotlin
  • Modules in JavaScript
  • Modules in Python
  • Ruby require statement

Struct keys

Some of struct fileds (one or many) can be marked with '[key]' attribute. As the result corresponding compare operators will be generated which allow to compare two instances of the struct (equality, ordering, hashing) by marked fields. This ability allows to use the struct as a key in associative map and hash containers.

Example below demonstrates the usage of '[key]' attribute:

struct MyKeyStruct
{
    [key] int32 uid;
    [key] stirng login;
    string name;
    string address;
}

After code generation for C++ language the following comparable class will be generated:

struct MyKeyStruct
{
    int32_t uid;
    ::sample::stirng login;
    std::string name;
    std::string address;

    ...

    bool operator==(const MyKeyStruct& other) const noexcept
    {
        return (
            (uid == other.uid)
            && (login == other.login)
            );
    }
    bool operator!=(const MyKeyStruct& other) const noexcept { return !operator==(other); }
    bool operator<(const MyKeyStruct& other) const noexcept
    {
        if (uid < other.uid)
            return true;
        if (other.uid < uid)
            return false;
        if (login < other.login)
            return true;
        if (other.login < login)
            return false;
        return false;
    }
    bool operator<=(const MyKeyStruct& other) const noexcept { return operator<(other) || operator==(other); }
    bool operator>(const MyKeyStruct& other) const noexcept { return !operator<=(other); }
    bool operator>=(const MyKeyStruct& other) const noexcept { return !operator<(other); }

    ...
};

Struct numeration

Struct type numbers are automatically increased until you provide it manually. There are two possibilities:

  1. Shift the current struct type number using '(+X)' suffix. As the result all new structs will have incremented type.
  2. Force set struct type number using '(X)' of '(base)' suffix. It will affect only one struct.

Example below demonstrates the idea:

// Package declaration. Offset is 0.
package proto

// Struct type number is 1 (implicit declared)
struct Struct1
{
    ...
}

// Struct type number is 2 (implicit declared)
struct Struct2
{
    ...
}

// Struct type number is 10 (explicit declared, shifted to 10)
struct Struct10(+10)
{
    ...
}

// Struct type number is 11 (implicit declared)
struct Struct11
{
    ...
}

// Struct type number is 100 (explicit declared, forced to 100)
struct Struct100(100)
{
    ...
}

// Struct type number is 12 (implicit declared)
struct Struct12
{
    ...
}

Struct inheritance

Structs can be inherited from another struct. In this case all fields from the base struct will be present in a child one.

package proto

// Struct type number is 1
struct StructBase
{
    bool f1;
    int8 f2;
}

// Struct type number is 2
struct StructChild : StructBase
{
    // bool f1 - will be inherited from StructBase
    // int8 f2 - will be inherited from StructBase
    int16 f3;
    int32 f4;
}

Also it is possible to reuse the base struct type number in a child one using '= base' operator. It is useful when you extend the struct from third-party imported package:

// Package declaration. Offset is 10.
package protoex offset 10

// Package import
import proto

// Struct type number is 1
struct StructChild(base) : proto.StructBase
{
    // bool f1 - will be inherited from proto.StructBase
    // int8 f2 - will be inherited from proto.StructBase
    int16 f3;
    int32 f4;
}

Versioning

Versioning is simple with Fast Binary Encoding.

Assume you have an original protocol:

package proto

enum MyEnum
{
    value1;
    value2;
}

flags MyFlags
{
    none = 0x00;
    flag1 = 0x01;
    flag2 = 0x02;
    flag3 = 0x04;
}

struct MyStruct
{
    bool field1;
    byte field2;
    char field3;
}

You need to extend it with new enum, flag and struct values. Just add required values to the end of the corresponding declarations:

package proto

enum MyEnum
{
    value1;
    value2;
    value3; // New value
    value4; // New value
}

flags MyFlags
{
    none = 0x00;
    flag1 = 0x01;
    flag2 = 0x02;
    flag3 = 0x04;
    flag4 = 0x08; // New value
    flag5 = 0x10; // New value
}

struct MyStruct
{
    bool field1;
    byte field2;
    char field3;
    int32 field4;          // New field (default value is 0)
    int64 field5 = 123456; // New field (default value is 123456)
}

Now you can serialize and deserialize structs in different combinations:

  • Serialize old, deserialize old - nothing will be lost (best case);
  • Serialize old, deserialize new - all old fields will be deserialized, all new fields will be initialized with 0 or default values according to definition;
  • Serialize new, deserialize old - all old fields will be deserialized, all new fields will be discarded;
  • Serialize new, deserialize new - nothing will be lost (best case);

Versioning of the third-party protocol

If you are not able to modify some third-party protocol, you can still have a solution of extending it. Just create a new protocol and import third-party one into it. Then extend structs with inheritance:

package protoex

import proto

struct MyStructEx(base) : proto.MyStruct
{
    int32 field4;          // New field (default value is 0)
    int64 field5 = 123456; // New field (default value is 123456)
}

Sender/Receiver protocol

If the domain model compiled with --sender flag, then Sender/Receiver protocol code will be generated.

Sender interface contains 'send(struct)' methods for all domain model structs. Also it has abstract 'onSend(data, size)' method which should be implemented to send serialized data to a socket, pipe, etc.

Receiver interface contains 'onReceive(struct)' handlers for all domain model structs. Also it has public 'onReceive(type, data, size)' method which should be used to feed the Receiver with received data from a socket, pipe, etc.

Here is an exmple of using Sender/Receiver communication protocol in C++ language:

#include "../proto/proto_protocol.h"

#include <iostream>

class MySender : public FBE::proto::Sender<FBE::WriteBuffer>
{
protected:
    size_t onSend(const void* data, size_t size) override
    {
        // Send nothing...
        return 0;
    }

    void onSendLog(const std::string& message) const override
    {
        std::cout << "onSend: " << message << std::endl;
    }
};

class MyReceiver : public FBE::proto::Receiver<FBE::WriteBuffer>
{
protected:
    void onReceive(const proto::Order& value) override {}
    void onReceive(const proto::Balance& value) override {}
    void onReceive(const proto::Account& value) override {}

    void onReceiveLog(const std::string& message) const override
    {
        std::cout << "onReceive: " << message << std::endl;
    }
};

int main(int argc, char** argv)
{
    MySender sender;

    // Enable logging
    sender.logging(true);

    // Create and send a new order
    proto::Order order = { 1, "EURUSD", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0 };
    sender.send(order);

    // Create and send a new balance wallet
    proto::Balance balance = { "USD", 1000.0 };
    sender.send(balance);

    // Create and send a new account with some orders
    proto::Account account = { 1, "Test", proto::State::good, { "USD", 1000.0 }, std::make_optional<proto::Balance>({ "EUR", 100.0 }), {} };
    account.orders.emplace_back(1, "EURUSD", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);
    account.orders.emplace_back(2, "EURUSD", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);
    account.orders.emplace_back(3, "EURUSD", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);
    sender.send(account);

    MyReceiver receiver;

    // Enable logging
    receiver.logging(true);

    // Receive all data from the sender
    receiver.receive(sender.buffer().data(), sender.buffer().size());

    return 0;
}

Output is the following:

onSend: Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000)
onSend: Balance(currency="USD",amount=1000)
onSend: Account(uid=1,name="Test",state=initialized|calculated|good,wallet=Balance(currency="USD",amount=1000),asset=Balance(currency="EUR",amount=100),orders=[3][Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000),Order(uid=2,symbol="EURUSD",side=sell,type=limit,price=1,volume=100),Order(uid=3,symbol="EURUSD",side=buy,type=stop,price=1.5,volume=10)])
onReceive: Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000)
onReceive: Balance(currency="USD",amount=1000)
onReceive: Account(uid=1,name="Test",state=initialized|calculated|good,wallet=Balance(currency="USD",amount=1000),asset=Balance(currency="EUR",amount=100),orders=[3][Order(uid=1,symbol="EURUSD",side=buy,type=market,price=1.23456,volume=1000),Order(uid=2,symbol="EURUSD",side=sell,type=limit,price=1,volume=100),Order(uid=3,symbol="EURUSD",side=buy,type=stop,price=1.5,volume=10)])

Performance benchmarks

All benchmarks use the same domain model to create a single account with three orders:

Account account = { 1, "Test", State::good, { "USD", 1000.0 }, std::make_optional<Balance>({ "EUR", 100.0 }), {} };
account.orders.emplace_back(1, "EURUSD", OrderSide::buy, OrderType::market, 1.23456, 1000.0);
account.orders.emplace_back(2, "EURUSD", OrderSide::sell, OrderType::limit, 1.0, 100.0);
account.orders.emplace_back(3, "EURUSD", OrderSide::buy, OrderType::stop, 1.5, 10.0);

Benchmark 1: Serialization

Serialization benchmark C++ code:

BENCHMARK_FIXTURE(SerializationFixture, "Serialize")
{
    // Reset FBE stream
    writer.reset();

    // Serialize the account to the FBE stream
    writer.serialize(account);
}

Serialization benchmark results:

Language & Platform Message size Serialization rate Serialization time
C++ Win64 252 bytes 10 416 667 ops/s 96 ns
C++ Win64 (Final) 152 bytes 16 129 032 ops/s 62 ns
C++ Win64 (JSON) 353 bytes 926 784 ops/s 1 079 ns
C# Win64 252 bytes 1 432 665 ops/s 698 ns
C# Win64 (Final) 152 bytes 1 597 444 ops/s 626 ns
C# Win64 (JSON) 341 bytes 434 783 ops/s 2 300 ns
Go Win64 252 bytes 2 739 726 ops/s 365 ns
Go Win64 (Final) 152 bytes 2 949 852 ops/s 339 ns
Go Win64 (JSON) 341 bytes 258 732 ops/s 3 865 ns
Java Win64 252 bytes 4 247 162 ops/s 236 ns
Java Win64 (Final) 152 bytes 4 883 205 ops/s 205 ns
Java Win64 (JSON) 353 bytes 213 983 ops/s 4 673 ns
JavaScript Win64 252 bytes 93 416 ops/s 10 705 ns
JavaScript Win64 (Final) 152 bytes 112 665 ops/s 8 876 ns
JavaScript Win64 (JSON) 341 bytes 217 637 ops/s 4 595 ns
Kotlin Win64 252 bytes 3 546 694 ops/s 282 ns
Kotlin Win64 (Final) 152 bytes 4 096 406 ops/s 244 ns
Kotlin Win64 (JSON) 353 bytes 185 788 ops/s 5 382 ns
Python Win64 252 bytes 9 434 ops/s 105 999 ns
Python Win64 (Final) 152 bytes 11 635 ops/s 85 945 ns
Python Win64 (JSON) 324 bytes 61 737 ops/s 16 198 ns
Ruby Win64 252 bytes 23 013 ops/s 43 453 ns
Ruby Win64 (Final) 152 bytes 33 361 ops/s 29 975 ns
Ruby Win64 (JSON) 353 bytes 50 842 ops/s 19 669 ns
Swift macOS 252 bytes 74 002 ops/s 13 513 ns
Swift macOS (Final) 152 bytes 100 755 ops/s 9 925 ns
Swift macOS (JSON) 353 bytes 18 534 ops/s 53 953 ns

Benchmark 2: Deserialization

Deserialization benchmark C++ code:

BENCHMARK_FIXTURE(DeserializationFixture, "Deserialize")
{
    // Deserialize the account from the FBE stream
    reader.deserialize(deserialized);
}

Deserialization benchmark results:

Language & Platform Message size Deserialization rate Deserialization time
C++ Win64 252 bytes 9 523 810 ops/s 105 ns
C++ Win64 (Final) 152 bytes 10 989 011 ops/s 91 ns
C++ Win64 (JSON) 353 bytes 1 375 516 ops/s 727 ns
C# Win64 252 bytes 1 014 199 ops/s 986 ns
C# Win64 (Final) 152 bytes 1 607 717 ops/s 622 ns
C# Win64 (JSON) 341 bytes 258 532 ops/s 3 868 ns
Go Win64 252 bytes 1 510 574 ops/s 662 ns
Go Win64 (Final) 152 bytes 1 540 832 ops/s 649 ns
Go Win64 (JSON) 341 bytes 251 825 ops/s 3 971 ns
Java Win64 252 bytes 2 688 084 ops/s 372 ns
Java Win64 (Final) 152 bytes 3 036 020 ops/s 329 ns
Java Win64 (JSON) 353 bytes 308 675 ops/s 3 240 ns
JavaScript Win64 252 bytes 133 892 ops/s 7 469 ns
JavaScript Win64 (Final) 152 bytes 292 273 ops/s 3 422 ns
JavaScript Win64 (JSON) 341 bytes 289 417 ops/s 3 455 ns
Kotlin Win64 252 bytes 2 280 923 ops/s 438 ns
Kotlin Win64 (Final) 152 bytes 2 652 728 ops/s 277 ns
Kotlin Win64 (JSON) 353 bytes 250 524 ops/s 3 992 ns
Python Win64 252 bytes 8 305 ops/s 120 411 ns
Python Win64 (Final) 152 bytes 11 661 ops/s 85 758 ns
Python Win64 (JSON) 324 bytes 48 859 ops/s 20 467 ns
Ruby Win64 252 bytes 24 351 ops/s 41 066 ns
Ruby Win64 (Final) 152 bytes 33 555 ops/s 29 802 ns
Ruby Win64 (JSON) 353 bytes 42 860 ops/s 23 331 ns
Swift macOS 252 bytes 86 288 ops/s 11 589 ns
Swift macOS (Final) 152 bytes 10 3519 ops/s 9 660 ns
Swift macOS (JSON) 353 bytes 17 077 ops/s 58 558 ns

Benchmark 3: Verify

Verify benchmark C++ code:

BENCHMARK_FIXTURE(VerifyFixture, "Verify")
{
    // Verify the account
    model.verify();
}

Verify benchmark results:

Language & Platform Message size Verify rate Verify time
C++ Win64 252 bytes 31 250 000 ops/s 32 ns
C++ Win64 (Final) 152 bytes 35 714 286 ops/s 28 ns
C# Win64 252 bytes 4 504 505 ops/s 222 ns
C# Win64 (Final) 152 bytes 8 064 516 ops/s 124 ns
Go Win64 252 bytes 8 474 576 ops/s 118 ns
Go Win64 (Final) 152 bytes 9 090 909 ops/s 110 ns
Java Win64 252 bytes 11 790 374 ops/s 85 ns
Java Win64 (Final) 152 bytes 16 205 533 ops/s 62 ns
JavaScript Win64 252 bytes 1 105 627 ops/s 905 ns
JavaScript Win64 (Final) 152 bytes 5 700 408 ops/s 175 ns
Kotlin Win64 252 bytes 8 625 935 ops/s 116 ns
Kotlin Win64 (Final) 152 bytes 13 373 757 ops/s 75 ns
Python Win64 252 bytes 20 825 ops/s 48 019 ns
Python Win64 (Final) 152 bytes 23 590 ops/s 42 391 ns
Ruby Win64 252 bytes 57 201 ops/s 17 482 ns
Ruby Win64 (Final) 152 bytes 74 262 ops/s 13 466 ns
Swift macOS 252 bytes 164 446 ops/s 6 081 ns
Swift macOS (Final) 152 bytes 228 154 ops/s 4 383 ns

fastbinaryencoding's People

Contributors

bort-777 avatar chronoxor avatar dependabot[bot] avatar stinnux avatar temoto avatar three7six avatar zbranevichfinstek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastbinaryencoding's Issues

Generate c++ without exceptions

At several locations in the fbe.cpp file exceptions are thrown. Is it possible to generate code without these exceptions?
For example here:

throw std::runtime_error("Cannot get value of CLOCK_REALTIME timer!");

I would like to use fbe in an embedded environment, where exceptions are disabled for performance reasons. However, now I am unable to compile the generated c++ code.

Broken Build on Mac OS

(base) adminmbp:FastBinaryEncoding admin$ gil update
Working path: /Users/admin/Desktop/FastBinaryEncoding
Discover git links: /Users/admin/Desktop/FastBinaryEncoding/.gitlinks
Discover git links: /Users/admin/Desktop/FastBinaryEncoding/modules/CppBenchmark/.gitlinks
Discover git links: /Users/admin/Desktop/FastBinaryEncoding/modules/CppCommon/.gitlinks
(base) adminmbp:FastBinaryEncoding admin$ ls
CMakeLists.txt _config.yml documents modules source
LICENSE bin examples performance tests
README.md build images projects
TODO.md cmake include proto
(base) adminmbp:FastBinaryEncoding admin$ ls -a
. .gitlinks _config.yml images source
.. .travis.yml bin include tests
.appveyor.yml CMakeLists.txt build modules
.git LICENSE cmake performance
.gitattributes README.md documents projects
.gitignore TODO.md examples proto
(base) adminmbp:FastBinaryEncoding admin$ cd build
(base) adminmbp:build admin$ ./unix.sh
-- The C compiler identification is AppleClang 11.0.3.11030032
-- The CXX compiler identification is AppleClang 11.0.3.11030032
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Darwin-19.4.0 Darwin 19.4.0 Platform/Darwin
-- Found BISON: /usr/bin/bison (found version "2.3")
-- Found FLEX: /usr/bin/flex (found version "2.5.35")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Darwin-19.4.0 Darwin 19.4.0 Platform/Darwin
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of off64_t
-- Check size of off64_t - failed
-- Looking for fseeko
-- Looking for fseeko - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Darwin-19.4.0 Darwin 19.4.0 Platform/Darwin
-- Could NOT find LIBBFD (missing: LIBBFD_LIBRARY LIBBFD_INCLUDE_DIR)
-- Found LIBDL: /usr/lib/libdl.dylib
-- Could NOT find LIBRT (missing: LIBRT_LIBRARY)
-- Could NOT find LIBUUID (missing: LIBUUID_LIBRARY)
-- Could NOT find LIBVLD (missing: LIBVLD_LIBRARY)
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/admin/Desktop/FastBinaryEncoding/temp
Scanning dependencies of target fmt
Scanning dependencies of target cpp-optparse
Scanning dependencies of target zlib
[ 1%] Building CXX object modules/CMakeFiles/cpp-optparse.dir/cpp-optparse/OptionParser.cpp.o
[ 2%] Building CXX object modules/CppCommon/modules/CMakeFiles/fmt.dir/fmt/src/format.cc.o
[ 2%] Building CXX object modules/CppCommon/modules/CMakeFiles/fmt.dir/fmt/src/os.cc.o
[ 3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/compress.c.o
[ 3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/adler32.c.o
[ 3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/crc32.c.o
[ 4%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/deflate.c.o
[ 4%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzclose.c.o
[ 5%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzlib.c.o
[ 5%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzread.c.o
[ 6%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzwrite.c.o
[ 6%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/infback.c.o
[ 7%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inffast.c.o
[ 7%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inflate.c.o
[ 8%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inftrees.c.o
[ 8%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/trees.c.o
[ 9%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/uncompr.c.o
[ 9%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/zutil.c.o
[ 10%] Linking C static library libzlib.a
[ 10%] Built target zlib
Scanning dependencies of target HdrHistogram
[ 10%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_encoding.c.o
[ 10%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_histogram.c.o
[ 11%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_histogram_log.c.o
[ 11%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_interval_recorder.c.o
[ 11%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_time.c.o
[ 12%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_thread.c.o
[ 13%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_writer_reader_phaser.c.o
[ 13%] Linking C static library libHdrHistogram.a
[ 13%] Built target HdrHistogram
[ 13%] Linking CXX static library libcpp-optparse.a
[ 13%] Built target cpp-optparse
Scanning dependencies of target cppbenchmark
[ 14%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/barrier.cpp.o
[ 15%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_pc.cpp.o
[ 15%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_base.cpp.o
[ 15%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark.cpp.o
[ 16%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_threads.cpp.o
[ 16%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/console.cpp.o
[ 17%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context.cpp.o
[ 17%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context_pc.cpp.o
[ 18%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context_threads.cpp.o
[ 18%] Linking CXX static library libfmt.a
[ 18%] Built target fmt
[ 18%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/environment.cpp.o
Scanning dependencies of target cppcommon
[ 19%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/algorithms/token_bucket.cpp.o
[ 19%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/cache/filecache.cpp.o
[ 20%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/reader.cpp.o
[ 20%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/uint128.cpp.o
[ 21%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/uint256.cpp.o
[ 21%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/writer.cpp.o
[ 22%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/executor.cpp.o
[ 23%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/exceptions.cpp.o
[ 23%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/exceptions_handler.cpp.o
[ 23%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/launcher.cpp.o
[ 24%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/launcher_console.cpp.o
[ 24%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_core.cpp.o
[ 25%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_metrics.cpp.o
[ 25%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_scope.cpp.o
[ 26%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/fatal.cpp.o
[ 26%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/system_error.cpp.o
[ 27%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_console.cpp.o
[ 28%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/directory.cpp.o
[ 28%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_csv.cpp.o
[ 29%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_json.cpp.o
[ 29%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/settings.cpp.o
[ 29%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/directory_iterator.cpp.o
[ 30%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/exceptions.cpp.o
[ 30%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/file.cpp.o
[ 31%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/system.cpp.o
[ 32%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/path.cpp.o
[ 32%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/symlink.cpp.o
[ 33%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/math/math.cpp.o
[ 33%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/memory/memory.cpp.o
[ 34%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/string/encoding.cpp.o
[ 34%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/string/string_utils.cpp.o
[ 35%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/console.cpp.o
[ 35%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/cpu.cpp.o
[ 36%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/dll.cpp.o
[ 36%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/environment.cpp.o
[ 37%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/pipe.cpp.o
[ 37%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/process.cpp.o
[ 38%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/shared_memory.cpp.o
[ 38%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/stack_trace.cpp.o
[ 39%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/stack_trace_manager.cpp.o
[ 39%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/stream.cpp.o
[ 40%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/uuid.cpp.o
[ 40%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/barrier.cpp.o
[ 40%] Linking CXX static library libcppbenchmark.a
[ 41%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/condition_variable.cpp.o
[ 41%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/critical_section.cpp.o
[ 41%] Built target cppbenchmark
[ 42%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/event_auto_reset.cpp.o
[ 42%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/event_manual_reset.cpp.o
[ 43%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/file_lock.cpp.o
[ 43%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/latch.cpp.o
[ 44%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/mutex.cpp.o
[ 44%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_condition_variable.cpp.o
[ 45%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_critical_section.cpp.o
[ 45%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_event_auto_reset.cpp.o
[ 46%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_event_manual_reset.cpp.o
[ 46%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_mutex.cpp.o
[ 47%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_rw_lock.cpp.o
[ 47%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/named_semaphore.cpp.o
[ 48%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/rw_lock.cpp.o
[ 48%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/semaphore.cpp.o
[ 49%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/threads/thread.cpp.o
[ 49%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/time/time.cpp.o
[ 50%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/time/timestamp.cpp.o
[ 50%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/time/timezone.cpp.o
[ 51%] Linking CXX static library libcppcommon.a
[ 51%] Built target cppcommon
[ 52%] [BISON][parser] Building parser with bison 2.3
[ 52%] [FLEX][lexer] Building scanner with flex 2.5.35
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison: invalid option -- W
Try `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison --help' for more information.
make[2]: *** [../source/fbe-parser.cpp] Error 1
make[2]: *** Waiting for unfinished jobs....
flex version 2.5.35 Apple(flex-32) usage statistics:
scanner options: -vI8 -Cem -o/Users/admin/Desktop/FastBinaryEncoding/source/fbe-lexer.cpp
590/2000 NFA states
250/1000 DFA states (1350 words)
76 rules
Compressed tables always back-up
1/40 start conditions
273 epsilon states, 113 double epsilon states
36/100 character classes needed 274/500 words of storage, 0 reused
6822 state/nextstate pairs created
649/6173 unique/duplicate transitions
265/1000 base-def entries created
496/2000 (peak 1128) nxt-chk entries created
165/2500 (peak 945) template nxt-chk entries created
0 empty table entries
18 protos created
15 templates created, 184 uses
63/256 equivalence classes created
11/256 meta-equivalence classes created
1 (1 saved) hash collisions, 402 DFAs equal
0 sets of reallocations needed
1841 total table entries needed
make[1]: *** [CMakeFiles/fbec.dir/all] Error 2
make: *** [all] Error 2
(base) adminmbp:build admin$

Is there something I am doing wrong?

Javascript Client Request Issue

Looks like the client _requests_by_id and _requests_by_timestamp are Map objects and should use set/get. Also, the timeout passed to the request method is multiplied by 1000000. I would think since the timestamp is milliseconds and the timeout is milliseconds that no conversion would be needed. Once I modified the Map objects to use set/get and removed the timeout multiplier, the client request seemed to work as expected. Thanks.

Generator for C

Interesting project, thanks. Would like to see a generator for ANSI C if possible, I have a few projects where I could utilize FBE and its cross-platform possibilities.

Broken build on Linux

./unix.sh script tryes to commit something to github after build?

finalizing index lists...
writing tag file...
lookup cache used 2123/65536 hits=54224 misses=2163
finished...
Built target doxygen
On branch gh-pages
Your branch is ahead of 'origin/gh-pages' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
Password for 'https://github.com': 
remote: Anonymous access to chronoxor/FastBinaryEncoding.git denied.
fatal: Authentication failed for 'https://@github.com/chronoxor/FastBinaryEncoding.git/'

need union/variant support

FBE is a awesome serialization library for cpp.
flatbuf will be slower and harder to use, but flatbuffer support union syntax, and the union/variant is very useful for our sceniaro.
So I want to know if Author of FBE has the plan to support it?

fbec should error-out on typo

Typo in domain model, eg:

struct MyStruct {
    unt64 ShouldBoom;
}

Note unt64 instead of uint64. fbec happily produces:

// MyStruct struct
type MyStruct struct {
    ShouldBoom Unt64 `json:"ShouldBoom"`
}

C++ FinalClient::request small bug

This should be easy to reproduce, using latest fbec 1.11.0.0 with --cpp --final --proto

The generated FinalClient::request(..) methods has

size_t serialized = Sender::send(value);

which my gcc 11 compiler complains
Fixed by changing to

size_t serialized = FinalSender::send(value);

btw, really awesome library!

python uuid default value small bug

In latest version 1.12.0.0, when generating python files

example .fbe file

message Generated
{
     string val1 = "42";
     uuid [id] = uuid1;
}

will create something like

...
class Generated(object):
     ...
     def __init__(self, val1=None, id=uuid.uuid1()):
          ...

which actually fixes the id to be the same when file is first evaluated, so the following code will print the same value

g1 = Generated()
g2 = Generated()
print(g1.id)
print(g2.id)

and I think this behaviour is inconsistent with its C++ counterpart.

Proposed fix:

...
class Generated(object):
     ...
     def __init__(self, val1=None, id=None):
          ...
          if id is None:
              id = uuid.uuid1()

This error may also appear for other type of default value, for example '[]'(empty list), etc. I have to say this python feature is quite counter-intuitive.

see also: https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument

"fbe.h" windows header file problem hope to modify

To resolve the conflict between WinSock2.h and windows.h

update FastBinaryEncoding\source\generator_cpp.cpp

change๏ผš
line 196

#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#undef DELETE
#undef ERROR
#undef HOST_NOT_FOUND
#undef Yield
#undef min
#undef max
#undef uuid_t
#endif

to๏ผš

#elif defined(_WIN32) || defined(_WIN64)
//#include <windows.h>
#undef DELETE
#undef ERROR
#undef HOST_NOT_FOUND
#undef Yield
#undef min
#undef max
#undef uuid_t
#endif

inser line 6334๏ผš

    // Generate win
    WriteLine();
    WriteLineIndent("#if defined(_WIN32) || defined(_WIN64)");
    WriteLineIndent("#include <windows.h>");
    WriteLineIndent("#undef uuid_t");
    WriteLineIndent("#endif");

std::max -> (std::max)

Receiver is unable to find message size despite parsing correctly

Hi, for some reason when i send some message from my server to client, client will receive it, parse it and invoke OnReceive(myType msg) correctly. After going out of scope, it throws assert error.
obrazek

After some investigation. i found out it that it tries to get message size like this:
obrazek

offset2 is 58 in this case:
obrazek

resulted message size is 0;

This is the content of the buffer
obrazek

This is called only once:
obrazek

obrazek

For some reason it tries to invalidate this message after invoking OnReceive(myType msg) and data inside that struct are correct. So i don't quite understand the callgraph here. Here is callstack:
obrazek

Is it possible to hide protocol field names

image

image

We are using protobuf now, it will keep the protocol in binary, it can almost restore the protocol, I noticed that FastBinaryEncoding also has this problem, I hope not to keep any related strings with the protocol declaration

Cannot build domain models on ubuntu

OS: Ubuntu 20.04
FBEC: 1.4.0.0

Im trying to build the sample domain model with the command:

./fbec --cpp --input=proto.fbe --output=out/.

however this gives me:

Open input file - proto.fbe...Done!

proto.fbe:5: error: syntax error
domain
     ^--- syntax error
Parsing input...Done!
Close input file...Done!
Segmentation fault (core dumped)

I cant find a solution to this

Versioning with Struct inheritance?

Is it supported to extend a struct that one inherits from? Also in multiple levels?

Its not clear from the documentation as versioning is only done on "simple" structs.

get around csharp analyzers

have you thought about adding a file header to get around csharp code analyzers

// <auto-generated>
//     This code was generated by a tool.
//     Version: {Environment.Version}
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>

is the most common format

Uint8 in Swift

The uint8 data type is converted in Swift code with the type name "uint8" instead of "UInt8".

Arbitrary length bits type supported?

Thanks for this awesome project. After read the documents, I have a question about arbitrary length bits type. I think now the current status about this kind of type is unsupoorted. Am I right? If I were right (hope not), is there any plan about it? Thanks very much! Have a nice day!

Swift Question: Ho do I get the serialized Data out of the buffer?

I have generated a model Visit, I want to fast serialize and then store it in a store that accepts Swift's Data() type.

What I have is:

let visit = Visit(number: 10)
let writer = VisitFinalModel()
try! writer.serialize(value: visit)

// I belive what I'm looking for is now in writer.buffer.data - but that is not accessible by default.
let data = writer.buffer.data

// I would now store data on disk. 

// this is how i would recreate the struct
let buf = Buffer()
buf.attach(buffer: data)
        
let reader = VisitModel()
reader.attach(buffer: buf)
let restoredModel = reader.deserialize()

Question: What's the official way to get something Data() compatible from the writer.

Thanx for this great library!

Generator for Rust

Hi!

This project looks very promising. Thanks for providing those benchmarks, they are super interesting.

I have not seen any mentions in the issues, so I thought I'd open an issue to see if there is any interest in creating a generator for Rust.

Can't install on Solus, LIBVLD issue?

camdenorrb@newhost ~/Documents/Installed/Make/FastBinaryEncoding $ cd ../
camdenorrb@newhost ~/Documents/Installed/Make $ git clone https://github.com/chronoxor/FastBinaryEncoding.git
Cloning into 'FastBinaryEncoding'...
remote: Enumerating objects: 450, done.
remote: Counting objects: 100% (450/450), done.
remote: Compressing objects: 100% (255/255), done.
remote: Total 33660 (delta 321), reused 217 (delta 191), pack-reused 33210
Receiving objects: 100% (33660/33660), 125.52 MiB | 4.88 MiB/s, done.
Resolving deltas: 100% (29368/29368), done.
camdenorrb@newhost ~/Documents/Installed/Make $ cd FastBinaryEncoding/
camdenorrb@newhost ~/Documents/Installed/Make/FastBinaryEncoding $ gil update
Working path: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding
Discover git links: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/.gitlinks
Running git clone https://github.com/catchorg/Catch2.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/Catch2
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/Catch2'...
remote: Enumerating objects: 122, done.
remote: Counting objects: 100% (122/122), done.
remote: Compressing objects: 100% (85/85), done.
remote: Total 26063 (delta 54), reused 77 (delta 37), pack-reused 25941
Receiving objects: 100% (26063/26063), 15.92 MiB | 3.73 MiB/s, done.
Resolving deltas: 100% (18143/18143), done.
Running git clone https://github.com/weisslj/cpp-optparse.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/cpp-optparse
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/cpp-optparse'...
remote: Enumerating objects: 343, done.
remote: Total 343 (delta 0), reused 0 (delta 0), pack-reused 343
Receiving objects: 100% (343/343), 70.62 KiB | 753.00 KiB/s, done.
Resolving deltas: 100% (203/203), done.
Running git clone https://github.com/chronoxor/CppBenchmark.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark'...
remote: Enumerating objects: 445, done.
remote: Counting objects: 100% (445/445), done.
remote: Compressing objects: 100% (211/211), done.
remote: Total 14519 (delta 360), reused 254 (delta 234), pack-reused 14074
Receiving objects: 100% (14519/14519), 40.65 MiB | 14.76 MiB/s, done.
Resolving deltas: 100% (12098/12098), done.
Discover git links: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/.gitlinks
Running git clone https://github.com/chronoxor/CppCommon.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon'...
remote: Enumerating objects: 1382, done.
remote: Counting objects: 100% (1382/1382), done.
remote: Compressing objects: 100% (566/566), done.
remote: Total 42646 (delta 1208), reused 854 (delta 816), pack-reused 41264
Receiving objects: 100% (42646/42646), 59.95 MiB | 4.28 MiB/s, done.
Resolving deltas: 100% (38617/38617), done.
Discover git links: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/.gitlinks
Running git clone https://github.com/miloyip/rapidjson.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/rapidjson
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/rapidjson'...
remote: Enumerating objects: 97, done.
remote: Counting objects: 100% (97/97), done.
remote: Compressing objects: 100% (56/56), done.
remote: Total 22725 (delta 68), reused 51 (delta 39), pack-reused 22628
Receiving objects: 100% (22725/22725), 27.06 MiB | 10.84 MiB/s, done.
Resolving deltas: 100% (17287/17287), done.
Running git clone https://github.com/chronoxor/CppBuildScripts.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/build
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/build'...
remote: Enumerating objects: 40, done.
remote: Counting objects: 100% (40/40), done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 490 (delta 21), reused 31 (delta 16), pack-reused 450
Receiving objects: 100% (490/490), 4.49 MiB | 1.02 MiB/s, done.
Resolving deltas: 100% (260/260), done.
Running git clone https://github.com/chronoxor/CppCMakeScripts.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/cmake
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/cmake'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 409 (delta 1), reused 3 (delta 1), pack-reused 403
Receiving objects: 100% (409/409), 51.05 KiB | 1024.00 KiB/s, done.
Resolving deltas: 100% (247/247), done.
Running git clone https://github.com/HdrHistogram/HdrHistogram_c.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/HdrHistogram
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/HdrHistogram'...
remote: Enumerating objects: 157, done.
remote: Counting objects: 100% (157/157), done.
remote: Compressing objects: 100% (99/99), done.
remote: Total 4733 (delta 98), reused 103 (delta 55), pack-reused 4576
Receiving objects: 100% (4733/4733), 2.66 MiB | 1.36 MiB/s, done.
Resolving deltas: 100% (2684/2684), done.
Running git clone https://github.com/madler/zlib.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/zlib
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/zlib'...
remote: Enumerating objects: 5144, done.
remote: Total 5144 (delta 0), reused 0 (delta 0), pack-reused 5144
Receiving objects: 100% (5144/5144), 3.62 MiB | 666.00 KiB/s, done.
Resolving deltas: 100% (3613/3613), done.
Running git clone https://github.com/fmtlib/fmt.git branch "master" into /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/modules/fmt
Cloning into '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/modules/fmt'...
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 20381 (delta 3), reused 8 (delta 2), pack-reused 20366
Receiving objects: 100% (20381/20381), 9.99 MiB | 10.49 MiB/s, done.
Resolving deltas: 100% (13861/13861), done.
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/Catch2 -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/Catch2
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/cpp-optparse -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/modules/cpp-optparse
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/build -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/build
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/cmake -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark/cmake
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/Catch2 -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/modules/Catch2
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppBenchmark -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/modules/CppBenchmark
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/build -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/build
Create git link: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/cmake -> /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/cmake
camdenorrb@newhost ~/Documents/Installed/Make/FastBinaryEncoding $ cd build/
camdenorrb@newhost ~/Documents/Installed/Make/FastBinaryEncoding/build $ ./unix.sh 
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Doxygen: /usr/bin/doxygen (found version "1.8.15") found components: doxygen missing components: dot
-- The System identification is Linux-5.5.11-151.current Linux 5.5.11-151.current Platform/Linux
-- Found BISON: /usr/bin/bison (found version "3.5.3") 
-- Found FLEX: /usr/bin/flex (found version "2.6.4") 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- The System identification is Linux-5.5.11-151.current Linux 5.5.11-151.current Platform/Linux
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of off64_t
-- Check size of off64_t - done
-- Looking for fseeko
-- Looking for fseeko - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- The System identification is Linux-5.5.11-151.current Linux 5.5.11-151.current Platform/Linux
-- Found LIBBFD: /usr/lib/libbfd.so  
-- Found LIBDL: /usr/lib/libdl.so  
-- Found LIBRT: /usr/lib/librt.so  
-- Found LIBUUID: /usr/lib/libuuid.so  
-- Could NOT find LIBVLD (missing: LIBVLD_LIBRARY) 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp
make[1]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
Scanning dependencies of target cpp-optparse
Scanning dependencies of target fmt
Scanning dependencies of target zlib
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[  1%] Building CXX object modules/CMakeFiles/cpp-optparse.dir/cpp-optparse/OptionParser.cpp.o
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[  1%] Building CXX object modules/CppCommon/modules/CMakeFiles/fmt.dir/fmt/src/format.cc.o
[  2%] Building CXX object modules/CppCommon/modules/CMakeFiles/fmt.dir/fmt/src/os.cc.o
[  3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/deflate.c.o
[  3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/crc32.c.o
[  3%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzclose.c.o
[  4%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/compress.c.o
[  4%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/adler32.c.o
[  5%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzlib.c.o
[  5%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzread.c.o
[  6%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/gzwrite.c.o
[  6%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/infback.c.o
[  7%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inffast.c.o
[  7%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inflate.c.o
[  8%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/inftrees.c.o
[  8%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/trees.c.o
[  9%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/uncompr.c.o
[  9%] Building C object modules/CppBenchmark/modules/CMakeFiles/zlib.dir/zlib/zutil.c.o
[ 10%] Linking C static library libzlib.a
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 10%] Built target zlib
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
Scanning dependencies of target HdrHistogram
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 10%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_encoding.c.o
[ 10%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_histogram.c.o
[ 10%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_interval_recorder.c.o
[ 11%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_thread.c.o
[ 11%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_time.c.o
[ 12%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_histogram_log.c.o
[ 13%] Building C object modules/CppBenchmark/modules/CMakeFiles/HdrHistogram.dir/HdrHistogram/src/hdr_writer_reader_phaser.c.o
[ 13%] Linking C static library libHdrHistogram.a
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 13%] Built target HdrHistogram
[ 13%] Linking CXX static library libcpp-optparse.a
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 13%] Built target cpp-optparse
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
Scanning dependencies of target cppbenchmark
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 13%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark.cpp.o
[ 13%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_pc.cpp.o
[ 14%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_base.cpp.o
[ 15%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/benchmark_threads.cpp.o
[ 16%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context.cpp.o
[ 17%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/barrier.cpp.o
[ 17%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/console.cpp.o
[ 17%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context_pc.cpp.o
[ 18%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/context_threads.cpp.o
[ 18%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/environment.cpp.o
[ 19%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/executor.cpp.o
[ 19%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/launcher.cpp.o
[ 20%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/launcher_console.cpp.o
[ 20%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_core.cpp.o
[ 21%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_metrics.cpp.o
[ 21%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/phase_scope.cpp.o
[ 22%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_console.cpp.o
[ 22%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_csv.cpp.o
[ 23%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/reporter_json.cpp.o
[ 23%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/settings.cpp.o
[ 24%] Building CXX object modules/CppBenchmark/CMakeFiles/cppbenchmark.dir/source/benchmark/system.cpp.o
[ 24%] Linking CXX static library libfmt.a
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 24%] Built target fmt
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
Scanning dependencies of target cppcommon
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[2]: Entering directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 25%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/algorithms/token_bucket.cpp.o
[ 26%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/reader.cpp.o
[ 26%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/uint128.cpp.o
[ 26%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/cache/filecache.cpp.o
[ 27%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/uint256.cpp.o
[ 27%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/common/writer.cpp.o
[ 28%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/exceptions.cpp.o
[ 28%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/exceptions_handler.cpp.o
[ 29%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/fatal.cpp.o
[ 29%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/errors/system_error.cpp.o
[ 30%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/directory.cpp.o
[ 30%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/directory_iterator.cpp.o
[ 31%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/exceptions.cpp.o
[ 31%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/file.cpp.o
[ 32%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/path.cpp.o
[ 32%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/filesystem/symlink.cpp.o
[ 33%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/math/math.cpp.o
[ 33%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/memory/memory.cpp.o
[ 33%] Linking CXX static library libcppbenchmark.a
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
[ 33%] Built target cppbenchmark
[ 34%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/string/encoding.cpp.o
[ 34%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/string/string_utils.cpp.o
[ 35%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/console.cpp.o
[ 35%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/cpu.cpp.o
[ 36%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/dll.cpp.o
[ 36%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/environment.cpp.o
[ 37%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/pipe.cpp.o
[ 37%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/process.cpp.o
[ 38%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/shared_memory.cpp.o
[ 38%] Building CXX object modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/stack_trace.cpp.o
In file included from /home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/source/system/stack_trace.cpp:21:
/usr/include/bfd.h:35:2: error: #error config.h must be included before this header
   35 | #error config.h must be included before this header
      |  ^~~~~
/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/source/system/stack_trace.cpp: In constructor โ€˜CppCommon::StackTrace::StackTrace(int)โ€™:
/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/source/system/stack_trace.cpp:162:18: error: โ€˜bfd_get_section_flagsโ€™ was not declared in this scope; did you mean โ€˜bfd_set_section_flagsโ€™?
  162 |             if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
      |                  ^~~~~~~~~~~~~~~~~~~~~
      |                  bfd_set_section_flags
/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/source/system/stack_trace.cpp:165:27: error: โ€˜bfd_get_section_vmaโ€™ was not declared in this scope; did you mean โ€˜bfd_set_section_vmaโ€™?
  165 |             bfd_vma vma = bfd_get_section_vma(abfd, section);
      |                           ^~~~~~~~~~~~~~~~~~~
      |                           bfd_set_section_vma
/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/modules/CppCommon/source/system/stack_trace.cpp:169:37: error: โ€˜bfd_get_section_sizeโ€™ was not declared in this scope; did you mean โ€˜bfd_set_section_sizeโ€™?
  169 |             bfd_size_type secsize = bfd_get_section_size(section);
      |                                     ^~~~~~~~~~~~~~~~~~~~
      |                                     bfd_set_section_size
make[2]: *** [modules/CppCommon/CMakeFiles/cppcommon.dir/build.make:414: modules/CppCommon/CMakeFiles/cppcommon.dir/source/system/stack_trace.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make[1]: *** [CMakeFiles/Makefile2:1118: modules/CppCommon/CMakeFiles/cppcommon.dir/all] Error 2
make[1]: Leaving directory '/home/camdenorrb/Documents/Installed/Make/FastBinaryEncoding/temp'
make: *** [Makefile:141: all] Error 2

Not really sure what to do from here :/

Question about domain declaration and offset calculation

First of all, thank you for the wonderful library, it's working fine and does a great job!
But I'd like to elaborate few things in order to get better understanding.

First, what is the purpose of 'domain' declaration? Is it for all languages or just for some?
It does not appear in the generated .h files.

Second, how the offset is calculated? Is it in bytes or other units? Offset from what?
It's not that obvious as may seem at first glance and I did not find any description of that.

Here is the example:

struct MyBytes
{
  bytes data;
}

I added 9 bytes to the data: [1,9];

Here is the corresponding hex dump of the buffer with my guess of what it means:

21 00 00 00 08 00 00 00  // total size 33 bytes + ? offset 8 bytes from the beginning
0C 00 00 00 02 00 00 00  // ? offset 12 bytes from the beginning + ? Type 2
0C 00 00 00 09 00 00 00  // ???? (4 bytes) + data size 9 bytes 
01 02 03 04 05 06 07 08  // the data
09

Inefficient output stream operator implementation

Now output stream operator includes a set of if statements, which might be inefficient if there are many different enum values. It could be much better if it's replaced by switch statement.

Also it would be very useful to have a separate free function to get const char * of enum. Output stream operator could use the function.

support typedef syntax in domain

Hello, this library is awesome!

I noticed that there is no support for typedef syntax in Domain at this stage.

There are a few scenarios where typedef maybe very useful, for example

When we want to represent the following C++ type

typedef vector<StructA> StructAVec;

It will be useful if we can implement this feature in the domain like:

typedef StructA[] StructAVec;

or

struct StructAVec: StructA[];

Thanks a lot!

C# generated code doesn't generate Send Method

I followed your documentation and i generated C++ code and C# code. However for some reason send method is not generated in C# code.
obrazek

Same proto is used for C++ and C++ was generated without any problems.

Here is the proto

/*
   Protocol description
*/

// Domain declaration
domain com.example

// Package declaration
package proto

// Protocol version
version 1.0

enum LoginResponseCode : byte
{
    Error;
    Success;
    WrongPassOrName;
    Banned;
}

struct BaseMessage
{
    //this id is for response
    [key] int32 responseId;
    bool fireAndForget;
}

struct LoginRequest
{
    string name;
    string pass;
}

struct LoginResult
{
    string name;
    string pass;
}

// Login message declaration
message LoginMessage
{
    LoginRequest login;
}

Thank you in advance.

Add configurable optional<T> support to C++

First, thanks for this great library! I can't compile the generated source code in C++11 mode (I can't upgrade gcc on the builder machine). I try replace optional with some C++11 compatible implementation and it works. So it would be nice to have macros like FBE_OPTIONAL_HEADER and FBE_OPTIONAL_NS for selecting optional implementation.

Build error on Ubuntu 20.04 LTS

lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal
gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

sudo apt install binutils-dev uuid-dev flex bison cmake doxygen graphviz

./unix.sh
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Doxygen: /usr/bin/doxygen (found version "1.8.17") found components: doxygen dot
-- The System identification is Linux 4.19.128-microsoft-standard Platform/Linux
-- Found BISON: /usr/bin/bison (found version "3.5.1")
-- Found FLEX: /usr/bin/flex (found version "2.6.4")
-- The System identification is Linux 4.19.128-microsoft-standard Platform/Linux
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of off64_t
-- Check size of off64_t - done
-- Looking for fseeko
-- Looking for fseeko - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- The System identification is Linux 4.19.128-microsoft-standard Platform/Linux
-- Found LIBBFD: /mnt/c/Program_Dirs/TDM-GCC-64/lib/libbfd.a
-- Found LIBDL: /usr/lib/x86_64-linux-gnu/libdl.so
-- Found LIBRT: /usr/lib/x86_64-linux-gnu/librt.so
-- Found LIBUUID: /usr/lib/x86_64-linux-gnu/libuuid.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dev/temp/FastBinaryEncoding/temp

... and later on:

[ 51%] Linking CXX executable fbec
/usr/bin/ld: modules/CppCommon/libcppcommon.a(stack_trace.cpp.o): in function `CppCommon::StackTrace::StackTrace(int)':
stack_trace.cpp:(.text+0x752): undefined reference to `bfd_openr'
/usr/bin/ld: stack_trace.cpp:(.text+0x76b): undefined reference to `bfd_check_format'
/usr/bin/ld: stack_trace.cpp:(.text+0x787): undefined reference to `bfd_check_format_matches'
/usr/bin/ld: stack_trace.cpp:(.text+0x936): undefined reference to `bfd_close'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/fbec.dir/build.make:283: fbec] Error 1
make[1]: *** [CMakeFiles/Makefile2:292: CMakeFiles/fbec.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

MemoryStream Set: incorrect get size and write to buffer causes exception (C# generator)

E.g. we have input stream with Length = 100 and Capacity = 1000.

public override void Set(MemoryStream value)
...
uint fbeBytesSize = (uint)value.Length; // here we have 100
...
Write(fbeBytesOffset + 4, value.GetBuffer()); // and trying to write 1000

Proposed solution (to c# generator)?

 Write(fbeBytesOffset + 4, value.GetBuffer(), 0, fbeBytesSize);

Watchdog timeout bug in x86

The request functions of the Client class receive a optional parameter size_t timeout.

Example: std::future<void> request(const ::proto::Ping& value, size_t timeout = 0);

Inside the function code we multiply this timeout by timeout * 1000000, since size_t is a macro that change the variable size based on x86 / x64 build, when compiling in x86 the timeout size is unsigned int, if we use a timeout bigger than ~4.3 seconds we have a arithmetic overflow on this multiply operation, causing the malfunction of the watchdog timeout.

Solution: change the function parameter to uint64_t or cast the multiply operation to uint64_t (uint64_t)timeout * 1000000.

Another question that I have about the watchdog is what the best way to run the watchdog? Currently I'm running it in a another thread with 50ms sleep between the calls to it, but I don't know if this imply in a performance decrease since the watchdog will be locking the mutex every 50ms.

It would be nice to have some documentation on the watchdog function, as it is not mentioned anywhere in the documentation (at least I didn't find it), I discovered it by looking at the code generated by FBE.

static DWORD WINAPI WatchdogEventsThread(CWsClient* WsClient)
{
    while (true)
    {
        try
        {
            WsClient->GetWsClient()->watchdog(FBE::utc());
        }
        catch (...)
        {
            LOG("Exception on watchdog thread.");
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    return 0;
}

libfmt issue for cpp

5d98a62

2 issues

  1. in this commit, the macro only checks for FMT_VERSION. but ostream_formatter is only introduced after fmt 9.0.0. So the generated code would fail with earlier version of fmt.

  2. think the user needs to include fmt/ostream.h header file for this to work? while FMT_VERSION is defined in fmt/core.h, so it's worth mentioning that user should include fmt/ostream.h if she already includes fmt/core.h

Not building on Windows (VS2019)

C:\Program_Dev\Git\FastBinaryEncoding\build>vs.bat
-- The C compiler identification is MSVC 19.28.29912.0
-- The CXX compiler identification is MSVC 19.28.29912.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Windows 10.0.19041 Platform/Windows
-- Could NOT find BISON (missing: BISON_EXECUTABLE)
-- Could NOT find FLEX (missing: FLEX_EXECUTABLE)
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Windows 10.0.19041 Platform/Windows
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of off64_t
-- Check size of off64_t - failed
-- Looking for fseeko
-- Looking for fseeko - not found
-- Looking for unistd.h
-- Looking for unistd.h - not found
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- The System identification is Windows 10.0.19041 Platform/Windows
-- Found DbgHelp: C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x86/DbgHelp.Lib
-- Found RPC: C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x86/RpcRT4.Lib
-- Found Userenv: C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0/um/x86/UserEnv.Lib
-- Found LIBVLD: C:/Program_Dev/Git/FastBinaryEncoding/modules/CppCommon/modules/vld/vld.lib
CMake Error at CMakeLists.txt:44 (flex_target):
  Unknown CMake command "flex_target".


-- Configuring incomplete, errors occurred!
See also "C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeOutput.log".
See also "C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeError.log".

CMakeError.log

Determining if the include file pthread.h exists failed with the following output:
Change Dir: C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeTmp

Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe cmTC_f0048.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=16.0 /v:m && Microsoft (R) Build Engine version 16.9.0+57a23d249 for .NET Framework

Copyright (C) Microsoft Corporation. All rights reserved.



  Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29912 for x64

  Copyright (C) Microsoft Corporation.  All rights reserved.

  CheckIncludeFile.c

  cl /c /Zi /W4 /WX /diagnostics:column /Od /Ob0 /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_f0048.dir\Debug\\" /Fd"cmTC_f0048.dir\Debug\vc142.pdb" /Gd /TC /errorReport:queue  /bigobj /bigobj C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\CheckIncludeFile.c

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\CheckIncludeFile.c(1,10): fatal error C1083: Cannot open include file: 'pthread.h': No such file or directory [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_f0048.vcxproj]




Determining size of off64_t failed with the following output:
Change Dir: C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeTmp

Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe cmTC_0404f.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=16.0 /v:m && Microsoft (R) Build Engine version 16.9.0+57a23d249 for .NET Framework

Copyright (C) Microsoft Corporation. All rights reserved.



  Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29912 for x64

  Copyright (C) Microsoft Corporation.  All rights reserved.

  OFF64_T.c

  cl /c /Zi /W4 /WX /diagnostics:column /Od /Ob0 /D WIN32 /D _WINDOWS /D _LARGEFILE64_SOURCE=1 /D HAVE_SYS_TYPES_H /D HAVE_STDINT_H /D HAVE_STDDEF_H /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_0404f.dir\Debug\\" /Fd"cmTC_0404f.dir\Debug\vc142.pdb" /Gd /TC /errorReport:queue  /bigobj /bigobj C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c(29,12): error C2065: 'off64_t': undeclared identifier [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_0404f.vcxproj]

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c(30,12): error C2065: 'off64_t': undeclared identifier [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_0404f.vcxproj]

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c(31,12): error C2065: 'off64_t': undeclared identifier [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_0404f.vcxproj]

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c(32,12): error C2065: 'off64_t': undeclared identifier [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_0404f.vcxproj]

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CheckTypeSize\OFF64_T.c(33,12): error C2065: 'off64_t': undeclared identifier [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_0404f.vcxproj]



C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CheckTypeSize/OFF64_T.c:
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>


#undef KEY
#if defined(__i386)
# define KEY '_','_','i','3','8','6'
#elif defined(__x86_64)
# define KEY '_','_','x','8','6','_','6','4'
#elif defined(__PPC64__)
# define KEY '_','_','P','P','C','6','4','_','_'
#elif defined(__ppc64__)
# define KEY '_','_','p','p','c','6','4','_','_'
#elif defined(__PPC__)
# define KEY '_','_','P','P','C','_','_'
#elif defined(__ppc__)
# define KEY '_','_','p','p','c','_','_'
#elif defined(__aarch64__)
# define KEY '_','_','a','a','r','c','h','6','4','_','_'
#elif defined(__ARM_ARCH_7A__)
# define KEY '_','_','A','R','M','_','A','R','C','H','_','7','A','_','_'
#elif defined(__ARM_ARCH_7S__)
# define KEY '_','_','A','R','M','_','A','R','C','H','_','7','S','_','_'
#endif

#define SIZE (sizeof(off64_t))
static char info_size[] =  {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',
  ('0' + ((SIZE / 10000)%10)),
  ('0' + ((SIZE / 1000)%10)),
  ('0' + ((SIZE / 100)%10)),
  ('0' + ((SIZE / 10)%10)),
  ('0' +  (SIZE    % 10)),
  ']',
#ifdef KEY
  ' ','k','e','y','[', KEY, ']',
#endif
  '\0'};

#ifdef __CLASSIC_C__
int main(argc, argv) int argc; char *argv[];
#else
int main(int argc, char *argv[])
#endif
{
  int require = 0;
  require += info_size[argc];
  (void)argv;
  return require;
}


Determining if the function fseeko exists failed with the following output:
Change Dir: C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeTmp

Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe cmTC_066de.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=16.0 /v:m && Microsoft (R) Build Engine version 16.9.0+57a23d249 for .NET Framework

Copyright (C) Microsoft Corporation. All rights reserved.



  Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29912 for x64

  Copyright (C) Microsoft Corporation.  All rights reserved.

  CheckFunctionExists.c

  cl /c /Zi /W4 /WX /diagnostics:column /Od /Ob0 /D WIN32 /D _WINDOWS /D CHECK_FUNCTION_EXISTS=fseeko /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_066de.dir\Debug\\" /Fd"cmTC_066de.dir\Debug\vc142.pdb" /Gd /TC /errorReport:queue  /bigobj /bigobj "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.19\Modules\CheckFunctionExists.c"

CheckFunctionExists.obj : error LNK2019: unresolved external symbol fseeko referenced in function main [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_066de.vcxproj]

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\Debug\cmTC_066de.exe : fatal error LNK1120: 1 unresolved externals [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_066de.vcxproj]




Determining if the include file unistd.h exists failed with the following output:
Change Dir: C:/Program_Dev/Git/FastBinaryEncoding/temp/CMakeFiles/CMakeTmp

Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/MSBuild/Current/Bin/MSBuild.exe cmTC_1c908.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=16.0 /v:m && Microsoft (R) Build Engine version 16.9.0+57a23d249 for .NET Framework

Copyright (C) Microsoft Corporation. All rights reserved.



  Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29912 for x64

  Copyright (C) Microsoft Corporation.  All rights reserved.

  CheckIncludeFile.c

  cl /c /Zi /W4 /WX /diagnostics:column /Od /Ob0 /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_1c908.dir\Debug\\" /Fd"cmTC_1c908.dir\Debug\vc142.pdb" /Gd /TC /errorReport:queue  /bigobj /bigobj C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\CheckIncludeFile.c

C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\CheckIncludeFile.c(1,10): fatal error C1083: Cannot open include file: 'unistd.h': No such file or directory [C:\Program_Dev\Git\FastBinaryEncoding\temp\CMakeFiles\CMakeTmp\cmTC_1c908.vcxproj]

Pointer to GO slice

Currently there is no notation in FBE's domain model capable of outputting:

type MyType struct {
    Tags *[]string `json:"tags,omitempty"`
}

Any plans on adding support for pointer to vector, array, list etc?

Documentation ambiguity

In the description of the wire format, it is unclear if the "size" parameter for arrays, lists, etc is the number of bytes the data structure takes on the wire, or a count of the number of elements in the data structure. Which is the correct interpretation? Please update the documentation to clear up this ambiguity. If it is the former, an option for a 64-bit size would be helpful.

Another thing you might want to document is how arrays and lists are accessed. If I want to access element M of N, do I have to waste time traversing M elements to get to it, which makes FBE essentially impossible to use with more than a tiny M because it is far too slow, or is it addressed directly?

Build failed on Mac OS

  • Darwin-16.7.0
  • AppleClang 9.0.0.9000039
In file included from /Users/ton/Developer/FastBinaryEncoding/tests/test_clone.cpp:7:
In file included from /Users/ton/Developer/FastBinaryEncoding/tests/../proto/proto.h:16:
/Users/ton/Developer/FastBinaryEncoding/tests/../proto/fbe.h:27:10: fatal error: 'optional' file
      not found
#include <optional>
         ^~~~~~~~~~

Question: can you share any technical detail?

Hi,

I have just found out about this library and it looks very impressive.
I am quite familiar with Flatbuffers and its implementation and I am just curious: can you share any detail about the reason why your approach outperform others that have "zero copy" deserialization?

Thanks for sharing your work.

Davide

Compare to Bond

I notice that Bond is missing from the benchmark comparison in readme.md. Given that Bond is another competitor of Protobuf etc., I would like to know how this compares to that option in terms of performance.

Leak if sending data in a loop.

I am trying to check net capacity and I am doing:

    private async Task FakeDataSource()
    {
        await Task.Delay(500);
        Random rnd = new Random();
        var randomBytes = new byte[64000]; // 64k
        rnd.NextBytes(randomBytes);

        while (true)
        {
             var packet = new VideoPacket(1280, 720, new MemoryStream(randomBytes , 0, randomBytes .Length, false, true));
             _client.Send(packet);
        }
    }
  • _client is SimpleProtoClient as in the example.
  • VideoPacket is a message defined as
message VideoPacket
{
    uint16 width;
    uint16 height;
    bytes data;
}

Memory goes high in few seconds taking some Gb and then it crashes, I can see that an object of type Buffer has got all the RAM. As a weird note, If I add "await Task.Delay(1);" after the Send() it doesn't crash (but obviously is sending just a fraction of what's possible ).

What I am doing wrong ? How can I send as much as possible?

executing fbec command(C#) with multiple .fbe files gives some missing dependency errors

Attached a simple vs project.
Paragon.DoT.zip

For example, have a look at this file:

  • Network/Messages/dot_network_messages.cs

All files were generated using this .bat file:
Run the Paragon.DoT\DoT\run-fbe.bat file and you will know what do I mean.

See if this is possible to fix or if it is better to use one BIG .fbe FILE.

Apart from that, would be nice to add support for subpackages using '.' in C#.

Thank you chronoxor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.