La codificación binaria rápida permite describir cualquier modelo de dominio, objetos comerciales, estructuras de datos complejas, solicitudes y respuestas de clientes/servidores y generar código nativo para diferentes lenguajes y plataformas de programación.
Documentación de codificación binaria rápida
Descargas de codificación binaria rápida
Especificación de codificación binaria rápida
La comparación de rendimiento con otros protocolos se puede encontrar aquí:
| Protocolo | Tamaño de mensaje | Tiempo de serialización | Tiempo de deserialización |
|---|---|---|---|
| Cap'n'proto | 208 bytes | 558 ns | 359 ns |
| Fastbinarycoding | 234 bytes | 66 ns | 82 ns |
| Plateros | 280 bytes | 830 ns | 290 ns |
| Protobuf | 120 bytes | 628 ns | 759 ns |
| Json | 301 bytes | 740 ns | 500 ns |
El flujo de trabajo de uso típico es el siguiente:
Proyectos de muestra:
Opcional:
sudo apt-get install -y binutils-dev uuid-dev flex bisonbrew install flex bisonchoco install winflexbison3pip3 install gilgit clone https://github.com/chronoxor/FastBinaryEncoding.git
cd FastBinaryEncoding
gil update cd build
./unix.sh cd build
./unix.sh cd build
unix.bat cd build
unix.bat cd build
mingw.bat cd build
vs.batPara usar la codificación binaria rápida, debe proporcionar un modelo de dominio (también conocido como objetos comerciales). Un modelo de dominio es un conjunto de enumines, banderas y estructuras que se relacionan entre sí y podrían agregarse en alguna jerarquía.
Especificación de formato de codificación binaria rápida (FBE)
Existe un modelo de dominio de muestra que describe la relación de los órdenes de equilibrio de cuentas de alguna plataforma de negociación abstracta:
// 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;
}El siguiente paso es una compilación de modelo de dominio utilizando el compilador 'FBEC' que creará un código generado para el lenguaje de programación requerido.
El siguiente comando creará un código generado por C ++:
fbec --c++ --input=proto.fbe --output=.Todas las opciones posibles para el compilador 'FBEC' son las siguientes:
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 codeEl modelo de dominio generado se representa con el código fuente para el idioma particular. Simplemente agréguelo a su proyecto y cree. Hay varios problemas y dependencias que deben mencionarse:
<fmt/format.h> y <fmt/ostream.h> ;go get github.com/stretchr/testify );go get github.com/json-iterator/go );go get github.com/shopspring/decimal );go get github.com/google/uuid );gem install json
gem install uuidtoolsLa codificación binaria rápida (FBE) es un formato binario rápido y compacto de representar modelos de dominio único en diferentes lenguajes y plataformas de programación. También el formato FBE resuelve el problema de versiones de protocolo.
Siga los pasos a continuación para serializar cualquier objeto de dominio:
Siga los pasos a continuación para deserializar cualquier objeto de dominio:
Aquí hay un EXMPLE de serialización de FBE en el lenguaje C ++:
# 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 ;
}La salida es lo siguiente:
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)
]
)
Es posible lograr una mayor velocidad de serialización si su protocolo es lo suficientemente maduro para que pueda arreglar su versión final y deshabilitar el versículo que requiere un tamaño y tiempo adicionales para procesar.
| Protocolo | Tamaño de mensaje | Tiempo de serialización | Tiempo de deserialización | Verificar el tiempo |
|---|---|---|---|---|
| Fbe | 252 bytes | 88 ns | 98 ns | 33 ns |
| FBE final | 152 bytes | 57 ns | 81 ns | 28 ns |
El modelo de dominio final se puede compilar con la bandera -cinal. Como resultado, los modelos finales adicionales estarán disponibles para la serialización.
Siga los pasos a continuación para serializar cualquier objeto de dominio en formato final:
Siga los pasos a continuación para deserializar cualquier objeto de dominio:
Aquí hay un Exmple de la serialización final de FBE en el lenguaje C ++:
# 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 ;
}La salida es lo siguiente:
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)
]
)
Si el modelo de dominio compilado con la bandera --json, entonces el código de serialización JSON se generará en todos los objetos de dominio. Como resultado, cada objeto de dominio se puede serializar/deserializarse en/desde el formato JSON.
Tenga en cuenta que algunos lenguajes de programación tienen soporte JSON nativo (JavaScript, Python). Otros idiomas requieren una biblioteca de terceros para trabajar con JSON:
Aquí hay un EXMPLE de la serialización JSON en el lenguaje C ++:
# 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 ;
}La salida es lo siguiente:
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)
]
)
Los paquetes se declaran con nombre de paquete y compensación de estructuras (opcional). El desplazamiento se agregará al tipo de estructura incrementada si no se proporciona explícito.
Aquí hay un ejemplo de la declaración de paquete simple:
// 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
{
...
}Un paquete se puede importar a otro y todos los enums, banderas y estructuras se pueden reutilizar en el paquete actual. El desplazamiento del paquete se usa aquí para evitar la intersección de los tipos de estructuras:
// 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
{
...
}La importación de paquetes múltiples también es posible:
// Package declaration. Offset is 100.
package test offset 100
// Package import
import proto
import protoex
...La importación de paquetes se implementa utilizando:
Algunas de las archivos de estructura (uno o muchos) se pueden marcar con el atributo '[clave]'. A medida que se generará operadores de comparación correspondientes, que permitan comparar dos instancias de la estructura (igualdad, ordenar, hash) mediante campos marcados. Esta habilidad permite usar la estructura como clave en el mapa asociativo y los contenedores hash.
El siguiente ejemplo demuestra el uso del atributo '[clave]':
struct MyKeyStruct
{
[key] int32 uid;
[key] stirng login;
string name;
string address;
}Después de la generación de código para el lenguaje C ++, se generará la siguiente clase comparable:
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); }
...
};Los números de tipo de estructura se incrementan automáticamente hasta que lo proporcione manualmente. Hay dos posibilidades:
El ejemplo a continuación demuestra la 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
{
...
}Las estructuras se pueden heredar de otra estructura. En este caso, todos los campos de la estructura base estarán presentes en uno niño.
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;
}También es posible reutilizar el número de tipo de estructura base en un niño que usa el operador '= base'. Es útil cuando extiende la estructura del paquete importado de terceros:
// 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;
}El verso es simple con una codificación binaria rápida.
Suponga que tiene un protocolo original:
package proto
enum MyEnum
{
value1;
value2;
}
flags MyFlags
{
none = 0x00;
flag1 = 0x01;
flag2 = 0x02;
flag3 = 0x04;
}
struct MyStruct
{
bool field1;
byte field2;
char field3;
}Debe extenderlo con nuevos valores de Enum, Flag y Struct. Simplemente agregue los valores requeridos al final de las declaraciones correspondientes:
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)
}Ahora puede serializar y deserializar estructuras en diferentes combinaciones:
Si no puede modificar algún protocolo de terceros, aún puede tener una solución para extenderlo. Simplemente cree un nuevo protocolo e importe un tercero en él. Luego extienda las estructuras con herencia:
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)
}Si el modelo de dominio compilado con el indicador --sender, entonces se generará el código del protocolo del remitente/receptor.
La interfaz del remitente contiene métodos 'Enviar (struct)' para todas las estructuras del modelo de dominio. También tiene método abstracto 'onsend (datos, tamaño)' que debe implementarse para enviar datos serializados a un enchufe, tubería, etc.
La interfaz receptor contiene manejadores 'OnReceive (Struct)' para todas las estructuras del modelo de dominio. También tiene método público 'onreceive (tipo, datos, tamaño)' que debe usarse para alimentar al receptor con datos recibidos de un zócalo, tubería, etc.
Aquí hay un Exmple del uso del protocolo de comunicación del remitente/receptor en el lenguaje C ++:
# 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 ;
}La salida es lo siguiente:
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)])
Todos los puntos de referencia usan el mismo modelo de dominio para crear una sola cuenta con tres pedidos:
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 );Código de referencia de referencia de serialización C ++:
BENCHMARK_FIXTURE (SerializationFixture, " Serialize " )
{
// Reset FBE stream
writer. reset ();
// Serialize the account to the FBE stream
writer. serialize (account);
}Resultados de referencia de serialización:
| Idioma y plataforma | Tamaño de mensaje | Tasa de serialización | Tiempo de serialización |
|---|---|---|---|
| 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 |
| Ir 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 |
| MacOS Swift | 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 |
Código C ++ de referencia de deserialización:
BENCHMARK_FIXTURE (DeserializationFixture, " Deserialize " )
{
// Deserialize the account from the FBE stream
reader. deserialize (deserialized);
}Resultados de referencia de deserialización:
| Idioma y plataforma | Tamaño de mensaje | Tasa de deserialización | Tiempo de deserialización |
|---|---|---|---|
| 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 |
| Ir 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 |
| MacOS Swift | 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 |
Verificar el código de referencia C ++:
BENCHMARK_FIXTURE (VerifyFixture, " Verify " )
{
// Verify the account
model. verify ();
}Verificar resultados de referencia:
| Idioma y plataforma | Tamaño de mensaje | Verificar la tasa | Verificar el tiempo |
|---|---|---|---|
| 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 |
| Ir 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 |
| MacOS Swift | 252 bytes | 164 446 OPS/S | 6 081 ns |
| Swift MacOS (final) | 152 bytes | 228 154 OPS/s | 4 383 ns |