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:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user