Created
April 8, 2024 03:17
-
-
Save chrsmutti/698f979ad07be89ec3319dceb13565a9 to your computer and use it in GitHub Desktop.
"Clean" Code, Horrible Performance in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(test)] | |
#![allow(dead_code)] | |
extern crate test; | |
mod m01_trait; | |
mod m02_match; | |
mod m03_table; | |
mod m04_table_multiplier; | |
const COUNT: usize = 1024 * 10; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f32::consts::PI; | |
trait Shape { | |
fn area(&self) -> f32; | |
fn corner(&self) -> f32; | |
} | |
struct Square { | |
side: f32, | |
} | |
impl Shape for Square { | |
fn area(&self) -> f32 { | |
self.side * self.side | |
} | |
fn corner(&self) -> f32 { | |
4f32 | |
} | |
} | |
struct Rectangle { | |
width: f32, | |
height: f32, | |
} | |
impl Shape for Rectangle { | |
fn area(&self) -> f32 { | |
self.width * self.height | |
} | |
fn corner(&self) -> f32 { | |
4f32 | |
} | |
} | |
struct Triangle { | |
base: f32, | |
height: f32, | |
} | |
impl Shape for Triangle { | |
fn area(&self) -> f32 { | |
0.5f32 * self.base * self.height | |
} | |
fn corner(&self) -> f32 { | |
3f32 | |
} | |
} | |
struct Circle { | |
radius: f32, | |
} | |
impl Shape for Circle { | |
fn area(&self) -> f32 { | |
PI * self.radius * self.radius | |
} | |
fn corner(&self) -> f32 { | |
0f32 | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use crate::COUNT; | |
use test::Bencher; | |
fn init(count: usize) -> Vec<Box<dyn Shape>> { | |
let mut shapes: Vec<Box<dyn Shape>> = Vec::with_capacity(count); | |
for i in 0..count { | |
match i % 4 { | |
0 => shapes.push(Box::new(Square { side: i as f32 })), | |
1 => shapes.push(Box::new(Rectangle { | |
height: i as f32, | |
width: i as f32 * 2f32, | |
})), | |
2 => shapes.push(Box::new(Triangle { | |
base: i as f32, | |
height: i as f32 * 2f32, | |
})), | |
3 => shapes.push(Box::new(Circle { radius: i as f32 })), | |
_ => panic!("impossible to get another value"), | |
} | |
} | |
shapes | |
} | |
#[bench] | |
fn total_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn total_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].area(); | |
accum2 += shapes[1 + (iter * 4)].area(); | |
accum3 += shapes[2 + (iter * 4)].area(); | |
accum4 += shapes[3 + (iter * 4)].area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
#[bench] | |
fn corner_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += 1f32 / (1f32 + shape.corner() * shape.area()); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn corner_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += 1f32 / (1f32 + shapes[iter * 4].corner() * shapes[iter * 4].area()); | |
accum2 += | |
1f32 / (1f32 + shapes[1 + iter * 4].corner() * shapes[1 + iter * 4].area()); | |
accum3 += | |
1f32 / (1f32 + shapes[2 + iter * 4].corner() * shapes[2 + iter * 4].area()); | |
accum4 += | |
1f32 / (1f32 + shapes[3 + iter * 4].corner() * shapes[3 + iter * 4].area()); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f32::consts::PI; | |
enum Shape { | |
Square { side: f32 }, | |
Rectangle { width: f32, height: f32 }, | |
Triangle { base: f32, height: f32 }, | |
Circle { radius: f32 }, | |
} | |
impl Shape { | |
fn area(&self) -> f32 { | |
match self { | |
Shape::Square { side } => side * side, | |
Shape::Rectangle { width, height } => width * height, | |
Shape::Triangle { base, height } => 0.5f32 * base * height, | |
Shape::Circle { radius } => PI * radius * radius, | |
} | |
} | |
fn corner(&self) -> f32 { | |
match self { | |
Shape::Square { .. } => 4f32, | |
Shape::Rectangle { .. } => 4f32, | |
Shape::Triangle { .. } => 3f32, | |
Shape::Circle { .. } => 0f32, | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use crate::COUNT; | |
use test::Bencher; | |
fn init(count: usize) -> Vec<Shape> { | |
let mut shapes: Vec<Shape> = Vec::with_capacity(count); | |
for i in 0..count { | |
match i % 4 { | |
0 => shapes.push(Shape::Square { side: i as f32 }), | |
1 => shapes.push(Shape::Rectangle { | |
height: i as f32, | |
width: i as f32 * 2f32, | |
}), | |
2 => shapes.push(Shape::Triangle { | |
base: i as f32, | |
height: i as f32 * 2f32, | |
}), | |
3 => shapes.push(Shape::Circle { radius: i as f32 }), | |
_ => panic!("impossible to get another value"), | |
} | |
} | |
shapes | |
} | |
#[bench] | |
fn total_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn total_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].area(); | |
accum2 += shapes[1 + (iter * 4)].area(); | |
accum3 += shapes[2 + (iter * 4)].area(); | |
accum4 += shapes[3 + (iter * 4)].area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
#[bench] | |
fn corner_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += 1f32 / (1f32 + shape.corner() * shape.area()); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn corner_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += 1f32 / (1f32 + shapes[iter * 4].corner() * shapes[iter * 4].area()); | |
accum2 += | |
1f32 / (1f32 + shapes[1 + iter * 4].corner() * shapes[1 + iter * 4].area()); | |
accum3 += | |
1f32 / (1f32 + shapes[2 + iter * 4].corner() * shapes[2 + iter * 4].area()); | |
accum4 += | |
1f32 / (1f32 + shapes[3 + iter * 4].corner() * shapes[3 + iter * 4].area()); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f32::consts::PI; | |
enum ShapeType { | |
Square, | |
Rectangle, | |
Triangle, | |
Circle, | |
} | |
impl ShapeType { | |
fn constant(&self) -> f32 { | |
match self { | |
ShapeType::Square => 1f32, | |
ShapeType::Rectangle => 1f32, | |
ShapeType::Triangle => 0.5f32, | |
ShapeType::Circle => PI, | |
} | |
} | |
fn constant_corner(&self) -> f32 { | |
match self { | |
ShapeType::Square => 1f32 / (1f32 + 4f32), | |
ShapeType::Rectangle => 1f32 / (1f32 + 4f32), | |
ShapeType::Triangle => 0.5f32 / (1f32 + 3f32), | |
ShapeType::Circle => PI, | |
} | |
} | |
} | |
struct Shape { | |
shape_type: ShapeType, | |
width: f32, | |
height: f32, | |
} | |
impl Shape { | |
fn area(&self) -> f32 { | |
self.shape_type.constant() * self.width * self.height | |
} | |
fn corner_area(&self) -> f32 { | |
self.shape_type.constant_corner() * self.width * self.height | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use crate::COUNT; | |
use test::Bencher; | |
fn init(count: usize) -> Vec<Shape> { | |
let mut shapes: Vec<Shape> = Vec::with_capacity(count); | |
for i in 0..count { | |
match i % 4 { | |
0 => shapes.push(Shape { | |
shape_type: ShapeType::Square, | |
width: i as f32, | |
height: i as f32, | |
}), | |
1 => shapes.push(Shape { | |
shape_type: ShapeType::Rectangle, | |
width: i as f32, | |
height: i as f32 * 2f32, | |
}), | |
2 => shapes.push(Shape { | |
shape_type: ShapeType::Triangle, | |
width: i as f32, | |
height: i as f32 * 2f32, | |
}), | |
3 => shapes.push(Shape { | |
shape_type: ShapeType::Circle, | |
width: i as f32, | |
height: i as f32 * 2f32, | |
}), | |
_ => panic!("impossible to get another value"), | |
} | |
} | |
shapes | |
} | |
#[bench] | |
fn total_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn total_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].area(); | |
accum2 += shapes[1 + (iter * 4)].area(); | |
accum3 += shapes[2 + (iter * 4)].area(); | |
accum4 += shapes[3 + (iter * 4)].area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
#[bench] | |
fn corner_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.corner_area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn corner_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].corner_area(); | |
accum2 += shapes[1 + (iter * 4)].corner_area(); | |
accum3 += shapes[2 + (iter * 4)].corner_area(); | |
accum4 += shapes[3 + (iter * 4)].corner_area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f32::consts::PI; | |
enum ShapeType { | |
Square { side: f32 }, | |
Rectangle { width: f32, height: f32 }, | |
Triangle { base: f32, height: f32 }, | |
Circle { radius: f32 }, | |
} | |
struct Shape { | |
multiplier: f32, | |
corner_area_multiplier: f32, | |
width: f32, | |
height: f32, | |
} | |
impl Shape { | |
fn new(shape_type: ShapeType) -> Self { | |
match shape_type { | |
ShapeType::Square { side } => Shape { | |
multiplier: 1f32, | |
corner_area_multiplier: 1f32 / (1f32 + 4f32), | |
width: side, | |
height: side, | |
}, | |
ShapeType::Rectangle { width, height } => Shape { | |
multiplier: 1f32, | |
corner_area_multiplier: 1f32 / (1f32 + 4f32), | |
width, | |
height, | |
}, | |
ShapeType::Triangle { base, height } => Shape { | |
multiplier: 0.5f32, | |
corner_area_multiplier: 0.5f32 / (1f32 + 4f32), | |
width: base, | |
height, | |
}, | |
ShapeType::Circle { radius } => Shape { | |
multiplier: PI, | |
corner_area_multiplier: PI, | |
width: radius, | |
height: radius, | |
}, | |
} | |
} | |
fn area(&self) -> f32 { | |
self.multiplier * self.width * self.height | |
} | |
fn corner_area(&self) -> f32 { | |
self.corner_area_multiplier * self.width * self.height | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use crate::COUNT; | |
use test::Bencher; | |
fn init(count: usize) -> Vec<Shape> { | |
let mut shapes: Vec<Shape> = Vec::with_capacity(count); | |
for i in 0..count { | |
match i % 4 { | |
0 => shapes.push(Shape::new(ShapeType::Square { side: i as f32 })), | |
1 => shapes.push(Shape::new(ShapeType::Rectangle { | |
width: i as f32, | |
height: i as f32 * 2f32, | |
})), | |
2 => shapes.push(Shape::new(ShapeType::Triangle { | |
base: i as f32, | |
height: i as f32 * 2f32, | |
})), | |
3 => shapes.push(Shape::new(ShapeType::Circle { radius: i as f32 })), | |
_ => panic!("impossible to get another value"), | |
} | |
} | |
shapes | |
} | |
#[bench] | |
fn total_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn total_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].area(); | |
accum2 += shapes[1 + (iter * 4)].area(); | |
accum3 += shapes[2 + (iter * 4)].area(); | |
accum4 += shapes[3 + (iter * 4)].area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
#[bench] | |
fn corner_area(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum = 0f32; | |
for shape in &shapes { | |
accum += shape.corner_area(); | |
} | |
accum | |
}); | |
} | |
#[bench] | |
fn corner_area_sum4(b: &mut Bencher) { | |
let shapes = init(COUNT); | |
b.iter(|| { | |
let mut accum1 = 0f32; | |
let mut accum2 = 0f32; | |
let mut accum3 = 0f32; | |
let mut accum4 = 0f32; | |
let count = COUNT / 4; | |
let mut iter = 1; | |
while count - iter > 0 { | |
accum1 += shapes[iter * 4].corner_area(); | |
accum2 += shapes[1 + (iter * 4)].corner_area(); | |
accum3 += shapes[2 + (iter * 4)].corner_area(); | |
accum4 += shapes[3 + (iter * 4)].corner_area(); | |
iter += 1; | |
} | |
accum1 + accum2 + accum3 + accum4 | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment