From: Wolfgang Bangerth Date: Thu, 25 Jan 2018 00:07:28 +0000 (-0700) Subject: Optimize the pack/unpack() functions for simple data types. X-Git-Tag: v9.0.0-rc1~528^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F5800%2Fhead;p=dealii.git Optimize the pack/unpack() functions for simple data types. --- diff --git a/include/deal.II/base/utilities.h b/include/deal.II/base/utilities.h index 4f08866847..914fa390d3 100644 --- a/include/deal.II/base/utilities.h +++ b/include/deal.II/base/utilities.h @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef DEAL_II_WITH_TRILINOS # include @@ -781,30 +782,53 @@ namespace Utilities template std::vector pack(const T &object) { - // set up a buffer and then use it as the target of a compressing - // stream into which we serialize the current object - std::vector buffer; - { + // see if the object is small and copyable via memcpy. if so, use + // this fast path. otherwise, we have to go through the BOOST + // serialization machinery + // + // we have to work around the fact that GCC 4.8.x claims to be C++ + // conforming, but is not actually as it does not implement + // std::is_trivially_copyable. + if ( +#if __GNUG__ && __GNUC__ < 5 + __has_trivial_copy(T) +#else + std::is_trivially_copyable() +#endif + && + sizeof(T)<256) + { + std::vector buffer (sizeof(T)); + std::memcpy (buffer.data(), &object, sizeof(T)); + return buffer; + } + else + { + // set up a buffer and then use it as the target of a compressing + // stream into which we serialize the current object + std::vector buffer; + { #ifdef DEAL_II_WITH_ZLIB - boost::iostreams::filtering_ostream out; - out.push(boost::iostreams::gzip_compressor - (boost::iostreams::gzip_params - (boost::iostreams::gzip::best_compression))); - out.push(boost::iostreams::back_inserter(buffer)); - - boost::archive::binary_oarchive archive(out); - archive << object; - out.flush(); + boost::iostreams::filtering_ostream out; + out.push(boost::iostreams::gzip_compressor + (boost::iostreams::gzip_params + (boost::iostreams::gzip::best_compression))); + out.push(boost::iostreams::back_inserter(buffer)); + + boost::archive::binary_oarchive archive(out); + archive << object; + out.flush(); #else - std::ostringstream out; - boost::archive::binary_oarchive archive(out); - archive << object; - const std::string &s = out.str(); - buffer.reserve(s.size()); - buffer.assign(s.begin(), s.end()); + std::ostringstream out; + boost::archive::binary_oarchive archive(out); + archive << object; + const std::string &s = out.str(); + buffer.reserve(s.size()); + buffer.assign(s.begin(), s.end()); #endif - } - return buffer; + } + return buffer; + } } @@ -812,27 +836,51 @@ namespace Utilities template T unpack(const std::vector &buffer) { - std::string decompressed_buffer; - T object; + // see if the object is small and copyable via memcpy. if so, use + // this fast path. otherwise, we have to go through the BOOST + // serialization machinery + // + // we have to work around the fact that GCC 4.8.x claims to be C++ + // conforming, but is not actually as it does not implement + // std::is_trivially_copyable. + if ( +#if __GNUG__ && __GNUC__ < 5 + __has_trivial_copy(T) +#else + std::is_trivially_copyable() +#endif + && + sizeof(T)<256) + { + Assert (buffer.size() == sizeof(T), ExcInternalError()); + T object; + std::memcpy (&object, buffer.data(), sizeof(T)); + return object; + } + else + { + std::string decompressed_buffer; + T object; - // first decompress the buffer - { + // first decompress the buffer + { #ifdef DEAL_II_WITH_ZLIB - boost::iostreams::filtering_ostream decompressing_stream; - decompressing_stream.push(boost::iostreams::gzip_decompressor()); - decompressing_stream.push(boost::iostreams::back_inserter(decompressed_buffer)); - decompressing_stream.write (buffer.data(), buffer.size()); + boost::iostreams::filtering_ostream decompressing_stream; + decompressing_stream.push(boost::iostreams::gzip_decompressor()); + decompressing_stream.push(boost::iostreams::back_inserter(decompressed_buffer)); + decompressing_stream.write (buffer.data(), buffer.size()); #else - decompressed_buffer.assign (buffer.begin(), buffer.end()); + decompressed_buffer.assign (buffer.begin(), buffer.end()); #endif - } + } - // then restore the object from the buffer - std::istringstream in(decompressed_buffer); - boost::archive::binary_iarchive archive(in); + // then restore the object from the buffer + std::istringstream in(decompressed_buffer); + boost::archive::binary_iarchive archive(in); - archive >> object; - return object; + archive >> object; + return object; + } } }