Skip to main content

Benchmark

The benchmark module is responsible for showing me what implementation is better for heavy data tasks by measuring how much time it takes for a specific job to finish

For example, I wanted to see serialization and deserialization timings for both yaml and json file formats

Example for json

BENCHMARK( kogayonon_benchmark::BM_JsonSerialization )
->Arg( 1000 )
->Arg( 100000 )
->Arg( 1000000 ) // number of entities to be seraialized
->Unit( benchmark::kSecond );// we want the result in seconds

And the function code looks like this, this is pretty self explanatory, we just save in json format all the data from the components we want to serialize

static void BM_JsonSerialization( benchmark::State& state )
{
for ( auto _ : state )
{
kogayonon_core::Registry registry;
// create the file
auto p = std::filesystem::absolute( "." );
p /= "benchmark.json";

// have a constant number of entries in the file for the deserialization
if(std::filesystem::exists(p))
std::filesystem::remove(p);

auto serializer = std::make_unique<kogayonon_utilities::JsonSerializer>( p.string() );

std::vector<kogayonon_core::Entity> entities;
// pass the args in here to allocate enough memory
entities.reserve( state.range( 0 ) );

for ( std::size_t i = 0; i < state.range( 0 ); ++i )
{
kogayonon_core::Entity entity{ &registry, registry.createEntity() };

entity.addComponent<kogayonon_core::TransformComponent>( kogayonon_core::TransformComponent{
.translation = { 1.0f, 2.0f, 3.0f },
.rotation = { 1.0f, 2.0f, 3.0f },
.scale = { 1.0f, 2.0f, 3.0f } }
);

entities.emplace_back( entity );
}

// now serialize
serializer->startDocument().startArray( "entities" );
for ( auto entity : entities )
{
auto& transform = entity.getComponent<kogayonon_core::TransformComponent>();
auto& rotation = transform.rotation;
auto& scale = transform.scale;
auto& translation = transform.translation;
// clang-format off
serializer->
startObject()
.addKeyValuePair("id",static_cast<int>(entity.getEntityId()))
.startObject("transform")
.startArray("rotation")
.addValue(rotation.x)
.addValue(rotation.x)
.addValue(rotation.x)
.endArray()
.startArray("scale")
.addValue(scale.x)
.addValue(scale.x)
.addValue(scale.x)
.endArray()
.startArray("translation")
.addValue(translation.x)
.addValue(translation.x)
.addValue(translation.x)
.endArray()
.endObject()
.endObject();

// clang-format on
}
serializer->endArray().endDocument();
}

Release build

Json

  • serialization

    EntitiesTime (CPU)
    1,000~0.002 s
    100,000~0.176 s
    1,000,000~1.92 s
  • deserialization

    EntitiesTime (CPU)
    1,000~4.77 s
    100,000~4.70 s
    1,000,000~4.67 s

Debug Build

Json

  • serialization

    EntitiesTime (CPU)
    1,000~0.030 s
    100,000~2.86 s
    1,000,000~29.4 s
  • deserialization

    EntitiesTime (CPU)
    1,000~46.6 s
    100,000~44.4 s
    1,000,000~35.8 s

Yaml findings were not good enough to post them here, 1mil entities would take roughly 8mins so I'll keep it for config files instead of scene serialization