빠른 바이너리 인코딩을 통해 도메인 모델, 비즈니스 객체, 복잡한 데이터 구조, 클라이언트/서버 요청 및 응답을 설명하고 다양한 프로그래밍 언어 및 플랫폼에 대한 기본 코드를 생성 할 수 있습니다.
빠른 바이너리 인코딩 문서
빠른 바이너리 인코딩 다운로드
빠른 바이너리 인코딩 사양
다른 프로토콜과의 성능 비교는 여기에서 찾을 수 있습니다.
| 규약 | 메시지 크기 | 직렬화 시간 | 사제화 시간 |
|---|---|---|---|
| Cap'n'proto | 208 바이트 | 558 ns | 359 ns |
| FastbinaryOnding | 234 바이트 | 66 ns | 82 ns |
| 플랫 버퍼 | 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 ++ 언어로 된 직렬화의 실행입니다.
# 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 |
최종 도메인 모델은 -Final Flag로 컴파일 할 수 있습니다. 결과적으로 추가 최종 모델을 직렬화에 사용할 수 있습니다.
최종 형식으로 도메인 오브젝트를 직렬화하려면 아래 단계를 따르십시오.
도메인 객체를 사로화하려면 아래 단계를 따라하십시오.
다음은 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 형식으로/로부터 직렬화/사제 화 될 수 있습니다.
일부 프로그래밍 언어에는 기본 JSON 지원 (JavaScript, Python)이 있습니다. 다른 언어에는 제 3 자 도서관이 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)
]
)
패키지는 패키지 이름 및 스트러크 오프셋 (선택 사항)으로 선언됩니다. 명시 적으로 제공되지 않은 경우 오프셋은 증분 구조 유형에 추가됩니다.
다음은 간단한 패키지 선언의 예입니다.
// 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
{
...
}한 패키지를 다른 패키지로 가져올 수 있으며 모든 열거, 플래그 및 스트러크를 현재 패키지에서 재사용 할 수 있습니다. 패키지 오프셋은 여기에서 Structs 유형 교차를 피하기 위해 사용됩니다.
// 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 Interface에는 모든 도메인 모델 Structs에 대한 'send (struct)'메소드가 포함되어 있습니다. 또한 초록 'OnSend (Data, Size)'방법이있어 직렬화 된 데이터를 소켓, 파이프 등으로 보내도록 구현해야합니다.
수신기 인터페이스에는 모든 도메인 모델 스트루트에 대한 'Onreceive (struct)'핸들러가 포함되어 있습니다. 또한 소켓, 파이프 등으로부터 수신 된 데이터를 수신자에게 공급하는 데 사용해야하는 공개 'OnReceive (유형, 데이터, 크기) 방법이 있습니다.
다음은 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 ++ 코드 :
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 |
| Java Win64 (Final) | 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 (Final) | 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 (Final) | 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 |
| 루비 윈 64 | 252 바이트 | 23 013 OPS/s | 43 453 ns |
| 루비 윈 64 (결승) | 152 바이트 | 33 361 OPS/s | 29 975 ns |
| 루비 윈 64 (JSON) | 353 바이트 | 50 842 OPS/s | 19 669 ns |
| 스위프트 마코스 | 252 바이트 | 74 002 ops/s | 13 513 ns |
| 스위프트 마코 (최종) | 152 바이트 | 100 755 ops/s | 9 925 ns |
| 스위프트 마코 (JSON) | 353 바이트 | 18 534 OPS/s | 53 953 ns |
Desserialization 벤치 마크 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 |
| 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 |
| Java Win64 (Final) | 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 (Final) | 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 (Final) | 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 |
| 루비 윈 64 | 252 바이트 | 24 351 OPS/s | 41 066 ns |
| 루비 윈 64 (결승) | 152 바이트 | 33 555 OPS/s | 29 802 ns |
| 루비 윈 64 (JSON) | 353 바이트 | 42 860 OPS/s | 23 331 ns |
| 스위프트 마코스 | 252 바이트 | 86 288 OPS/s | 11 589 ns |
| 스위프트 마코 (최종) | 152 바이트 | 10 3519 ops/s | 9 660 ns |
| 스위프트 마코 (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 |
| Java Win64 (Final) | 152 바이트 | 16 205 533 Ops/s | 62 ns |
| JavaScript Win64 | 252 바이트 | 1 105 627 ops/s | 905 ns |
| JavaScript Win64 (Final) | 152 바이트 | 5 700 408 OPS/s | 175 ns |
| Kotlin Win64 | 252 바이트 | 8 625 935 OPS/s | 116 ns |
| Kotlin Win64 (Final) | 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 |
| 루비 윈 64 | 252 바이트 | 57 201 ops/s | 17 482 ns |
| 루비 윈 64 (결승) | 152 바이트 | 74 262 OPS/s | 13 466 ns |
| 스위프트 마코스 | 252 바이트 | 164 446 OPS/s | 6 081 ns |
| 스위프트 마코 (최종) | 152 바이트 | 228 154 OPS/s | 4 383 ns |