This is an automated email from the ASF dual-hosted git repository.
pandalee pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 313fc7132 perf(c++): fair benchmark for cpp (#2963)
313fc7132 is described below
commit 313fc713259cf92ce21e86caf2f30a7c62660ba7
Author: Shawn Yang <[email protected]>
AuthorDate: Wed Dec 3 02:23:28 2025 +0800
perf(c++): fair benchmark for cpp (#2963)
## Why?
The previouse benchmark is not fair:
- Protobuf encode negative varint use 5 bytes, but fory may only use one
bytes. And for small varint, fory has zigzag cost. this is not a fair
compare
- When serialize Sample, Fory allocate a vector every time, but protobuf
serialize to a buffer instead.
## What does this PR do?
- Make NumericStruct contains int32 of all kinds size, and positive and
negative
- Make fory serialize to a buffer to for sample
With this fair compare, fory is similair performance as protobuf
## Related issues
#2958
#2960
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fory/issues/new/choose) describing the
need to do so and update the document if necessary.
Delete section if not applicable.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
| Datatype | Operation | Fory (ns) | Protobuf (ns) | Faster |
|----------|-----------|-----------|---------------|--------|
| Sample | Serialize | 345.6 | 316.4 | Protobuf (1.1x) |
| Sample | Deserialize | 1376.4 | 1374.6 | Protobuf (1.0x) |
| Struct | Serialize | 129.4 | 157.0 | Fory (1.2x) |
| Struct | Deserialize | 207.5 | 154.4 | Protobuf (1.3x) |
---------
Co-authored-by: Pan Li <[email protected]>
---
benchmarks/cpp_benchmark/benchmark.cc | 120 +++++++++++++++++++++-------------
1 file changed, 75 insertions(+), 45 deletions(-)
diff --git a/benchmarks/cpp_benchmark/benchmark.cc
b/benchmarks/cpp_benchmark/benchmark.cc
index 10ccb0525..fa3ec009b 100644
--- a/benchmarks/cpp_benchmark/benchmark.cc
+++ b/benchmarks/cpp_benchmark/benchmark.cc
@@ -105,7 +105,17 @@ FORY_STRUCT(Sample, int_value, long_value, float_value,
double_value,
// ============================================================================
NumericStruct CreateNumericStruct() {
- return NumericStruct{1, 2, 3, 4, 5, 6, 7, 8};
+ // Use mixed positive/negative int32 values for realistic benchmark
+ return NumericStruct{
+ -12345, // f1: negative
+ 987654321, // f2: large positive
+ -31415, // f3: negative
+ 27182818, // f4: positive
+ -32000, // f5: negative (near int16 min)
+ 1000000, // f6: medium positive
+ -999999999, // f7: large negative
+ 42 // f8: small positive
+ };
}
// ============================================================================
@@ -146,70 +156,84 @@ protobuf::Struct CreateProtoStruct() {
}
Sample CreateSample() {
+ // Consistent with Java Sample.populate() for fair cross-language comparison
Sample sample;
- sample.int_value = 42;
- sample.long_value = 1234567890123LL;
- sample.float_value = 3.14f;
- sample.double_value = 2.718281828;
- sample.short_value = 100;
- sample.char_value = 65;
+ sample.int_value = 123;
+ sample.long_value = 1230000LL;
+ sample.float_value = 12.345f;
+ sample.double_value = 1.234567;
+ sample.short_value = 12345;
+ sample.char_value = '!'; // 33
sample.boolean_value = true;
- sample.int_value_boxed = 42;
- sample.long_value_boxed = 1234567890123LL;
- sample.float_value_boxed = 3.14f;
- sample.double_value_boxed = 2.718281828;
- sample.short_value_boxed = 100;
- sample.char_value_boxed = 65;
- sample.boolean_value_boxed = true;
- sample.int_array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- sample.long_array = {100, 200, 300, 400, 500};
- sample.float_array = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f};
- sample.double_array = {1.11, 2.22, 3.33, 4.44, 5.55};
- sample.short_array = {10, 20, 30, 40, 50};
- sample.char_array = {65, 66, 67, 68, 69};
- sample.boolean_array = {true, false, true, false, true};
- sample.string = "Hello, Fory benchmark!";
+
+ sample.int_value_boxed = 321;
+ sample.long_value_boxed = 3210000LL;
+ sample.float_value_boxed = 54.321f;
+ sample.double_value_boxed = 7.654321;
+ sample.short_value_boxed = 32100;
+ sample.char_value_boxed = '$'; // 36
+ sample.boolean_value_boxed = false;
+
+ // Arrays with mixed positive/negative values (same as Java)
+ sample.int_array = {-1234, -123, -12, -1, 0, 1, 12, 123, 1234};
+ sample.long_array = {-123400, -12300, -1200, -100, 0,
+ 100, 1200, 12300, 123400};
+ sample.float_array = {-12.34f, -12.3f, -12.0f, -1.0f, 0.0f,
+ 1.0f, 12.0f, 12.3f, 12.34f};
+ sample.double_array = {-1.234, -1.23, -12.0, -1.0, 0.0,
+ 1.0, 12.0, 1.23, 1.234};
+ sample.short_array = {-1234, -123, -12, -1, 0, 1, 12, 123, 1234};
+ sample.char_array = {'a', 's', 'd', 'f', 'A', 'S', 'D', 'F'}; // "asdfASDF"
+ sample.boolean_array = {true, false, false, true};
+
+ sample.string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return sample;
}
protobuf::Sample CreateProtoSample() {
+ // Consistent with Java Sample.populate() for fair cross-language comparison
protobuf::Sample sample;
- sample.set_int_value(42);
- sample.set_long_value(1234567890123LL);
- sample.set_float_value(3.14f);
- sample.set_double_value(2.718281828);
- sample.set_short_value(100);
- sample.set_char_value(65);
+ sample.set_int_value(123);
+ sample.set_long_value(1230000LL);
+ sample.set_float_value(12.345f);
+ sample.set_double_value(1.234567);
+ sample.set_short_value(12345);
+ sample.set_char_value('!'); // 33
sample.set_boolean_value(true);
- sample.set_int_value_boxed(42);
- sample.set_long_value_boxed(1234567890123LL);
- sample.set_float_value_boxed(3.14f);
- sample.set_double_value_boxed(2.718281828);
- sample.set_short_value_boxed(100);
- sample.set_char_value_boxed(65);
- sample.set_boolean_value_boxed(true);
- for (int i = 1; i <= 10; ++i) {
- sample.add_int_array(i);
+
+ sample.set_int_value_boxed(321);
+ sample.set_long_value_boxed(3210000LL);
+ sample.set_float_value_boxed(54.321f);
+ sample.set_double_value_boxed(7.654321);
+ sample.set_short_value_boxed(32100);
+ sample.set_char_value_boxed('$'); // 36
+ sample.set_boolean_value_boxed(false);
+
+ // Arrays with mixed positive/negative values (same as Java)
+ for (int v : {-1234, -123, -12, -1, 0, 1, 12, 123, 1234}) {
+ sample.add_int_array(v);
}
- for (int64_t v : {100LL, 200LL, 300LL, 400LL, 500LL}) {
+ for (int64_t v : {-123400LL, -12300LL, -1200LL, -100LL, 0LL, 100LL, 1200LL,
+ 12300LL, 123400LL}) {
sample.add_long_array(v);
}
- for (float v : {1.1f, 2.2f, 3.3f, 4.4f, 5.5f}) {
+ for (float v :
+ {-12.34f, -12.3f, -12.0f, -1.0f, 0.0f, 1.0f, 12.0f, 12.3f, 12.34f}) {
sample.add_float_array(v);
}
- for (double v : {1.11, 2.22, 3.33, 4.44, 5.55}) {
+ for (double v : {-1.234, -1.23, -12.0, -1.0, 0.0, 1.0, 12.0, 1.23, 1.234}) {
sample.add_double_array(v);
}
- for (int v : {10, 20, 30, 40, 50}) {
+ for (int v : {-1234, -123, -12, -1, 0, 1, 12, 123, 1234}) {
sample.add_short_array(v);
}
- for (int v : {65, 66, 67, 68, 69}) {
+ for (int v : {'a', 's', 'd', 'f', 'A', 'S', 'D', 'F'}) { // "asdfASDF"
sample.add_char_array(v);
}
- for (bool v : {true, false, true, false, true}) {
+ for (bool v : {true, false, false, true}) {
sample.add_boolean_array(v);
}
- sample.set_string("Hello, Fory benchmark!");
+ sample.set_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
return sample;
}
@@ -322,9 +346,15 @@ static void BM_Fory_Sample_Serialize(benchmark::State
&state) {
RegisterForyTypes(fory);
Sample obj = CreateSample();
+ // Pre-allocate buffer (like Protobuf benchmark does)
+ fory::Buffer buffer;
+ buffer.Reserve(4096);
+
for (auto _ : state) {
- auto result = fory.serialize(obj);
+ buffer.WriterIndex(0);
+ auto result = fory.serialize_to(obj, buffer);
benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(buffer.data());
}
}
BENCHMARK(BM_Fory_Sample_Serialize);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]