يسمح الترميز الثنائي السريع بوصف أي نماذج للمجال ، وكائنات الأعمال ، وهياكل البيانات المعقدة ، وطلبات وطلبات العميل/الخادم وإنشاء التعليمات البرمجية الأصلية للغات والبرمجة المختلفة.
وثائق تشفير ثنائية سريعة
تنزيلات الترميز الثنائية السريعة
مواصفات الترميز الثنائي السريع
يمكن العثور على مقارنة الأداء بالبروتوكولات الأخرى هنا:
| بروتوكول | حجم الرسالة | وقت التسلسل | وقت هجر |
|---|---|---|---|
| cap'n'proto | 208 بايت | 558 NS | 359 NS |
| fastbinaryencoding | 234 بايت | 66 NS | 82 ns |
| Flatbuffers | 280 بايت | 830 NS | 290 NS |
| protobuf | 120 بايت | 628 NS | 759 NS |
| جيسون | 301 بايت | 740 NS | 500 نانو ثانية |
سير عمل الاستخدام النموذجي هو ما يلي:
مشاريع العينة:
خياري:
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 تنسيق يحل مشكلة إصدار البروتوكول.
اتبع الخطوات أدناه من أجل تسلسل أي كائن مجال:
اتبع الخطوات أدناه من أجل إلغاء تمييز أي كائن مجال:
فيما يلي exmple من تسلسل FBE في لغة 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 ;
}الإخراج هو ما يلي:
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 | 252 بايت | 88 ns | 98 ns | 33 NS |
| FBE النهائي | 152 بايت | 57 NS | 81 NS | 28 ns |
يمكن تجميع نموذج المجال النهائي مع -العلم النهائي. ونتيجة ستتوفر النماذج النهائية الإضافية للتسلسل.
اتبع الخطوات أدناه من أجل تسلسل أي كائن مجال بالتنسيق النهائي:
اتبع الخطوات أدناه من أجل إلغاء تمييز أي كائن مجال:
فيما يلي exmple من التسلسل النهائي FBE في لغة 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 ;
}الإخراج هو ما يلي:
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.
يرجى ملاحظة أن بعض لغات البرمجة لديها دعم JSON الأصلي (JavaScript ، Python). تتطلب اللغات الأخرى مكتبة الطرف الثالث للحصول على العمل مع JSON:
فيما يلي exmple من تسلسل JSON في لغة 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 ;
}الإخراج هو ما يلي:
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)
]
)
يتم الإعلان عن الحزم باسم الحزمة وإزاحة الهياكل (اختياري). سيتم إضافة الإزاحة إلى نوع الهيكل المتزايد إذا لم يتم توفيره بشكل صريح.
فيما يلي مثال على إعلان الحزمة البسيط:
// 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 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); }
...
};يتم زيادة أرقام نوع الهيكل تلقائيًا حتى توفرها يدويًا. هناك احتمالان:
مثال أدناه يوضح الفكرة:
// 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;
}من الممكن أيضًا إعادة استخدام رقم نوع الهيكل الأساسي في طفل باستخدام مشغل "= قاعدة". إنه مفيد عند تمديد البنية من الحزمة المستوردة من طرف ثالث:
// 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;
}تحتاج إلى تمديده مع قيم التعداد والعلم والبنية الجديدة. فقط أضف القيم المطلوبة إلى نهاية الإعلانات المقابلة:
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 ، فسيتم إنشاء رمز بروتوكول المرسل/المستلم.
تحتوي واجهة المرسل على طرق "Send (struct)" لجميع بنيات نموذج النطاق. كما أنه يحتوي على طريقة مجردة 'OnSend (البيانات ، الحجم) "والتي يجب تنفيذها لإرسال البيانات المسلسل إلى مقبس ، أنبوب ، إلخ.
تحتوي واجهة المتلقي على معالجات "onReceive (struct)" لجميع بنيات نموذج المجال. كما أنه يحتوي على طريقة عامة 'onReceive (النوع ، البيانات ، الحجم) والتي يجب استخدامها لتغذية المتلقي بالبيانات المستلمة من مقبس ، أنبوب ، إلخ.
فيما يلي exmple من استخدام بروتوكول اتصال المرسل/المتلقي بلغة 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)])
تستخدم جميع المعايير نفس نموذج المجال لإنشاء حساب واحد مع ثلاثة أوامر:
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 ++ Code CONCARTY COM:
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 |
| ج# 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 |
| اذهب وين 64 | 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 |
| Java Win64 (نهائي) | 152 بايت | 4 883 205 OPS/S | 205 NS |
| Java Win64 (JSON) | 353 بايت | 213 983 OPS/S. | 4 673 NS |
| JavaScript Win64 | 252 بايت | 93 416 OPS/S. | 10 705 ns |
| JavaScript Win64 (نهائي) | 152 بايت | 112 665 OPS/S. | 8 876 NS |
| JavaScript Win64 (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 |
| بيثون Win64 | 252 بايت | 9 434 OPS/S. | 105 999 ns |
| بيثون Win64 (نهائي) | 152 بايت | 11 635 OPS/S. | 85 945 ns |
| بيثون Win64 (JSON) | 324 بايت | 61 737 OPS/S. | 16 198 ns |
| روبي Win64 | 252 بايت | 23 013 OPS/S. | 43 453 NS |
| روبي Win64 (نهائي) | 152 بايت | 33 361 OPS/S. | 29 975 ns |
| روبي Win64 (JSON) | 353 بايت | 50 842 OPS/S. | 19 669 ns |
| Macos السريع | 252 بايت | 74 002 OPS/S. | 13 513 ns |
| Macos السريع (النهائي) | 152 بايت | 100 755 OPS/S. | 9 925 ns |
| MACOS SWIFT (JSON) | 353 بايت | 18 534 OPS/S. | 53 953 NS |
رمز كود C ++ Code:
BENCHMARK_FIXTURE (DeserializationFixture, " Deserialize " )
{
// Deserialize the account from the FBE stream
reader. deserialize (deserialized);
}نتائج القياس المنهارة:
| اللغة والمنصة | حجم الرسالة | معدل هجر | وقت هجر |
|---|---|---|---|
| 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 |
| ج# 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 |
| اذهب وين 64 | 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 |
| Java Win64 (نهائي) | 152 بايت | 3 036 020 OPS/S | 329 NS |
| Java Win64 (JSON) | 353 بايت | 308 675 OPS/S. | 3 240 ns |
| JavaScript Win64 | 252 بايت | 133 892 OPS/S. | 7 469 ns |
| JavaScript Win64 (نهائي) | 152 بايت | 292 273 OPS/S. | 3 422 ns |
| JavaScript Win64 (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 |
| بيثون Win64 | 252 بايت | 8 305 OPS/S. | 120 411 ns |
| بيثون Win64 (نهائي) | 152 بايت | 11 661 OPS/S. | 85 758 ns |
| بيثون Win64 (JSON) | 324 بايت | 48 859 OPS/S. | 20 467 ns |
| روبي Win64 | 252 بايت | 24 351 OPS/S. | 41 066 ns |
| روبي Win64 (نهائي) | 152 بايت | 33 555 OPS/S. | 29 802 ns |
| روبي Win64 (JSON) | 353 بايت | 42 860 OPS/S. | 23 331 NS |
| Macos السريع | 252 بايت | 86 288 OPS/S. | 11 589 NS |
| Macos السريع (النهائي) | 152 بايت | 10 3519 OPS/S. | 9 660 ns |
| MACOS SWIFT (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 |
| ج# win64 | 252 بايت | 4 504 505 OPS/S | 222 NS |
| C# Win64 (نهائي) | 152 بايت | 8 064 516 OPS/S | 124 NS |
| اذهب وين 64 | 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 |
| Java Win64 (نهائي) | 152 بايت | 16 205 533 OPS/S | 62 ns |
| JavaScript Win64 | 252 بايت | 1 105 627 OPS/S | 905 ns |
| JavaScript Win64 (نهائي) | 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 |
| بيثون Win64 | 252 بايت | 20 825 OPS/S. | 48 019 NS |
| بيثون Win64 (نهائي) | 152 بايت | 23 590 OPS/S. | 42 391 NS |
| روبي Win64 | 252 بايت | 57 201 Ops/s | 17 482 ns |
| روبي Win64 (نهائي) | 152 بايت | 74 262 OPS/S. | 13 466 ns |
| Macos السريع | 252 بايت | 164 446 OPS/S. | 6 081 ns |
| Macos السريع (النهائي) | 152 بايت | 228 154 OPS/S. | 4 383 NS |