# forums.4fips.com

Forums dedicated to the projects hosted at 4FipS.com

## Data-oriented design & programming - A simple benchmark

> About coding, hacking, photography, and such...

### Data-oriented design & programming - A simple benchmark

Since I've been recently very interested in Data Oriented Design (DOD) and wanted to have some real numbers at hand, I've decided to write a simple benchmark that compares the Object and Data Oriented approaches in a fictive particle system. Basically, I'm trying to measure the processing speed (system throughput) at various particle counts.

The graph below shows the dependency:

Here's my configuration:
Windows Vista 64-bit
Visual Studio 2010
Intel Core 2 Quad Q8400 (4 MB Cache, 2.66 GHz, 1333 MHz FSB)
4GB RAM (at 416 MHz)

And here's the code that drives the benchmark:
``/*(c) 2012 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSEARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=588*/#include <fs/system.h>#include <fs/math.h>using namespace fs;using namespace fs::system;using namespace fs::math;struct Cold_data{    char dummy[32];};struct Particle_oop{    Vector3_f pos;    Vector3_f vel;    Vector4_f color;    float size;    Uint32 updates_to_death;    Cold_data cold_data;    void reset()    {        pos = Vector3_f(0.f, 0.f, 0.f);        vel = Vector3_f(1.f, 1.f, 1.f);        color = Vector4_f(0.f, 0.f, 0.f, 0.f);        size = 1.f;        updates_to_death = 1000000;    }    void update(float dt)    {        if(updates_to_death > 0) // alive        {            --updates_to_death;            pos += vel * dt;            color = Vector4_f(0.f, pos.y, 0.f, dt);            size += pos.x;        }    }};struct Particle_system_oop // AoS{    std::vector<Particle_oop> particles;    explicit Particle_system_oop(size_t num_particles):    particles(num_particles)    {        for(size_t i = 0, n = particles.size(); i < n; ++i)            particles[i].reset();    }    void update(float dt)    {        for(size_t i = 0, n = particles.size(); i < n; ++i)            particles[i].update(dt);    }};struct Particle_system_dop // SoA{    std::vector<Vector3_f> pos_vec;    std::vector<Vector3_f> vel_vec;    std::vector<Vector4_f> color_vec;    std::vector<float> size_vec;    std::vector<Uint32> updates_to_death_vec;    std::vector<Cold_data> cold_data_vec;    explicit Particle_system_dop(size_t num_particles):    pos_vec(num_particles),    vel_vec(num_particles),    color_vec(num_particles),    size_vec(num_particles),    updates_to_death_vec(num_particles),    cold_data_vec(num_particles)    {        for(size_t i = 0, n = pos_vec.size(); i < n; ++i)            reset_particle(i);    }    void update(float dt)    {        for(size_t i = 0, n = pos_vec.size(); i < n; ++i)            update_particle(i, dt);    }    void reset_particle(size_t i)    {        pos_vec[i] = Vector3_f(0.f, 0.f, 0.f);        vel_vec[i] = Vector3_f(1.f, 1.f, 1.f);        color_vec[i] = Vector4_f(0.f, 0.f, 0.f, 0.f);        size_vec[i] = 1.f;        updates_to_death_vec[i] = 1000000;    }    void update_particle(size_t i, float dt)    {        Vector3_f &pos = pos_vec[i];        Vector3_f &vel = vel_vec[i];        Vector4_f &color = color_vec[i];        float &size = size_vec[i];        Uint32 &updates_to_death = updates_to_death_vec[i];        if(updates_to_death > 0) // alive        {            --updates_to_death;            pos += vel * dt;            color = Vector4_f(0.f, pos.y, 0.f, dt);            size += pos.x;        }    }};struct Particle_system_nop // AoS / no pool{    typedef std::unique_ptr<Particle_oop> Particle_oop_ptr;    std::vector<Particle_oop_ptr> particles;    explicit Particle_system_nop(size_t num_particles):    particles(num_particles)    {        for(size_t i = 0, n = particles.size(); i < n; ++i)        {            particles[i] = std::move(Particle_oop_ptr(new Particle_oop));            particles[i]->reset();        }    }    void update(float dt)    {        for(size_t i = 0, n = particles.size(); i < n; ++i)            particles[i]->update(dt);    }};double run_particle_system_oop(size_t num_particles, size_t num_iterations){    Particle_system_oop particle_sys_oop(num_particles);    const double t = time_sec();    for(size_t j = 0; j < num_iterations; ++j)        particle_sys_oop.update(.1f);    const double dur = time_sec() - t;    printf("run_particle_system_oop(%u, %u) -> %f s\n",     unsigned(num_particles), unsigned(num_iterations), dur);    return dur;}double run_particle_system_dop(size_t num_particles, size_t num_iterations){    Particle_system_dop particle_sys_dop(num_particles);    const double t = time_sec();    for(size_t j = 0; j < num_iterations; ++j)        particle_sys_dop.update(.1f);    const double dur = time_sec() - t;    printf("run_particle_system_dop(%u, %u) -> %f s\n",     unsigned(num_particles), unsigned(num_iterations), dur);    return dur;}double run_particle_system_nop(size_t num_particles, size_t num_iterations){    Particle_system_nop particle_sys_nop(num_particles);    const double t = time_sec();    for(size_t j = 0; j < num_iterations; ++j)        particle_sys_nop.update(.1f);    const double dur = time_sec() - t;    printf("run_particle_system_nop(%u, %u) -> %f s\n",     unsigned(num_particles), unsigned(num_iterations), dur);    return dur;}int main(){    double total_oop = 0.0;    double total_dop = 0.0;    double total_nop = 0.0;    for(size_t j = 1; j <= 100; ++j)    {        const size_t num_particles = 1000 * j;        printf("num_particles = %u\n", (unsigned)num_particles);        double dur_oop = 0.0;        double dur_dop = 0.0;        double dur_nop = 0.0;        size_t sum_particles = 0;        for(int i = 1; i <= 5; ++i)        {            const size_t num_iterations = 1000 * i;            dur_oop += run_particle_system_oop(num_particles, num_iterations);            dur_dop += run_particle_system_dop(num_particles, num_iterations);            dur_nop += run_particle_system_nop(num_particles, num_iterations);            sum_particles += num_particles * num_iterations;        }        printf("oop -> %f s, dop -> %f s , nop -> %f s\n",         dur_oop, dur_dop, dur_nop);        printf("oop -> %f M/s, dop -> %f M/s, nop -> %f M/s\n\n",         .000001 * sum_particles / dur_oop,         .000001 * sum_particles / dur_dop,         .000001 * sum_particles / dur_nop);        total_oop += dur_oop;        total_dop += dur_dop;        total_nop += dur_nop;    }    printf("total: oop -> %f s, dop -> %f s, nop -> %f s\n\n",     total_oop, total_dop, total_nop);    return 0;}``

fips

Posts: 161
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague