112 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use criterion::*;
 | |
| 
 | |
| use cgmath::prelude::*;
 | |
| use cgmath::{vec3, Matrix4, Quaternion, Vector3};
 | |
| use legion::prelude::*;
 | |
| use rayon::join;
 | |
| 
 | |
| #[derive(Copy, Clone, Debug, PartialEq)]
 | |
| struct Position(Vector3<f32>);
 | |
| 
 | |
| #[derive(Copy, Clone, Debug, PartialEq)]
 | |
| struct Orientation(Quaternion<f32>);
 | |
| 
 | |
| #[derive(Copy, Clone, Debug, PartialEq)]
 | |
| struct Scale(Vector3<f32>);
 | |
| 
 | |
| #[derive(Copy, Clone, Debug, PartialEq)]
 | |
| struct Transform(Matrix4<f32>);
 | |
| 
 | |
| fn data(n: usize) -> Vec<(Position, Orientation, Scale, Transform)> {
 | |
|     let mut v = Vec::<(Position, Orientation, Scale, Transform)>::new();
 | |
| 
 | |
|     for _ in 0..n {
 | |
|         v.push((
 | |
|             Position(vec3(0.0, 0.0, 0.0)),
 | |
|             Orientation(Quaternion::new(1.0, 0.0, 0.0, 0.0)),
 | |
|             Scale(vec3(0.0, 0.0, 0.0)),
 | |
|             Transform(Matrix4::identity()),
 | |
|         ));
 | |
|     }
 | |
| 
 | |
|     v
 | |
| }
 | |
| 
 | |
| fn setup(data: Vec<(Position, Orientation, Scale, Transform)>) -> World {
 | |
|     let universe = Universe::new();
 | |
|     let mut world = universe.create_world();
 | |
| 
 | |
|     world.insert((), data);
 | |
| 
 | |
|     world
 | |
| }
 | |
| 
 | |
| fn process(
 | |
|     position: &Vector3<f32>,
 | |
|     orientation: &Quaternion<f32>,
 | |
|     scale: &Vector3<f32>,
 | |
| ) -> Matrix4<f32> {
 | |
|     let rot: Matrix4<f32> = (*orientation).into();
 | |
|     Matrix4::from_nonuniform_scale(scale.x, scale.y, scale.z)
 | |
|         * rot
 | |
|         * Matrix4::from_translation(*position)
 | |
| }
 | |
| 
 | |
| fn ideal(data: &mut Vec<(Position, Orientation, Scale, Transform)>) {
 | |
|     for (pos, orient, scale, trans) in data.iter_mut() {
 | |
|         trans.0 = process(&pos.0, &orient.0, &scale.0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn sequential(world: &mut World) {
 | |
|     for (pos, orient, scale, mut trans) in <(
 | |
|         Read<Position>,
 | |
|         Read<Orientation>,
 | |
|         Read<Scale>,
 | |
|         Write<Transform>,
 | |
|     )>::query()
 | |
|     .iter_mut(world)
 | |
|     {
 | |
|         trans.0 = process(&pos.0, &orient.0, &scale.0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn par_for_each_mut(world: &mut World) {
 | |
|     <(
 | |
|         Read<Position>,
 | |
|         Read<Orientation>,
 | |
|         Read<Scale>,
 | |
|         Write<Transform>,
 | |
|     )>::query()
 | |
|     .par_for_each_mut(world, |(pos, orient, scale, mut trans)| {
 | |
|         trans.0 = process(&pos.0, &orient.0, &scale.0);
 | |
|     });
 | |
| }
 | |
| 
 | |
| fn bench_transform(c: &mut Criterion) {
 | |
|     c.bench(
 | |
|         "update transform (experimental)",
 | |
|         ParameterizedBenchmark::new(
 | |
|             "ideal sequential",
 | |
|             |b, n| {
 | |
|                 let mut data = data(*n);
 | |
|                 b.iter(|| ideal(&mut data));
 | |
|             },
 | |
|             (1..11).map(|i| i * 1000),
 | |
|         )
 | |
|         .with_function("sequential", |b, n| {
 | |
|             let data = data(*n);
 | |
|             let mut world = setup(data);
 | |
|             b.iter(|| sequential(&mut world));
 | |
|         })
 | |
|         .with_function("par_for_each_mut", |b, n| {
 | |
|             let data = data(*n);
 | |
|             let mut world = setup(data);
 | |
|             join(|| {}, || b.iter(|| par_for_each_mut(&mut world)));
 | |
|         }),
 | |
|     );
 | |
| }
 | |
| 
 | |
| criterion_group!(iterate, bench_transform);
 | |
| criterion_main!(iterate);
 | 
