Skip to content

Instantly share code, notes, and snippets.

@chrsmutti
Created April 8, 2024 03:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrsmutti/698f979ad07be89ec3319dceb13565a9 to your computer and use it in GitHub Desktop.
Save chrsmutti/698f979ad07be89ec3319dceb13565a9 to your computer and use it in GitHub Desktop.
"Clean" Code, Horrible Performance in Rust
#![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;
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
});
}
}
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
});
}
}
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
});
}
}
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