Durch die schnelle binäre Codierung werden Domänenmodelle, Geschäftsobjekte, komplexe Datenstrukturen, Client/Server -Anforderungen und -antworten beschrieben und nativen Code für verschiedene Programmiersprachen und -plattformen generiert.
Schnelle binäre Codierungsdokumentation
Schnelle Binärcodierung Downloads
Schnelle binäre Codierungsspezifikation
Der Leistungsvergleich mit anderen Protokollen finden Sie hier:
| Protokoll | Nachrichtengröße | Serialisierungszeit | Deserialisierungszeit |
|---|---|---|---|
| Cap'n'proto | 208 Bytes | 558 ns | 359 ns |
| FASTBINYECODING | 234 Bytes | 66 ns | 82 ns |
| Flatbuffer | 280 Bytes | 830 ns | 290 ns |
| Protobuf | 120 Bytes | 628 ns | 759 ns |
| JSON | 301 Bytes | 740 ns | 500 ns |
Der typische Verwendungsworkflow ist der folgende:
Beispielprojekte:
Optional:
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.batUm eine schnelle binäre Codierung zu verwenden, sollten Sie ein Domänenmodell (auch bekannt als Business -Objekte) bereitstellen. Ein Domänenmodell ist eine Reihe von Enums, Flags und Strukturen, die sich miteinander beziehen und in einer Hierarchie möglicherweise aggregiert werden.
FBE -Formatspezifikation (schneller binärer Codierungsformat)
Es gibt ein Beispiel-Domänenmodell, das die Beziehung zwischen den Kontoausschüssen einer abstrakten Handelsplattform beschreibt:
// 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;
}Der nächste Schritt ist eine Domänenmodell -Kompilierung mit dem "FBEC" -Kompiler, der einen generierten Code für die erforderliche Programmiersprache erstellt.
Der folgende Befehl erstellt einen C ++ generierten Code:
fbec --c++ --input=proto.fbe --output=.Alle möglichen Optionen für den "FBEC" -Kompiler sind Folgendes:
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 codeDas generierte Domänenmodell wird mit Quellcode für die jeweilige Sprache dargestellt. Fügen Sie es einfach Ihrem Projekt hinzu und bauen Sie es auf. Es gibt mehrere Probleme und Abhängigkeiten, die erwähnt werden sollten:
<fmt/format.h> und <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 uuidtoolsFast Binary Coding (FBE) ist ein schnelles und kompaktes binäres Format bei der Darstellung einzelner Domänenmodelle in verschiedenen Programmiersprachen und Plattformen. Auch FBE -Format löst das Protokollversioning -Problem.
Befolgen Sie die folgenden Schritte, um ein Domänenobjekt zu serialisieren:
Befolgen Sie die folgenden Schritte, um ein Domänenobjekt zu Deserialisierung:
Hier ist ein Exmple der FBE -Serialisierung in C ++ - Sprache:
# 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 ;
}Ausgabe ist Folgendes:
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 ist möglich, mehr Serialisierungsgeschwindigkeit zu erreichen, wenn Ihr Protokoll ausgereift ist, sodass Sie die endgültige Version beheben und die Versionierung deaktivieren können, die zusätzliche Größe und Zeit zum Verarbeiten erfordert.
| Protokoll | Nachrichtengröße | Serialisierungszeit | Deserialisierungszeit | Zeit überprüfen |
|---|---|---|---|---|
| Fbe | 252 Bytes | 88 ns | 98 ns | 33 ns |
| FBE Finale | 152 Bytes | 57 ns | 81 ns | 28 ns |
Das endgültige Domänenmodell kann mit der FLAGE zusammengestellt werden. Als Ergebnis stehen zusätzliche endgültige Modelle für die Serialisierung zur Verfügung.
Befolgen Sie die folgenden Schritte, um jedes Domänenobjekt im endgültigen Format zu serialisieren:
Befolgen Sie die folgenden Schritte, um ein Domänenobjekt zu Deserialisierung:
Hier ist ein Exmple der FBE -Final -Serialisierung in C ++ - Sprache:
# 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 ;
}Ausgabe ist Folgendes:
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)
]
)
Wenn das Domänenmodell mit -JSON -Flag kompiliert wird, wird der JSON -Serialisierungscode in allen Domänenobjekten generiert. Als Ergebnis kann jedes Domänenobjekt in/aus JSON -Format serialisiert/deserialisiert werden.
Bitte beachten Sie, dass einige Programmiersprachen einen nativen JSON -Support (JavaScript, Python) haben. Andere Sprachen erfordert die Bibliothek von Drittanbietern, um mit JSON zusammenzuarbeiten:
Hier ist ein Exmple der JSON -Serialisierung in C ++ - Sprache:
# 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 ;
}Ausgabe ist Folgendes:
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)
]
)
Die Pakete werden mit dem Paketnamen und dem Strukturenversatz (optional) deklariert. Der Offset wird zum inkrementierten Strukturtyp hinzugefügt, wenn nicht explizit bereitgestellt wurde.
Hier ist ein Beispiel für die einfache Paketerklärung:
// 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
{
...
}Ein Paket kann in ein anderes importiert werden und alle Aufzüge, Flaggen und Strukturen können im aktuellen Paket wiederverwendet werden. Paketversatz wird hier verwendet, um Strukturen -Typen zu vermeiden: Schnittpunkte:
// 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
{
...
}Mehrer Paketimport ist auch möglich:
// Package declaration. Offset is 100.
package test offset 100
// Package import
import proto
import protoex
...Der Paketimport wird mit:
Einige von Strukturen (einer oder viele) können mit dem Attribut von '[Schlüssel] markiert werden. Als Ergebnis werden entsprechende Vergleichsbetreiber generiert, die es ermöglichen, zwei Instanzen der Struktur (Gleichheit, Ordnung, Hashing) mit markierten Feldern zu vergleichen. Diese Fähigkeit ermöglicht es, die Struktur als Schlüssel für assoziative Karte und Hash -Container zu verwenden.
Beispiel unten zeigt die Verwendung des Attributs von '[Key]':
struct MyKeyStruct
{
[key] int32 uid;
[key] stirng login;
string name;
string address;
}Nach der Codegenerierung für C ++ - Sprache wird die folgende vergleichbare Klasse generiert:
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); }
...
};Strukturypzahlen werden automatisch erhöht, bis Sie es manuell zur Verfügung stellen. Es gibt zwei Möglichkeiten:
Beispiel unten zeigt die Idee:
// 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
{
...
}Strukturen können von einer anderen Struktur vererbt werden. In diesem Fall werden alle Felder aus der Basisstruktur in einem Kind vorhanden sein.
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;
}Außerdem ist es möglich, die Basisstruktur -Typ -Nummer in einem untergeordneten Operator "= Basis" wiederzuverwenden. Es ist nützlich, wenn Sie die Struktur vom importierten Paket von Drittanbietern erweitern:
// 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;
}Die Versionierung ist einfach mit einer schnellen Binärcodierung.
Angenommen, Sie haben ein originales Protokoll:
package proto
enum MyEnum
{
value1;
value2;
}
flags MyFlags
{
none = 0x00;
flag1 = 0x01;
flag2 = 0x02;
flag3 = 0x04;
}
struct MyStruct
{
bool field1;
byte field2;
char field3;
}Sie müssen es mit neuen Aufzünder-, Flag- und Strukturmwerten erweitern. Fügen Sie einfach die erforderlichen Werte zum Ende der entsprechenden Deklarationen hinzu:
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)
}Jetzt können Sie Strukturen in verschiedenen Kombinationen serialisieren und deserialisieren:
Wenn Sie kein Protokoll von Drittanbietern modifizieren können, können Sie immer noch eine Lösung zur Erweiterung haben. Erstellen Sie einfach ein neues Protokoll und importieren Sie einen Drittanbieter. Dann erweitern Sie Strukturen mit Vererbung:
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)
}Wenn das Domänenmodell mit dem Sender -Flag kompiliert wird, wird der Protokollcode des Absender/Empfängers generiert.
Die Sendersschnittstelle enthält Methoden "Send (struktur) für alle Domänenmodellstrukturen. Außerdem hat es eine abstrakte "Onsend (Daten, Größe)" -Methode, die implementiert werden sollte, um serialisierte Daten an einen Sockel, eine Rohr-, Pipe usw. zu senden.
Die Empfängerschnittstelle enthält 'OnReceive (Struct)' Handler für alle Domänenmodellstrukturen. Außerdem hat es eine öffentliche "OnReceive (Typ, Daten, Größe)" -Methode ", mit der der Empfänger mit empfangenen Daten aus einem Sockel, einer Rohr usw. ernährt werden sollte.
Hier ist ein Unterschied über die Verwendung von Sendern/Empfänger -Kommunikationsprotokoll in C ++ - Sprache:
# 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 ;
}Ausgabe ist Folgendes:
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)])
Alle Benchmarks verwenden das gleiche Domänenmodell, um ein einzelnes Konto mit drei Bestellungen zu erstellen:
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 );Serialisierungsbenchmark C ++ Code:
BENCHMARK_FIXTURE (SerializationFixture, " Serialize " )
{
// Reset FBE stream
writer. reset ();
// Serialize the account to the FBE stream
writer. serialize (account);
}Serialisierungsbenchmarkergebnisse:
| Sprache & Plattform | Nachrichtengröße | Serialisierungsrate | Serialisierungszeit |
|---|---|---|---|
| C ++ Win64 | 252 Bytes | 10 416 667 ops/s | 96 ns |
| C ++ Win64 (Finale) | 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 (Finale) | 152 Bytes | 1 597 444 OPS/S | 626 ns |
| C# Win64 (JSON) | 341 Bytes | 434 783 OPS/s | 2 300 ns |
| Geh Win64 | 252 Bytes | 2 739 726 ops/s | 365 ns |
| Go Win64 (Finale) | 152 Bytes | 2 949 852 OPS/S | 339 ns |
| Geh Win64 (JSON) | 341 Bytes | 258 732 Ops/s | 3 865 ns |
| Java Win64 | 252 Bytes | 4 247 162 OPS/S | 236 ns |
| Java Win64 (Finale) | 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 (Finale) | 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 (Finale) | 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 (Finale) | 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 (Finale) | 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 (endgültig) | 152 Bytes | 100 755 Ops/s | 9 925 ns |
| Swift macos (JSON) | 353 Bytes | 18 534 OPS/s | 53 953 ns |
Deserialisierung Benchmark C ++ Code:
BENCHMARK_FIXTURE (DeserializationFixture, " Deserialize " )
{
// Deserialize the account from the FBE stream
reader. deserialize (deserialized);
}Deserialisierungs -Benchmark -Ergebnisse:
| Sprache & Plattform | Nachrichtengröße | Deserialisierungsrate | Deserialisierungszeit |
|---|---|---|---|
| C ++ Win64 | 252 Bytes | 9 523 810 ops/s | 105 ns |
| C ++ Win64 (Finale) | 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 (Finale) | 152 Bytes | 1 607 717 OPS/S | 622 ns |
| C# Win64 (JSON) | 341 Bytes | 258 532 Ops/s | 3 868 ns |
| Geh Win64 | 252 Bytes | 1 510 574 OPS/S | 662 ns |
| Go Win64 (Finale) | 152 Bytes | 1 540 832 OPS/S | 649 ns |
| Geh Win64 (JSON) | 341 Bytes | 251 825 OPS/s | 3 971 ns |
| Java Win64 | 252 Bytes | 2 688 084 OPS/S | 372 ns |
| Java Win64 (Finale) | 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 (Finale) | 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 (Finale) | 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 (Finale) | 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 (Finale) | 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 (endgültig) | 152 Bytes | 10 3519 OPS/s | 9 660 ns |
| Swift macos (JSON) | 353 Bytes | 17 077 OPS/s | 58 558 ns |
Überprüfen Sie den Benchmark C ++ - Code:
BENCHMARK_FIXTURE (VerifyFixture, " Verify " )
{
// Verify the account
model. verify ();
}Überprüfen Sie die Benchmark -Ergebnisse:
| Sprache & Plattform | Nachrichtengröße | Rate überprüfen | Zeit überprüfen |
|---|---|---|---|
| C ++ Win64 | 252 Bytes | 31 250 000 OPS/S | 32 ns |
| C ++ Win64 (Finale) | 152 Bytes | 35 714 286 OPS/S | 28 ns |
| C# Win64 | 252 Bytes | 4 504 505 Ops/S | 222 ns |
| C# Win64 (Finale) | 152 Bytes | 8 064 516 ops/s | 124 ns |
| Geh Win64 | 252 Bytes | 8 474 576 ops/s | 118 ns |
| Go Win64 (Finale) | 152 Bytes | 9 090 909 OPS/S | 110 ns |
| Java Win64 | 252 Bytes | 11 790 374 OPS/S | 85 ns |
| Java Win64 (Finale) | 152 Bytes | 16 205 533 OPS/S | 62 ns |
| JavaScript Win64 | 252 Bytes | 1 105 627 ops/s | 905 ns |
| JavaScript Win64 (Finale) | 152 Bytes | 5 700 408 OPS/S | 175 ns |
| Kotlin Win64 | 252 Bytes | 8 625 935 OPS/S | 116 ns |
| Kotlin Win64 (Finale) | 152 Bytes | 13 373 757 ops/s | 75 ns |
| Python Win64 | 252 Bytes | 20 825 OPS/s | 48 019 ns |
| Python Win64 (Finale) | 152 Bytes | 23 590 Ops/s | 42 391 ns |
| Ruby Win64 | 252 Bytes | 57 201 Ops/s | 17 482 ns |
| Ruby Win64 (Finale) | 152 Bytes | 74 262 Ops/s | 13 466 ns |
| Swift macos | 252 Bytes | 164 446 OPS/s | 6 081 ns |
| Swift macos (endgültig) | 152 Bytes | 228 154 Ops/s | 4 383 ns |