This is an automated email from the ASF dual-hosted git repository.
chaokunyang 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 802b860b1 docs(c++): update readme and benchmarks docs (#3305)
802b860b1 is described below
commit 802b860b101196e812d8d52f6c114893f520caf8
Author: Shawn Yang <[email protected]>
AuthorDate: Fri Feb 6 21:13:49 2026 +0800
docs(c++): update readme and benchmarks docs (#3305)
## Why?
- Refresh top-level documentation and benchmark docs to reflect current
project positioning and outputs.
- Publish an updated C++ benchmark report and plots in docs.
- Ensure generated benchmark markdown is MDX-compatible so the fory-site
validation build passes.
## What does this PR do?
- Updates `README.md` feature/protocol wording and benchmark
presentation (including chart sizing).
- Updates `benchmarks/cpp_benchmark/benchmark_report.py` to:
- split throughput visualization into separate non-list and list
subplots for clearer comparison,
- emit self-closing `<img />` tags in generated markdown for MDX
compatibility.
- Adds generated C++ benchmark report and related images under
`docs/benchmarks/cpp/`.
- Simplifies `docs/benchmarks/go/README.md` to focus on the combined
benchmark chart plus summary tables.
- Updates `java/README.md` Java support badge from `8 to 24` to `8 to
25`.
## Related issues
- None.
## Does this PR introduce any user-facing change?
- Yes. Documentation and benchmark report content are updated.
- No runtime/API/protocol behavior change.
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
- C++ benchmark report and charts were regenerated and checked in under
`docs/benchmarks/cpp/REPORT.md` and accompanying images.
---
README.md | 51 +++++-------
benchmarks/cpp_benchmark/benchmark_report.py | 47 +++++++----
docs/benchmarks/cpp/REPORT.md | 116 +++++++++++++++++++++++++++
docs/benchmarks/cpp/mediacontent.png | Bin 0 -> 51863 bytes
docs/benchmarks/cpp/mediacontentlist.png | Bin 0 -> 54504 bytes
docs/benchmarks/cpp/sample.png | Bin 0 -> 48714 bytes
docs/benchmarks/cpp/samplelist.png | Bin 0 -> 51686 bytes
docs/benchmarks/cpp/struct.png | Bin 0 -> 47309 bytes
docs/benchmarks/cpp/structlist.png | Bin 0 -> 48428 bytes
docs/benchmarks/cpp/throughput.png | Bin 44522 -> 73763 bytes
docs/benchmarks/go/README.md | 34 +-------
java/README.md | 2 +-
12 files changed, 174 insertions(+), 76 deletions(-)
diff --git a/README.md b/README.md
index aa6d29157..806cdf0e0 100644
--- a/README.md
+++ b/README.md
@@ -18,26 +18,24 @@
## Key Features
-### 🚀 High-Performance Serialization
+### High-Performance Serialization
Apache Fory™ delivers excellent performance through advanced optimization
techniques:
- **JIT Compilation**: Runtime code generation for Java eliminates virtual
method calls and inlines hot paths
- **Static Code Generation**: Compile-time code generation for Rust, C++, and
Go delivers peak performance without runtime overhead
-- **Zero-Copy Operations**: Direct memory access without intermediate buffer
copies; row format enables random access and partial serialization
-- **Meta Packing & Sharing**: Class metadata packing and sharing reduces
redundant type information across serializations
+- **Meta Packing & Sharing**: Class metadata packing and sharing reduces
redundant type information across objects on one stream
-### 🌍 Cross-Language Serialization
+### Cross-Language Serialization
The **[xlang serialization
format](docs/specification/xlang_serialization_spec.md)** enables seamless data
exchange across programming languages:
-- **Automatic Type Mapping**: Automatic conversion between language-specific
types ([type mapping](docs/specification/xlang_type_mapping.md))
- **Reference Preservation**: Shared and circular references work correctly
across languages
- **Polymorphism**: Objects serialize/deserialize with their actual runtime
types
- **Schema Evolution**: Optional forward/backward compatibility for evolving
schemas
-- **Automatic Serialization**: No IDL or schema definitions required;
serialize any object directly without code generation
+- **Automatic Serialization**: Serialize domain objects automatically, no IDL
or schema definitions required
-### 📊 Row Format
+### Row Format
A cache-friendly **[row format](docs/specification/row_format_spec.md)**
optimized for analytics workloads:
@@ -46,27 +44,26 @@ A cache-friendly **[row
format](docs/specification/row_format_spec.md)** optimiz
- **Apache Arrow Integration**: Seamless conversion to columnar format for
analytics pipelines
- **Multi-Language**: Available in Java, Python, Rust and C++
-### đź”’ Security & Production-Readiness
+### Security & Production-Readiness
-Enterprise-grade security and compatibility:
+Built for production environments with secure defaults and explicit control:
-- **Class Registration**: Whitelist-based deserialization control (enabled by
default)
-- **Depth Limiting**: Protection against recursive object graph attacks
-- **Configurable Policies**: Custom class checkers and deserialization policies
-- **Platform Support**: Java 8-24, GraalVM native image, multiple OS platforms
+- **Class Registration**: Whitelist-based deserialization control is enabled
by default to block untrusted classes.
+- **Depth Limiting**: Configurable object graph depth limits mitigate
recursive and stack exhaustion attacks.
+- **Configurable Policies**: Custom class checkers and deserialization
policies let teams enforce internal security rules.
+- **Platform Support**: Runs on Java 8 through 25, supports GraalVM native
image, and works across major operating systems.
## Protocols
-Apache Fory™ implements multiple binary protocols optimized for different
scenarios:
+Apache Fory™ provides three protocol families optimized for different
scenarios:
-| Protocol |
Use Case | Key Features
|
-| ------------------------------------------------------------------------- |
------------------------------ |
------------------------------------------------------ |
-| **[Xlang Serialization](docs/specification/xlang_serialization_spec.md)** |
Cross-language object exchange | Automatic serialization, references,
polymorphism |
-| **[Java Serialization](docs/specification/java_serialization_spec.md)** |
High-performance Java-only | Drop-in JDK serialization replacement, 100x
faster |
-| **[Row Format](docs/specification/row_format_spec.md)** |
Analytics and data processing | Zero-copy random access, Arrow compatibility
|
-| **Python Native** |
Python-specific serialization | Pickle/cloudpickle replacement with better
performance |
+| Protocol Family |
Use Case | Key Features
|
+| ------------------------------------------------------------------------- |
------------------------------ |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
+| **[Xlang Serialization](docs/specification/xlang_serialization_spec.md)** |
Cross-language object exchange | Automatic serialization, reference
preservation, polymorphism
|
+| **[Row Format](docs/specification/row_format_spec.md)** |
Analytics and data processing | Zero-copy random access, partial operations,
Apache Arrow compatibility
|
+| **Native Serialization** |
Language-specific optimization | Native protocol implementations per language,
including **[Java
Serialization](docs/specification/java_serialization_spec.md)** and Python
Native. Python Native extends Xlang with more type support and better
performance. |
-All protocols share the same optimized codebase, allowing improvements in one
protocol to benefit others.
+All protocol families share the same optimized codebase, allowing improvements
in one family to benefit others.
## Benchmarks
@@ -77,12 +74,6 @@ All protocols share the same optimized codebase, allowing
improvements in one pr
The following benchmarks compare Fory against popular Java serialization
frameworks. Charts labeled **"compatible"** show schema evolution mode with
forward/backward compatibility enabled, while others show schema consistent
mode where class schemas must match.
-**Test Classes**:
-
-- `Struct`: Class with [100 primitive fields](docs/benchmarks/java#Struct)
-- `MediaContent`: Class from
[jvm-serializers](https://github.com/eishay/jvm-serializers/blob/master/tpc/src/data/media/MediaContent.java)
-- `Sample`: Class from [Kryo
benchmark](https://github.com/EsotericSoftware/kryo/blob/master/benchmarks/src/main/java/com/esotericsoftware/kryo/benchmarks/data/Sample.java)
-
**Serialization Throughput**:
<p align="center">
@@ -104,11 +95,11 @@ For additional benchmarks covering type forward/backward
compatibility, off-heap
Fory Rust demonstrates competitive performance compared to other Rust
serialization frameworks.
<p align="center">
-<img src="docs/benchmarks/rust/ecommerce_data.png" width="70%">
+<img src="docs/benchmarks/rust/ecommerce_data.png" width="90%">
</p>
<p align="center">
-<img src="docs/benchmarks/rust/system_data.png" width="70%">
+<img src="docs/benchmarks/rust/system_data.png" width="90%">
</p>
For more detailed benchmarks and methodology, see [Rust
Benchmarks](benchmarks/rust_benchmark).
@@ -118,7 +109,7 @@ For more detailed benchmarks and methodology, see [Rust
Benchmarks](benchmarks/r
Fory C++ demonstrates competitive performance compared to protobuf c++
serialization framework.
<p align="center">
-<img src="docs/benchmarks/cpp/throughput.png" width="70%">
+<img src="docs/benchmarks/cpp/throughput.png" width="95%">
</p>
For more detailed benchmarks and methodology, see [C++
Benchmarks](benchmarks/cpp_benchmark).
diff --git a/benchmarks/cpp_benchmark/benchmark_report.py
b/benchmarks/cpp_benchmark/benchmark_report.py
index e9dbd832f..5e49c1106 100644
--- a/benchmarks/cpp_benchmark/benchmark_report.py
+++ b/benchmarks/cpp_benchmark/benchmark_report.py
@@ -234,35 +234,52 @@ for datatype in datatypes:
plt.close()
# === Create combined TPS comparison plot ===
-fig, axes = plt.subplots(1, 2, figsize=(14, 6))
+non_list_datatypes = [dt for dt in datatypes if not dt.endswith("list")]
+list_datatypes = [dt for dt in datatypes if dt.endswith("list")]
-for idx, op in enumerate(operations):
- ax = axes[idx]
- x = np.arange(len(datatypes))
+
+def plot_combined_tps_subplot(ax, grouped_datatypes, operation, title):
+ if not grouped_datatypes:
+ ax.set_title(f"{title}\nNo Data")
+ ax.axis("off")
+ return
+
+ x = np.arange(len(grouped_datatypes))
width = 0.35
- fory_times = [data[dt][op].get("fory", 0) for dt in datatypes]
- proto_times = [data[dt][op].get("protobuf", 0) for dt in datatypes]
+ fory_times = [data[dt][operation].get("fory", 0) for dt in
grouped_datatypes]
+ proto_times = [data[dt][operation].get("protobuf", 0) for dt in
grouped_datatypes]
# Convert to TPS (operations per second)
fory_tps = [1e9 / t if t > 0 else 0 for t in fory_times]
proto_tps = [1e9 / t if t > 0 else 0 for t in proto_times]
- bars1 = ax.bar(x - width / 2, fory_tps, width, label="Fory",
color=FORY_COLOR)
- bars2 = ax.bar(
- x + width / 2, proto_tps, width, label="Protobuf", color=PROTOBUF_COLOR
- )
+ ax.bar(x - width / 2, fory_tps, width, label="Fory", color=FORY_COLOR)
+ ax.bar(x + width / 2, proto_tps, width, label="Protobuf",
color=PROTOBUF_COLOR)
- ax.set_ylabel("Throughput (ops/sec)")
- ax.set_title(f"{op.capitalize()} Throughput (higher is better)")
+ ax.set_title(title)
ax.set_xticks(x)
- ax.set_xticklabels([format_datatype_label(dt) for dt in datatypes])
+ ax.set_xticklabels([format_datatype_label(dt) for dt in grouped_datatypes])
ax.legend()
ax.grid(True, axis="y", linestyle="--", alpha=0.5)
- # Format y-axis with K/M suffixes
+ # Use a dedicated y-scale per subplot so list benchmarks are not
compressed.
ax.ticklabel_format(style="scientific", axis="y", scilimits=(0, 0))
+
+fig, axes = plt.subplots(1, 4, figsize=(24, 6))
+fig.supylabel("Throughput (ops/sec)")
+
+combined_subplots = [
+ (axes[0], non_list_datatypes, "serialize", "Serialize Throughput"),
+ (axes[1], non_list_datatypes, "deserialize", "Deserialize Throughput"),
+ (axes[2], list_datatypes, "serialize", "Serialize Throughput (*List)"),
+ (axes[3], list_datatypes, "deserialize", "Deserialize Throughput (*List)"),
+]
+
+for ax, grouped_datatypes, op, title in combined_subplots:
+ plot_combined_tps_subplot(ax, grouped_datatypes, op, f"{title} (higher is
better)")
+
fig.tight_layout()
combined_plot_path = os.path.join(output_dir, "throughput.png")
plt.savefig(combined_plot_path, dpi=150)
@@ -294,7 +311,7 @@ for datatype, img in plot_images:
img_path_report = args.plot_prefix + img_filename
md_report.append(f"\n### {datatype.replace('_', ' ').title()}\n\n")
md_report.append(
- f'<p align="center">\n<img src="{img_path_report}"
width="90%">\n</p>\n'
+ f'<p align="center">\n<img src="{img_path_report}" width="90%"
/>\n</p>\n'
)
# Results table
diff --git a/docs/benchmarks/cpp/REPORT.md b/docs/benchmarks/cpp/REPORT.md
new file mode 100644
index 000000000..cf66f3981
--- /dev/null
+++ b/docs/benchmarks/cpp/REPORT.md
@@ -0,0 +1,116 @@
+# C++ Benchmark Performance Report
+
+_Generated on 2026-02-06 20:01:02_
+
+## How to Generate This Report
+
+```bash
+cd benchmarks/cpp_benchmark/build
+./fory_benchmark --benchmark_format=json --benchmark_out=benchmark_results.json
+cd ..
+python benchmark_report.py --json-file build/benchmark_results.json
--output-dir report
+```
+
+## Hardware & OS Info
+
+| Key | Value |
+| -------------------------- | ------------------------- |
+| OS | Darwin 24.6.0 |
+| Machine | arm64 |
+| Processor | arm |
+| CPU Cores (Physical) | 12 |
+| CPU Cores (Logical) | 12 |
+| Total RAM (GB) | 48.0 |
+| Benchmark Date | 2026-02-06T20:00:20+08:00 |
+| CPU Cores (from benchmark) | 12 |
+
+## Benchmark Plots
+
+### Mediacontent
+
+<p align="center">
+<img src="mediacontent.png" width="90%" />
+</p>
+
+### Mediacontentlist
+
+<p align="center">
+<img src="mediacontentlist.png" width="90%" />
+</p>
+
+### Sample
+
+<p align="center">
+<img src="sample.png" width="90%" />
+</p>
+
+### Samplelist
+
+<p align="center">
+<img src="samplelist.png" width="90%" />
+</p>
+
+### Struct
+
+<p align="center">
+<img src="struct.png" width="90%" />
+</p>
+
+### Structlist
+
+<p align="center">
+<img src="structlist.png" width="90%" />
+</p>
+
+### Throughput
+
+<p align="center">
+<img src="throughput.png" width="90%" />
+</p>
+
+## Benchmark Results
+
+### Timing Results (nanoseconds)
+
+| Datatype | Operation | Fory (ns) | Protobuf (ns) | Faster |
+| ---------------- | ----------- | --------- | ------------- | ------------ |
+| Mediacontent | Serialize | 512.0 | 1990.9 | Fory (3.9x) |
+| Mediacontent | Deserialize | 1674.1 | 2516.6 | Fory (1.5x) |
+| Mediacontentlist | Serialize | 2261.0 | 10804.2 | Fory (4.8x) |
+| Mediacontentlist | Deserialize | 6943.5 | 13375.9 | Fory (1.9x) |
+| Sample | Serialize | 241.7 | 309.4 | Fory (1.3x) |
+| Sample | Deserialize | 1055.8 | 1361.5 | Fory (1.3x) |
+| Samplelist | Serialize | 963.2 | 11716.7 | Fory (12.2x) |
+| Samplelist | Deserialize | 5295.9 | 12162.2 | Fory (2.3x) |
+| Struct | Serialize | 117.1 | 169.6 | Fory (1.4x) |
+| Struct | Deserialize | 138.6 | 156.2 | Fory (1.1x) |
+| Structlist | Serialize | 308.4 | 1299.4 | Fory (4.2x) |
+| Structlist | Deserialize | 706.2 | 1188.0 | Fory (1.7x) |
+
+### Throughput Results (ops/sec)
+
+| Datatype | Operation | Fory TPS | Protobuf TPS | Faster |
+| ---------------- | ----------- | --------- | ------------ | ------------ |
+| Mediacontent | Serialize | 1,952,940 | 502,295 | Fory (3.9x) |
+| Mediacontent | Deserialize | 597,343 | 397,356 | Fory (1.5x) |
+| Mediacontentlist | Serialize | 442,277 | 92,557 | Fory (4.8x) |
+| Mediacontentlist | Deserialize | 144,020 | 74,761 | Fory (1.9x) |
+| Sample | Serialize | 4,138,037 | 3,232,073 | Fory (1.3x) |
+| Sample | Deserialize | 947,188 | 734,472 | Fory (1.3x) |
+| Samplelist | Serialize | 1,038,236 | 85,348 | Fory (12.2x) |
+| Samplelist | Deserialize | 188,825 | 82,222 | Fory (2.3x) |
+| Struct | Serialize | 8,542,313 | 5,896,325 | Fory (1.4x) |
+| Struct | Deserialize | 7,217,541 | 6,403,969 | Fory (1.1x) |
+| Structlist | Serialize | 3,242,105 | 769,562 | Fory (4.2x) |
+| Structlist | Deserialize | 1,416,005 | 841,739 | Fory (1.7x) |
+
+### Serialized Data Sizes (bytes)
+
+| Datatype | Fory | Protobuf |
+| ---------------- | ---- | -------- |
+| Struct | 58 | 61 |
+| Sample | 446 | 375 |
+| MediaContent | 365 | 301 |
+| StructList | 184 | 315 |
+| SampleList | 1980 | 1890 |
+| MediaContentList | 1535 | 1520 |
diff --git a/docs/benchmarks/cpp/mediacontent.png
b/docs/benchmarks/cpp/mediacontent.png
new file mode 100644
index 000000000..3c42b14f3
Binary files /dev/null and b/docs/benchmarks/cpp/mediacontent.png differ
diff --git a/docs/benchmarks/cpp/mediacontentlist.png
b/docs/benchmarks/cpp/mediacontentlist.png
new file mode 100644
index 000000000..604663b68
Binary files /dev/null and b/docs/benchmarks/cpp/mediacontentlist.png differ
diff --git a/docs/benchmarks/cpp/sample.png b/docs/benchmarks/cpp/sample.png
new file mode 100644
index 000000000..2932de24b
Binary files /dev/null and b/docs/benchmarks/cpp/sample.png differ
diff --git a/docs/benchmarks/cpp/samplelist.png
b/docs/benchmarks/cpp/samplelist.png
new file mode 100644
index 000000000..6d903f53c
Binary files /dev/null and b/docs/benchmarks/cpp/samplelist.png differ
diff --git a/docs/benchmarks/cpp/struct.png b/docs/benchmarks/cpp/struct.png
new file mode 100644
index 000000000..94209b375
Binary files /dev/null and b/docs/benchmarks/cpp/struct.png differ
diff --git a/docs/benchmarks/cpp/structlist.png
b/docs/benchmarks/cpp/structlist.png
new file mode 100644
index 000000000..fe2dca4ca
Binary files /dev/null and b/docs/benchmarks/cpp/structlist.png differ
diff --git a/docs/benchmarks/cpp/throughput.png
b/docs/benchmarks/cpp/throughput.png
index e726ebbc1..1aa86b16b 100644
Binary files a/docs/benchmarks/cpp/throughput.png and
b/docs/benchmarks/cpp/throughput.png differ
diff --git a/docs/benchmarks/go/README.md b/docs/benchmarks/go/README.md
index 582b053c8..7195fe88d 100644
--- a/docs/benchmarks/go/README.md
+++ b/docs/benchmarks/go/README.md
@@ -8,6 +8,10 @@ Generated: 2026-02-06 11:26:58
- **Architecture**: arm64
- **Python**: 3.10.8
+## Performance Charts
+
+
+
## Performance Summary
| Data Type | Operation | Fory (ops/s) | Protobuf (ops/s) | Msgpack
(ops/s) | Fory vs PB | Fory vs MP |
@@ -52,33 +56,3 @@ Generated: 2026-02-06 11:26:58
| StructList | 560 | 1260 | 1146 |
| SampleList | 7600 | 7560 | 10486 |
| MediaContentList | 5776 | 6080 | 8006 |
-
-## Performance Charts
-
-### Combined Overview
-
-
-
-### Struct
-
-
-
-### Structlist
-
-
-
-### Sample
-
-
-
-### Samplelist
-
-
-
-### Mediacontent
-
-
-
-### Mediacontentlist
-
-
diff --git a/java/README.md b/java/README.md
index bbae5a857..8c162d6c8 100644
--- a/java/README.md
+++ b/java/README.md
@@ -1,7 +1,7 @@
# Apache Fory™ Java
[](https://search.maven.org/#search|gav|1|g:"org.apache.fory"%20AND%20a:"fory-core")
-[](https://www.oracle.com/java/)
+[](https://www.oracle.com/java/)
[](https://opensource.org/licenses/Apache-2.0)
Apache Fory™ Java provides blazingly-fast serialization for the Java
ecosystem, delivering up to **170x performance improvement** over traditional
frameworks through JIT compilation and zero-copy techniques.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]