快速二进制编码允许描述任何域模型,业务对象,复杂的数据结构,客户端/服务器请求和响应,并为不同的编程语言和平台生成本机代码。
快速二进制编码文档
快速二进制编码下载
快速二进制编码规范
可以在此处找到与其他协议的性能比较:
| 协议 | 消息大小 | 序列化时间 | 避免时间 |
|---|---|---|---|
| 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 |
| 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序列化的Exmple:
# 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 |
最终域模型可以用 - 最终标志编译。结果,其他最终模型将用于序列化。
请按照以下步骤以最终格式序列化任何域对象:
请按照以下步骤进行测试,以便对任何域对象进行估算:
这是C ++语言中FBE最终序列化的Exmple:
# 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格式中。
请注意,某些编程语言具有本机JSON支持(JavaScript,Python)。其他语言需要第三方库才能与JSON合作:
这是C ++语言中JSON序列化的Exmple:
# 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
...软件包导入是使用:
一些结构归档(一个或多个)可以用“ [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); }
...
};结构类型数字会自动增加,直到您手动提供它为止。有两种可能性:
下面的示例演示了这个想法:
// 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;
}您需要使用新的枚举,标志和结构值扩展它。只需在相应声明的末尾添加所需值:
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标志编译,则将生成发件人/接收器协议代码。
发件人界面包含所有域模型结构的“发送(struct)”方法。它还具有抽象的“ OnSend(数据,大小)”方法,应实现将序列化数据发送到插座,管道等。
接收器界面包含所有域模型结构的“ OnReceive(struct)”处理程序。此外,它还具有公共“接种(类型,数据,大小)”方法,该方法应用于将接收器从套接字,管道等接收到的数据。
这是使用C ++语言使用发送者/接收器通信协议的Exmple:
# 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 ++代码:
BENCHMARK_FIXTURE (SerializationFixture, " Serialize " )
{
// Reset FBE stream
writer. reset ();
// Serialize the account to the FBE stream
writer. serialize (account);
}序列化基准结果:
| 语言和平台 | 消息大小 | 序列化率 | 序列化时间 |
|---|---|---|---|
| C ++ Win64 | 252字节 | 10 416667 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 |
| 赢了64 | 252字节 | 2 739 726 OPS/S | 365 ns |
| 去Win64(决赛) | 152字节 | 2 949 852 OPS/S | 339 ns |
| 去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 |
| 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 |
| Swift Macos | 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 |
理想化基准C ++代码:
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 |
| 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 |
| 赢了64 | 252字节 | 1 510 574 OPS/S | 662 ns |
| 去Win64(决赛) | 152字节 | 1 540 832 OPS/S | 649 ns |
| 去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 |
| 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 |
| Swift Macos | 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 |
| 赢了64 | 252字节 | 8 474 576 OPS/S | 118 ns |
| 去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 |
| 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 |
| Swift Macos | 252字节 | 164 446 OPS/s | 6 081 ns |
| Swift Macos(决赛) | 152字节 | 228 154 OPS/s | 4 383 ns |