soa_derive 0.12.0

Automatic Struct of Array generation
Documentation
#![allow(clippy::needless_return)]

use soa_derive::StructOfArray;

use bencher::{Bencher, benchmark_group, benchmark_main};

#[derive(StructOfArray)]
pub struct Small {
    x: f64,
    y: f64,
    z: f64,
}

impl Small {
    fn new() -> Small {
        Small {
            x: 1.0,
            y: 0.2,
            z: -2.3,
        }
    }

    fn aos_vec(size: usize) -> Vec<Small> {
        let mut vec = Vec::new();
        for _ in 0..size {
            vec.push(Small::new())
        }
        return vec;
    }

    fn soa_vec(size: usize) -> SmallVec {
        let mut vec = SmallVec::new();
        for _ in 0..size {
            vec.push(Small::new())
        }
        return vec;
    }
}

#[derive(StructOfArray)]
pub struct Big {
    position: (f64, f64, f64),
    velocity: (f64, f64, f64),
    id: usize,
    name: String,
    userdata: String
}

impl Big {
    fn new() -> Big {
        Big {
            position: (1.0, 0.2, -2.3),
            velocity: (1.0, 0.2, -2.3),
            id: 67,
            name: "foo".into(),
            userdata: "bar".into()
        }
    }

    fn aos_vec(size: usize) -> Vec<Big> {
        let mut vec = Vec::new();
        for _ in 0..size {
            vec.push(Big::new())
        }
        return vec;
    }

    fn soa_vec(size: usize) -> BigVec {
        let mut vec = BigVec::new();
        for _ in 0..size {
            vec.push(Big::new())
        }
        return vec;
    }
}

fn aos_small_push(bencher: &mut Bencher) {
    let mut vec = Vec::new();
    bencher.iter(||{
        vec.push(Small::new())
    })
}

fn soa_small_push(bencher: &mut Bencher) {
    let mut vec = SmallVec::new();
    bencher.iter(||{
        vec.push(Small::new())
    })
}

fn aos_big_push(bencher: &mut Bencher) {
    let mut vec = Vec::new();
    bencher.iter(||{
        vec.push(Big::new())
    })
}

fn soa_big_push(bencher: &mut Bencher) {
    let mut vec = BigVec::new();
    bencher.iter(||{
        vec.push(Big::new())
    })
}

fn aos_small_do_work_10000(bencher: &mut Bencher) {
    let vec = Small::aos_vec(10000);
    bencher.iter(||{
        let mut s = 0.0;
        for v in &vec {
            s += v.x + v.y;
        }
        s
    })
}

fn soa_small_do_work_10000(bencher: &mut Bencher) {
    let vec = Small::soa_vec(10000);
    bencher.iter(||{
        let mut s = 0.0;
        for (x, y) in vec.x.iter().zip(&vec.y) {
            s += x + y;
        }
        s
    })
}

fn aos_big_do_work_1000(bencher: &mut Bencher) {
    let vec = Big::aos_vec(1000);
    bencher.iter(||{
        let mut s = 0.0;
        for v in &vec {
            s += v.position.0 + v.velocity.0 * 0.1;
        }
        s
    })
}

fn aos_big_do_work_10000(bencher: &mut Bencher) {
    let vec = Big::aos_vec(10000);
    bencher.iter(||{
        let mut s = 0.0;
        for v in &vec {
            s += v.position.0 + v.velocity.0 * 0.1;
        }
        s
    })
}

fn soa_big_do_work_1000(bencher: &mut Bencher) {
    let vec = Big::soa_vec(1000);
    bencher.iter(||{
        let mut s = 0.0;
        for (position, velocity) in vec.position.iter().zip(&vec.velocity) {
            s += position.0 + velocity.0;
        }
        s
    })
}

fn soa_big_do_work_10000(bencher: &mut Bencher) {
    let vec = Big::soa_vec(10000);
    bencher.iter(||{
        let mut s = 0.0;
        for (position, velocity) in vec.position.iter().zip(&vec.velocity) {
            s += position.0 + velocity.0;
        }
        s
    })
}


benchmark_group!(aos,
    aos_small_push, aos_big_push, aos_small_do_work_10000, aos_big_do_work_1000,
    aos_big_do_work_10000
);
benchmark_group!(soa,
    soa_small_push, soa_big_push, soa_small_do_work_10000, soa_big_do_work_1000,
    soa_big_do_work_10000
);
benchmark_main!(soa, aos);