BinaryData optimization for Bitset

Integrates the changes proposed by #236

Bitset will now use a chunking method when serializing to BinaryData
capable archives, which should be faster, especially for larger bitsets.

Archives that do not support BinaryData will continue to use the old method.

Also added a larger bitset to the test case
This commit is contained in:
Shane Grant
2016-02-05 10:14:44 -08:00
parent 6c1b3f7602
commit e9d33b0a1f
2 changed files with 70 additions and 3 deletions
+64 -3
View File
@@ -43,12 +43,49 @@ namespace cereal
{
ulong,
ullong,
string
string,
bits
};
}
//! Serializing (save) for std::bitset
template <class Archive, size_t N> inline
//! Serializing (save) for std::bitset when BinaryData optimization supported
template <class Archive, size_t N,
traits::EnableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
= traits::sfinae> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
{
ar( CEREAL_NVP_("type", bitset_detail::type::bits) );
// Serialize 8 bit chunks
std::uint8_t chunk = 0;
std::uint8_t mask = 0x80;
// Set each chunk using a rotating mask for the current bit
for( std::size_t i = 0; i < N; ++i )
{
if( bits[i] )
chunk |= mask;
mask >>= 1;
// output current chunk when mask is empty (8 bits)
if( mask == 0 )
{
ar( chunk );
chunk = 0;
mask = 0x80;
}
}
// serialize remainder, if it exists
if( mask != 0x80 )
ar( chunk );
}
//! Serializing (save) for std::bitset when BinaryData is not supported
template <class Archive, size_t N,
traits::DisableIf<traits::is_output_serializable<BinaryData<std::uint32_t>, Archive>::value>
= traits::sfinae> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
{
try
@@ -103,6 +140,30 @@ namespace cereal
bits = std::bitset<N>( b );
break;
}
case bitset_detail::type::bits:
{
// Normally we would use BinaryData to route this at compile time,
// but doing this at runtime doesn't break any old serialization
std::uint8_t chunk = 0;
std::uint8_t mask = 0;
// Load one chunk at a time, rotating through the chunk
// to set bits in the bitset
for( std::size_t i = 0; i < N; ++i )
{
if( mask == 0 )
{
ar( chunk );
mask = 0x80;
}
if( chunk & mask )
bits[i] = 1;
mask >>= 1;
}
break;
}
default:
throw Exception("Invalid bitset data representation");
}
+6
View File
@@ -36,12 +36,14 @@ void test_bitset()
auto rng32 = [&](){ return random_binary_string<32>( gen ); };
auto rng65 = [&](){ return random_binary_string<65>( gen ); };
auto rng256 = [&](){ return random_binary_string<256>( gen ); };
auto rng512 = [&](){ return random_binary_string<512>( gen ); };
for(int ii=0; ii<100; ++ii)
{
std::bitset<32> o_bit32( rng32() );
std::bitset<65> o_bit65( rng65() );
std::bitset<256> o_bit256( rng256() );
std::bitset<512> o_bit512( rng512() );
std::ostringstream os;
{
@@ -50,11 +52,13 @@ void test_bitset()
oar(o_bit32);
oar(o_bit65);
oar(o_bit256);
oar(o_bit512);
}
std::bitset<32> i_bit32;
std::bitset<65> i_bit65;
std::bitset<256> i_bit256;
std::bitset<512> i_bit512;
std::istringstream is(os.str());
{
@@ -63,11 +67,13 @@ void test_bitset()
iar(i_bit32);
iar(i_bit65);
iar(i_bit256);
iar(i_bit512);
}
BOOST_CHECK_EQUAL( o_bit32, i_bit32 );
BOOST_CHECK_EQUAL( o_bit65, i_bit65 );
BOOST_CHECK_EQUAL( o_bit256, i_bit256 );
BOOST_CHECK_EQUAL( o_bit512, i_bit512 );
}
}