高速バイナリエンコードにより、ドメインモデル、ビジネスオブジェクト、複雑なデータ構造、クライアント/サーバーリクエストと応答を記述し、さまざまなプログラミング言語とプラットフォームのネイティブコードを生成できます。
高速バイナリエンコーディングドキュメント
高速バイナリエンコードダウンロード
高速バイナリエンコード仕様
他のプロトコルとのパフォーマンス比較は、こちらにあります:
| プロトコル | メッセージサイズ | シリアル化時間 | 敏arialialization時間 |
|---|---|---|---|
| Cap'n'proto | 208バイト | 558 ns | 359 ns |
| fastbinaryEncoding | 234バイト | 66 ns | 82 ns |
| フラットバッファー | 280バイト | 830 ns | 290 ns |
| プロトブフ | 120バイト | 628 ns | 759 ns |
| JSON | 301バイト | 740 ns | 500 ns |
典型的な使用ワークフローは次のとおりです。
サンプルプロジェクト:
オプション:
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.bat高速バイナリエンコーディングを使用するには、ドメインモデル(別名ビジネスオブジェクト)を提供する必要があります。ドメインモデルは、互いに関連し、いくつかの階層に集約される可能性のある列挙、フラグ、構造のセットです。
高速バイナリエンコーディング(FBE)形式仕様
いくつかの抽象取引プラットフォームのアカウントバランスの関係を説明するサンプルドメインモデルがあります。
// 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;
}次のステップは、必要なプログラミング言語の生成されたコードを作成する「FBEC」コンパイラを使用したドメインモデルコンパイルです。
次のコマンドは、C ++生成コードを作成します。
fbec --c++ --input=proto.fbe --output=.「FBEC」コンパイラのすべての可能なオプションは次のとおりです。
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生成されたドメインモデルは、特定の言語のソースコードで表されます。プロジェクトに追加して構築してください。言及すべきいくつかの問題と依存関係があります:
<fmt/format.h>および<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 uuidtools高速バイナリエンコーディング(FBE)は、さまざまなプログラミング言語やプラットフォームで単一ドメインモデルを表す高速でコンパクトなバイナリ形式です。また、FBE形式はプロトコルバージョンの問題を解決します。
ドメインオブジェクトをシリアル化するために、以下の手順に従ってください。
任意のドメインオブジェクトをゆるくするために、以下の手順に従ってください。
これは、C ++言語でのFBEシリアル化の例です。
# 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 ;
}出力は次のとおりです。
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)
]
)
プロトコルが十分に成熟している場合、より多くのシリアル化速度を達成することができます。そのため、最終バージョンを修正し、処理するために余分なサイズと時間を必要とするバージョンを無効にすることができます。
| プロトコル | メッセージサイズ | シリアル化時間 | 敏arialialization時間 | 時間を確認します |
|---|---|---|---|---|
| fbe | 252バイト | 88 ns | 98 ns | 33 ns |
| FBEファイナル | 152バイト | 57 ns | 81 ns | 28 ns |
最終ドメインモデルは、 - ファイナルフラグでコンパイルできます。その結果、追加の最終モデルがシリアル化に利用可能になります。
任意のドメインオブジェクトを最終形式でシリアル化するために、以下の手順に従ってください。
任意のドメインオブジェクトをゆるくするために、以下の手順に従ってください。
これは、C ++言語でのFBE最終シリアル化の例です。
# 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 ;
}出力は次のとおりです。
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フラグでコンパイルされたドメインモデルの場合、JSONシリアル化コードはすべてのドメインオブジェクトで生成されます。結果として、各ドメインオブジェクトは、JSON形式に/from Serializated/Daserializedを使用できます。
一部のプログラミング言語には、ネイティブJSONサポート(JavaScript、Python)があることに注意してください。他の言語では、JSONとの仕事を得るためにサードパーティライブラリが必要です。
これは、C ++言語でのJSONシリアル化の例です。
# 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 ;
}出力は次のとおりです。
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)
]
)
パッケージは、パッケージ名とstructs offset(オプション)で宣言されます。オフセットは、明示的に提供されていない場合、増分構造タイプに追加されます。
これが簡単なパッケージ宣言の例です。
// 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
{
...
}あるパッケージを別のパッケージにインポートでき、すべての列挙、フラグ、および構造体を現在のパッケージで再利用できます。ここでは、構造体の種類の交差点を回避するためにパッケージオフセットが使用されます。
// 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
{
...
}複数のパッケージインポートも可能です。
// Package declaration. Offset is 100.
package test offset 100
// Package import
import proto
import protoex
...パッケージのインポートは以下を使用して実装されます。
いくつかのstructファイリング(1つまたは多く)には、「[key]」属性でマークできます。結果として対応する比較演算子が生成され、マークされたフィールドで構造体(等式、順序、ハッシュ)の2つのインスタンスを比較できます。この機能により、構造体を連想マップおよびハッシュコンテナのキーとして使用できます。
以下の例は、「[key]」属性の使用法を示しています。
struct MyKeyStruct
{
[key] int32 uid;
[key] stirng login;
string name;
string address;
}C ++言語のコード生成の後、次の同等のクラスが生成されます。
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); }
...
};構造体タイプ数は、手動で提供するまで自動的に増加します。 2つの可能性があります:
以下の例は、アイデアを示しています。
// 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
{
...
}構造体は別の構造体から継承できます。この場合、ベース構造体からのすべてのフィールドが子供のフィールドに存在します。
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;
}また、 '= base'演算子を使用して、子供のベース構造体タイプ数を再利用することもできます。サードパーティのインポートパッケージから構造体を拡張する場合に役立ちます。
// 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;
}バージョン化は、高速バイナリエンコーディングで簡単です。
元のプロトコルがあると仮定します。
package proto
enum MyEnum
{
value1;
value2;
}
flags MyFlags
{
none = 0x00;
flag1 = 0x01;
flag2 = 0x02;
flag3 = 0x04;
}
struct MyStruct
{
bool field1;
byte field2;
char field3;
}新しいenum、flag、およびstructの値で拡張する必要があります。対応する宣言の最後に必要な値を追加するだけです。
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)
}これで、さまざまな組み合わせで構造体をシリアル化して脱暗起することができます。
サードパーティのプロトコルを変更できない場合でも、拡張の解決策があります。新しいプロトコルを作成し、サードパーティのプロトコルをインポートするだけです。次に、継承で構造体を拡張します。
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フラグでコンパイルされたドメインモデルの場合、送信者/レシーバープロトコルコードが生成されます。
Sender Interfaceには、すべてのドメインモデル構造体の「送信(struct)」メソッドが含まれます。また、シリアル化されたデータをソケット、パイプなどに送信するために実装する必要がある「Onsend(データ、サイズ)」メソッドもあります。
受信機インターフェイスには、すべてのドメインモデル構造体の「OnReceive(struct)」ハンドラーが含まれます。また、レシーバーにソケット、パイプなどから受信したデータをフィードするために使用する必要がある公開「oneceive(タイプ、データ、サイズ)」メソッドもあります。
これは、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 ;
}出力は次のとおりです。
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)])
すべてのベンチマークは同じドメインモデルを使用して、3つの注文で単一のアカウントを作成します。
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 ++コード:
BENCHMARK_FIXTURE (SerializationFixture, " Serialize " )
{
// Reset FBE stream
writer. reset ();
// Serialize the account to the FBE stream
writer. serialize (account);
}シリアル化ベンチマークの結果:
| 言語とプラットフォーム | メッセージサイズ | シリアル化率 | シリアル化時間 |
|---|---|---|---|
| C ++ Win64 | 252バイト | 10 416 667 ops/s | 96 ns |
| C ++ Win64(最終) | 152バイト | 16 129 032 ops/s | 62 ns |
| C ++ Win64(JSON) | 353バイト | 926 784 ops/s | 1 079 ns |
| C#Win64 | 252バイト | 1 432 665 ops/s | 698 ns |
| C#Win64(最終) | 152バイト | 1 597 444 ops/s | 626 ns |
| C#Win64(JSON) | 341バイト | 434 783 ops/s | 2 300 ns |
| win64に行きます | 252バイト | 2 739 726 ops/s | 365 ns |
| Go Win64(最終) | 152バイト | 2 949 852 ops/s | 339 ns |
| Go Win64(JSON) | 341バイト | 258 732 ops/s | 3 865 ns |
| Java Win64 | 252バイト | 4 247 162 ops/s | 236 ns |
| JavaWin64(最終) | 152バイト | 4 883 205 ops/s | 205 ns |
| JavaWin64(JSON) | 353バイト | 213 983 ops/s | 4 673 ns |
| JavaScript win64 | 252バイト | 93 416 ops/s | 10 705 ns |
| JavaScriptWin64(最終) | 152バイト | 112 665 ops/s | 8 876 ns |
| JavaScriptWin64(JSON) | 341バイト | 217 637 ops/s | 4 595 ns |
| Kotlin Win64 | 252バイト | 3 546 694 OPS/s | 282 ns |
| Kotlin Win64(最終) | 152バイト | 4 096 406 ops/s | 244 ns |
| Kotlin Win64(JSON) | 353バイト | 185 788 ops/s | 5 382 ns |
| Python Win64 | 252バイト | 9 434 ops/s | 105 999 ns |
| Python Win64(最終) | 152バイト | 11 635 ops/s | 85 945 ns |
| Python Win64(JSON) | 324バイト | 61 737 ops/s | 16 198 ns |
| Ruby Win64 | 252バイト | 23 013 ops/s | 43 453 ns |
| Ruby Win64(最終) | 152バイト | 33 361 ops/s | 29 975 ns |
| Ruby Win64(JSON) | 353バイト | 50 842 ops/s | 19 669 ns |
| 迅速なマコー | 252バイト | 74 002 ops/s | 13 513 ns |
| Swift MacOS(最終) | 152バイト | 100 755 ops/s | 9 925 ns |
| Swift MacOS(JSON) | 353バイト | 18 534 ops/s | 53 953 ns |
Desarialization Benchmark C ++コード:
BENCHMARK_FIXTURE (DeserializationFixture, " Deserialize " )
{
// Deserialize the account from the FBE stream
reader. deserialize (deserialized);
}脱介入ベンチマークの結果:
| 言語とプラットフォーム | メッセージサイズ | 敏latialialization速度 | 敏arialialization時間 |
|---|---|---|---|
| C ++ Win64 | 252バイト | 9 523 810 ops/s | 105 ns |
| C ++ Win64(最終) | 152バイト | 10 989 011 ops/s | 91 ns |
| C ++ Win64(JSON) | 353バイト | 1 375 516 OPS/s | 727 ns |
| C#Win64 | 252バイト | 1 014 199 ops/s | 986 ns |
| C#Win64(最終) | 152バイト | 1 607 717 ops/s | 622 ns |
| C#Win64(JSON) | 341バイト | 258 532 ops/s | 3 868 ns |
| win64に行きます | 252バイト | 1 510 574 ops/s | 662 ns |
| Go Win64(最終) | 152バイト | 1 540 832 ops/s | 649 ns |
| Go Win64(JSON) | 341バイト | 251 825 ops/s | 3 971 ns |
| Java Win64 | 252バイト | 2 688 084 OPS/s | 372 ns |
| JavaWin64(最終) | 152バイト | 3 036 020 ops/s | 329 ns |
| JavaWin64(JSON) | 353バイト | 308 675 ops/s | 3 240 ns |
| JavaScript win64 | 252バイト | 133 892 ops/s | 7 469 ns |
| JavaScriptWin64(最終) | 152バイト | 292 273 ops/s | 3 422 ns |
| JavaScriptWin64(JSON) | 341バイト | 289 417 ops/s | 3 455 ns |
| Kotlin Win64 | 252バイト | 2 280 923 ops/s | 438 ns |
| Kotlin Win64(最終) | 152バイト | 2 652 728 ops/s | 277 ns |
| Kotlin Win64(JSON) | 353バイト | 250 524 ops/s | 3 992 ns |
| Python Win64 | 252バイト | 8 305 ops/s | 120 411 ns |
| Python Win64(最終) | 152バイト | 11 661 ops/s | 85 758 ns |
| Python Win64(JSON) | 324バイト | 48 859 ops/s | 20 467 ns |
| Ruby Win64 | 252バイト | 24 351 ops/s | 41 066 ns |
| Ruby Win64(最終) | 152バイト | 33 555 ops/s | 29 802 ns |
| Ruby Win64(JSON) | 353バイト | 42 860 ops/s | 23 331 ns |
| 迅速なマコー | 252バイト | 86 288 ops/s | 11 589 ns |
| Swift MacOS(最終) | 152バイト | 10 3519 ops/s | 9 660 ns |
| Swift MacOS(JSON) | 353バイト | 17 077 ops/s | 58 558 ns |
ベンチマークC ++コードを確認します:
BENCHMARK_FIXTURE (VerifyFixture, " Verify " )
{
// Verify the account
model. verify ();
}ベンチマークの結果を確認します:
| 言語とプラットフォーム | メッセージサイズ | レートを確認します | 時間を確認します |
|---|---|---|---|
| C ++ Win64 | 252バイト | 31 250 000 ops/s | 32 ns |
| C ++ Win64(最終) | 152バイト | 35 714 286 ops/s | 28 ns |
| C#Win64 | 252バイト | 4 504 505 ops/s | 222 ns |
| C#Win64(最終) | 152バイト | 8 064 516 ops/s | 124 ns |
| win64に行きます | 252バイト | 8 474 576 ops/s | 118 ns |
| Go Win64(最終) | 152バイト | 9 090 909 ops/s | 110 ns |
| Java Win64 | 252バイト | 11 790 374 ops/s | 85 ns |
| JavaWin64(最終) | 152バイト | 16 205 533 ops/s | 62 ns |
| JavaScript win64 | 252バイト | 1 105 627 ops/s | 905 ns |
| JavaScriptWin64(最終) | 152バイト | 5 700 408 ops/s | 175 ns |
| Kotlin Win64 | 252バイト | 8 625 935 ops/s | 116 ns |
| Kotlin Win64(最終) | 152バイト | 13 373 757 ops/s | 75 ns |
| Python Win64 | 252バイト | 20 825 ops/s | 48 019 ns |
| Python Win64(最終) | 152バイト | 23 590 ops/s | 42 391 ns |
| Ruby Win64 | 252バイト | 57 201 ops/s | 17 482 ns |
| Ruby Win64(最終) | 152バイト | 74 262 ops/s | 13 466 ns |
| 迅速なマコー | 252バイト | 164 446 ops/s | 6 081 ns |
| Swift MacOS(最終) | 152バイト | 228 154 ops/s | 4 383 ns |