Subject: [Boost-bugs] [Boost C++ Libraries] #1418: polymorphic archive performance improvement
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2007-11-07 21:01:02
#1418: polymorphic archive performance improvement
------------------------------------------+---------------------------------
Reporter: Kim Barrett <kab_at_[hidden]> | Owner: ramey
Type: Patches | Status: new
Milestone: To Be Determined | Component: serialization
Version: Boost 1.34.1 | Severity: Optimization
Keywords: |
------------------------------------------+---------------------------------
The attached patch (against boost-1.34.1 release) addresses a performance
problem when using boost.serialization polymorphic archives.
To simplify the description, we'll only discuss here the output side
(i.e. serialization), although everything described here has a symmetrical
part on the input (deserialization) side.
When serializing an object, the oserializer class template's
save_object_data
is called with arguments of a basic_oarchive and a void* referring to the
object's data. That function must, among other things, convert the archive
argument to the "most specialized" type of the archive, as specified by
the
oserializer class's Archive template argument. In boost_1.34.1 (and
before),
this conversion is performed using boost::smart_cast_reference, to convert
the
basic_oarchive& to an Archive&.
When using a "normal" (non-polymorphic) archive, the Archive type is the
most
specialized type for the archive object, and that type is (indirectly)
derived
from basic_oarchive. Thus, the conversion can be safely performed using a
downward static_cast. (The smart_cast mechanism uses a checked downward
dynamic_cast when compiled in debug mode rather than release mode.)
When using a polymorphic archive, the Archive type is polymorphic_oarchive
(or
perhaps a more specialized variant of polymorphic_oarchive). The
polymorphic_oarchive class is not in a base/derived relationship with
basic_oarchive, in either direction. Thus, the smart_cast-based conversion
always uses a dynamic_cast, and that dynamic_cast is in fact a cross-cast.
Note that all conversions involving a given archive instance are to the
same Archive type. In the non-polymorphic case, Archive must always be the
most specialized type of the archive. In the polymorphic case, Archive
must
always be polymorphic_oarchive, else there would be little point to using
a
polymorphic archive.
Note that this archive conversion must be performed for each subobject of
each
object that is saved, recursively down through the subobjects, which means
that it gets performed a lot.
For non-polymorphic archives, there is no problem, since a downward
static_cast is cheap.
For polymorphic archives though, there is a serious problem, because
dynamic_cast in general and especially cross-casts may be very expensive
on
some platforms. Our measurements have shown that in boost-1.34.1 the
performance of serialization with polymorphic archives is completely
dominated
by this conversion on some platforms (gcc3.x), and strongly impacted by it
on
others (gcc4.x). Separate measurements seem to indicate that Windows
compilers
may be closer to gcc3.x than gcc4.x in this respect.
This patch introduces a new operation, archive_cast, which is used by the
serializers to perform this conversion. archive_cast uses the preexisting
smart_cast-based conversion when the Archive type is derived from the
source
type. Otherwise, it performs the expensive dynamic cast once and then
caches
the result in the archive for later use. The result is a dramatic speedup
of
polymorphic archive serialization on gcc3.x platforms and a significant
speedup on gcc4.x platforms.
This patch is against the boost-1.34.1 release, and has only been tested
against that release. There might be some adjustments required in order to
apply it to the current trunk, though it looks like it shouldn't require
any
major changes to the patch.
This patch has only been tested by us on gcc3.4 and gcc4.1. Though it
doesn't
do anything that appears all that complex in the way of templates, there
is
still a possibility that it might run afoul of some compiler limitation on
some platform presently supported by the serialization library. It does
use
partial class template specialization over a non-type template parameter.
According to boost/config, some very old compilers don't support partial
specialization of class templates. A reasonable fallback in such a case,
if
some workaround isn't available, is to just use the preexisting
smart_cast-based conversion, i.e. have archive_cast always use
smart_cast_reference and continue to have the performance issue.
Because this patch has only been tested by us on gcc-based platforms,
there is
a pretty good chance that some of the Windows declspec-related stuff is
wrong
in the patch. We've made a good-faith but largely uninformed attempt at
dealing with that, so beware.
--
Ticket URL: <http://svn.boost.org/trac/boost/ticket/1418>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:56 UTC