Serialization is the loading and saving of objects to files or memory - it seems like such a simple concept, but in practice...not so much.
Serialization is a difficult feature to implement in C++.
The lack of runtime metadata, as well as reflection make
serialization in C++ especially tedious.
This has resulted in an inability for library writers
to tackle serialization in a meaningful way in standard
C++.
opC++ solves this issue by automatically generating
mappings for serialization at compile-time, and by using
the latest template techniques, it is fast and
type safe as well!
One recent C++ library attempt is Boost Serialization,
which heavily uses template techniques to achieve a nearly theoretically
optimal code path - we'll compare the techniques it uses
to opC++ Serialization throughout this overview.
Optimal Serialization
To get optimal serialization - you have to consider a number of factors, including:
Speed - is it fast? does it have decent compile times?
Memory - does it add a lot of memory dynamically? does it cause code bloat?
Flexibility - is adding more features possible? how complicated is it?
opC++ Serialization does a good job fitting these requirements:
Fast - very fast access to data dynamically via opC++ Reflection.
Predictable - uses no dynamic memory allocations, adds a constant amount of code per member.
Extendable - extendable using simple visitor classes, no template coding is necessary.
Serialization Speed
Saving Speed
This graph shows binary serialization save times, per test class. All tests use memory based streams, with Boost and opC++ using the same underlying stream (std::stringstream).
Despite being easier to extend, and using polymorphic visitors, opC++ is able
to outperform the C++ Boost Serialization template libraries.
In terms of pure speed - usually you want to call fewer instructions for the same amount of work. Templates give you this by inlining, removing unnecessary code, and through compile time switching. Using templates you can often get code very close to hand written assembly.
However, on todays processors it's sometimes more important to have more localized code than a theoretically efficient code path. opC++ Serialization uses a more localized hybrid approach instead of a massively templated approach - and because of this is sometimes able to exceed the speeds of massively inlined code.
opC++ Serialization comes with Text, Binary, and Xml saving and loading. These visitors use standard C++ streams in order to be as type safe and readable as possible. These visitors are written to be readable, and are certainly not the fastest possible - yet they still exceed the alternatives!
opC++ Code Size
Code Size
This graph shows resulting code sizes for a test program, per test class. Serialization in C++ is not without costs, but what are those costs?
For Boost, each archiver you use (binary save, load, etc) adds an additional code path. In opC++ however, code size per member is constant no matter how many archivers you add and use.
With opC++ Serialization, you don't have to worry about code size when adding new archivers. Add as many archivers as you need without a code bloat penalty.
You can write interesting archivers/visitors such as:
complex archivers - compressed, diffed, or xml archivers.
simple utility archivers - perform object clones, pre-count bytes, etc.
opC++ Compile Times
Compile Times
This graph shows resulting compile times for a test program in seconds, per (complex) test class.
For massively templated code (Boost) we can see growth per code path.
Keep in mind that for a reasonably large program loading and saving two file formats (4 archivers) is certainly not atypical.
Serialization In Standard opC++
Serialization in Standard opC++ builds upon the Reflection support, and gives you a platform to generate
complex serialization quickly and easily.
Finally you can write serialization in C++ without intrusive code
maintenance. Just use a serialization visitor and forget about
the rest.
Standard opC++ Features Serialization Support:
transient modifier - mark fields as transient, and non-serializable.
native modifier - mark fields as completely non-reflectable, and therefore not serializable.
text, binary and xml serialization visitors.
Serialization
The opC++ Compiler opens up new possibilities for serialization in C++.
Write code once, add modifiers, then experiment with interesting new serialization schemes by swapping out dialect code.
Find the proper balance for your application while avoiding the pain of manual mappings and unstructured code.
You can also combine your own language extensions to add additional
meta-data your serializers can use.
You could, for example:
add an xml_tag() modifier to control the tag output.
add a version() modifier to control variable versioning.
Approaches to Serialization
Since opC++ Serialization is built using the opC++ Dialect Language - you can also
create your own approaches to serialization using opC++ Dialects.
Possible alternative approaches include:
automatically generate binding code for existing serialization libraries (Boost, etc).
use a fully templated approach with your own archiver types.
generate polymorphic per archiver code paths (savebinary, loadbinary, etc).