SerDeLite is a lightweight, high-performance C++ serialization library designed for deterministic environments. It provides a unified framework for converting C++ objects into compact Binary formats and human-readable JSON with zero external dependencies.
SerDeLite is engineered for developers who require absolute control over memory and performance.
-
๐ Zero Dynamic Allocation: Designed for high-performance and embedded systems. SerDeLite operates entirely on pre-allocated buffers, meaning no new or malloc calls during serialization.
-
๐ Dual-Protocol Support: Seamlessly switch between compact Binary (for performance) and human-readable JSON (for debugging/config) using the same class structure.
-
๐ฆ Header-Only Friendly: Minimal dependencies and a lightweight footprint, making it easy to integrate into existing C++11 (or newer) projects.
-
๐ ๏ธ Simple Interface: Turn any class into a serializable object by simply inheriting from JsonSerializable or ByteSerializable and implementing one or two methods.
-
๐ Automatic Memory Management: The ByteBuffer and JsonBuffer systems prevent buffer overflows and ensure memory safety during stream operations.
-
๐จ Pretty Printing: Built-in support for "Pretty JSON" formatting, making it easy to generate logs and configuration files that humans can actually read.
SerDeLite is engineered for high-frequency systems where low latency is critical. These benchmarks demonstrate the library's efficiency on modern high-performance hardware.
- CPU: Intelยฎ Coreโข i7-11800H @ 2.30GHz (Up to 4.6GHz Turbo)
- GPU: NVIDIA GeForce RTX 3050 (4GB)
- Compiler: g++ 13.x (Optimization level:
-O3) - Methodology: 1,000,000 iterations per object type with a 100k iteration CPU warm-up.
| Workload | Complexity | Throughput | Latency |
|---|---|---|---|
Numeric Data (PlayerStats) |
3 Mixed Integers | 17.63M objects/sec | 56.7 ns/object |
Physics Data (Vec3) |
3 Floats | 14.61M objects/sec | 68.4 ns/object |
Nested Object (Player) |
Recursive + Strings | 4.05M objects/sec | 246.5 ns/object |
Stress Test (ComplexPlayer) |
Nested Profile (Player) + 10 Items |
1.43 M objects/sec | 699.3 ns/object |
- O(1) Memory Reset:
ByteBuffer::clear()only resets the internal cursor, keeping the memory "warm" in the CPU L1/L2 cache. - Zero-Allocation Hot Path: No
newormalloccalls occur during the serialization loop, eliminating heap fragmentation and non-deterministic latency. - Exception-Free: Error propagation uses boolean status chains, avoiding the heavy stack-unwinding overhead of C++ exceptions.
- Cache Locality: By using a contiguous
uint8_tbuffer, data stays in the L1/L2 cache, preventing "Cache Misses" that can slow down performance by 100x. - Non-Blocking Logic: The library is entirely synchronous and thread-safe for local buffers, ensuring that serialization never blocks the main execution thread.
- Instruction Inlining: Due to the header-only friendly architecture, the compiler can inline
writeObjectcalls, removing function-call overhead.
Note
Source code for these benchmarks is available in the tests/benchmarks directory, including the 'World State' stress test which simulates high-density entity serialization.
The latest stable binaries and header bundles are available for manual integration.
- Download Latest Release
- Includes:
libserdelite.a(UCRT64/x64) and fullinclude/directory.
- Includes:
SerDeLite provides native support for a wide range of primitive types, ensuring consistent serialization across different architectures.
| Category | Types Supported | Stream Methods |
|---|---|---|
| Integers | uint8, int8, uint16, int16, uint32, int32, uint64, int64 |
writeUintXX, readUintXX |
| Floating Point | float (32-bit), double (64-bit) |
writeFloat, writeDouble |
| Booleans | bool (serialized as 1-byte) |
writeBool, readBool |
| Strings | UTF-8 / ASCII null-terminated | writeString, readString |
| Custom Objects | Classes implementing ByteSerializable or JsonSerializable |
writeObject |
The library is divided into four distinct layers to ensure separation of concerns:
- Physical Layer (
ByteBuffer): Direct management of the raw memory storage. - Logic Layer (
ByteStream/JsonStream): Implementation of serialization protocols. - Interface Layer (
Serializable): The contract used by custom classes to enable streaming. - Presentation Layer (
JsonBuffer): Tools for visualizing data in human-readable formats.
Pre-compiled binaries for Windows x64 are available for immediate use.
- Download the
libserdelite.afrom the Latest Release. - Add the
includefolder to your project's include path. - Link the library using the following compiler flags:
-L./bin -lserdelite
To compile a project using the pre-compiled SerDeLite library, use the following g++ command structure:
g++ main.cpp -o my_app.exe -I./include -L./bin -lserdeliteBreakdown of Flags:
- main.cpp: Your application source code.
- -I./include: Tells the compiler where to find the serdelite.h header file.
- -L./bin: Tells the linker where the libserdelite.a file is stored.
- -lserdelite: Links the actual library (Note: the lib prefix and .a extension are omitted here).
If a custom build is required, the library can be compiled directly from the source code using the following commands:
g++ -c -I./include src/serdelite/*.cppar rcs bin/libserdelite.a *.oInherit from ByteSerializable and JsonSerializable to enable dual-format support.
#include <serdelite.h>
using namespace serdelite;
class Player : public ByteSerializable,
public JsonSerializable {
public:
uint32_t id;
float health;
Player(uint32_t _id=0, float _health=0)
: id(_id), health(_health) {}
// Binary logic
bool toByteStream(ByteStream& s) const override {
return s.writeUint32(id) &&
s.writeFloat(health);
}
bool fromByteStream(ByteStream& s) override {
return s.readUint32(id) &&
s.readFloat(health);
}
size_t byteSize() const override {
return sizeof(id) + sizeof(health);
}
protected:
// JSON logic
bool serializeToJson(JsonStream& s) const override {
return s.writeUint32("id", id) &&
s.writeFloat("health", health);
}
};uint8_t mem[128];
ByteBuffer buffer(mem, sizeof(mem));
ByteStream stream(buffer);
// Write SerDeLite header
stream.writeLibraryHeader();
Player p(101, 95.5f);
bool success = stream.writeObject(p);
if (!success) printf("Failed to serialize Player!\n");// Reset the read cursor first
stream.resetReadCursor();
if (stream.verifyLibraryHeader()) {
buffer.dump();
Player p2;
// Read the previously written player object(p) and store it into p2
bool success = stream.readObject(p2);
if (!success) printf("Failed to write player p into player p2");
else {
printf("ID: %u\n", p2.id);
printf("Health: %.1f\n", p2.health);
}
}// using the same buffer to write json
buffer.erase(); // delete all data from buffer
JsonStream jStream(buffer);
success = p.toJson(jStream);
if (!success) printf("Failed to serialize player to Json!");
else jStream.getJson().printPretty();
