Skip to content

Instantly share code, notes, and snippets.

@FlexW
Last active April 13, 2023 09:43
Show Gist options
  • Save FlexW/e6a682af212f6d59d1eff637484e4e12 to your computer and use it in GitHub Desktop.
Save FlexW/e6a682af212f6d59d1eff637484e4e12 to your computer and use it in GitHub Desktop.
Clean code bench
// Code from https://blog.codef00.com/2023/04/13/casey-muratori-is-wrong-about-clean-code
// I've created this file to try to reproduce the results in this blog.
// This little program was timed with Measure-Command { a.exe 9999999 | Out-Default } repeatedly
// and compiled with Clang 16.0.0 x86_64-pc_windows-msvc with the command clang++.exe -std=c++17 -O3 cleancodebench.cpp.
// On my hardware and operating system Ryzen 7 5800X and Windows 11 I couldn't reproduce the results.
// My ranking was:
// 1. TestTotalAreaSwitch4 ~15ms
// 2. TestTotalAreaSwitch ~550ms
// 4. TestTotalAreaVariant ~550ms
// 3. TestTotalAreaVariant4 ~590ms
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <variant>
using f32 = float;
using u32 = uint32_t;
constexpr f32 Pi32 = 3.14159;
constexpr int Count = 128;
class square {
public:
square(f32 SideInit) : Side(SideInit) {}
f32 Area() const { return Side * Side; }
private:
f32 Side;
};
class rectangle {
public:
rectangle(f32 WidthInit, f32 HeightInit)
: Width(WidthInit), Height(HeightInit) {}
f32 Area() const { return Width * Height; }
private:
f32 Width, Height;
};
class triangle {
public:
triangle(f32 BaseInit, f32 HeightInit) : Base(BaseInit), Height(HeightInit) {}
f32 Area() const { return 0.5f * Base * Height; }
private:
f32 Base, Height;
};
class circle {
public:
circle(f32 RadiusInit) : Radius(RadiusInit) {}
f32 Area() const { return Pi32 * Radius * Radius; }
private:
f32 Radius;
};
class default_shape {
public:
f32 Area() const { return 0.0; }
};
using any_shape =
std::variant<default_shape, square, rectangle, triangle, circle>;
f32 TotalAreaVariant(u32 ShapeCount, any_shape *Shapes) {
f32 Accum = 0.0f;
for (u32 ShapeIndex = 0; ShapeIndex < ShapeCount; ++ShapeIndex) {
Accum += std::visit([](auto &&shape) { return shape.Area(); },
Shapes[ShapeIndex]);
}
return Accum;
}
f32 TotalAreaVariant4(u32 ShapeCount, any_shape *Shapes) {
f32 Accum0 = 0.0f;
f32 Accum1 = 0.0f;
f32 Accum2 = 0.0f;
f32 Accum3 = 0.0f;
u32 Count = ShapeCount / 4;
while (Count--) {
Accum0 += std::visit([](auto &&shape) { return shape.Area(); }, Shapes[0]);
Accum1 += std::visit([](auto &&shape) { return shape.Area(); }, Shapes[1]);
Accum2 += std::visit([](auto &&shape) { return shape.Area(); }, Shapes[2]);
Accum3 += std::visit([](auto &&shape) { return shape.Area(); }, Shapes[3]);
Shapes += 4;
}
f32 Result = (Accum0 + Accum1 + Accum2 + Accum3);
return Result;
}
enum shape_type : u32 {
Shape_Square,
Shape_Rectangle,
Shape_Triangle,
Shape_Circle,
Shape_Count,
};
struct shape_union {
shape_type Type;
f32 Width;
f32 Height;
};
f32 GetAreaSwitch(shape_union Shape) {
f32 Result = 0.0f;
switch (Shape.Type) {
case Shape_Square: {
Result = Shape.Width * Shape.Width;
} break;
case Shape_Rectangle: {
Result = Shape.Width * Shape.Height;
} break;
case Shape_Triangle: {
Result = 0.5f * Shape.Width * Shape.Height;
} break;
case Shape_Circle: {
Result = Pi32 * Shape.Width * Shape.Width;
} break;
case Shape_Count: {
} break;
}
return Result;
}
f32 TotalAreaSwitch(u32 ShapeCount, shape_union *Shapes) {
f32 Accum = 0.0f;
for (u32 ShapeIndex = 0; ShapeIndex < ShapeCount; ++ShapeIndex) {
Accum += GetAreaSwitch(Shapes[ShapeIndex]);
}
return Accum;
}
f32 TotalAreaSwitch4(u32 ShapeCount, shape_union *Shapes) {
f32 Accum0 = 0.0f;
f32 Accum1 = 0.0f;
f32 Accum2 = 0.0f;
f32 Accum3 = 0.0f;
ShapeCount /= 4;
while (ShapeCount--) {
Accum0 += GetAreaSwitch(Shapes[0]);
Accum1 += GetAreaSwitch(Shapes[1]);
Accum2 += GetAreaSwitch(Shapes[2]);
Accum3 += GetAreaSwitch(Shapes[3]);
Shapes += 4;
}
f32 Result = (Accum0 + Accum1 + Accum2 + Accum3);
return Result;
}
static void TestTotalAreaVariant(u32 TestIterations) {
srand(0); // predictable seed
any_shape shapes[Count];
for (int i = 0; i < Count; i++) {
switch (i & 3) {
case 0:
shapes[i] = square(rand());
break;
case 1:
shapes[i] = (rectangle(rand(), rand()));
break;
case 2:
shapes[i] = (triangle(rand(), rand()));
break;
case 3:
shapes[i] = (circle(rand()));
break;
}
}
f32 result;
for (u32 i = 0; i < TestIterations; ++i) {
result += TotalAreaVariant(Count, shapes);
}
printf("result %f\n", result);
}
static void TestTotalAreaVariant4(u32 TestIterations) {
srand(0); // predictable seed
any_shape shapes[Count];
for (int i = 0; i < Count; i++) {
switch (i & 3) {
case 0:
shapes[i] = square(rand());
break;
case 1:
shapes[i] = (rectangle(rand(), rand()));
break;
case 2:
shapes[i] = (triangle(rand(), rand()));
break;
case 3:
shapes[i] = (circle(rand()));
break;
}
}
f32 result;
for (u32 i = 0; i < TestIterations; ++i) {
result += TotalAreaVariant4(Count, shapes);
}
printf("result %f\n", result);
}
static void TestTotalAreaSwitch(u32 TestIterations) {
srand(0); // predictable seed
shape_union shapes[Count];
for (int i = 0; i < Count; i++) {
switch (i & 3) {
case 0:
shapes[i] = {Shape_Square, static_cast<f32>(rand())};
break;
case 1:
shapes[i] = {Shape_Rectangle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
case 2:
shapes[i] = {Shape_Triangle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
case 3:
shapes[i] = {Shape_Circle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
}
}
f32 result;
for (u32 i = 0; i < TestIterations; ++i) {
result += TotalAreaSwitch(Count, shapes);
}
printf("result %f\n", result);
}
static void TestTotalAreaSwitch4(u32 TestIterations) {
srand(0); // predictable seed
shape_union shapes[Count];
for (int i = 0; i < Count; i++) {
switch (i & 3) {
case 0:
shapes[i] = {Shape_Square, static_cast<f32>(rand())};
break;
case 1:
shapes[i] = {Shape_Rectangle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
case 2:
shapes[i] = {Shape_Triangle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
case 3:
shapes[i] = {Shape_Circle, static_cast<f32>(rand()),
static_cast<f32>(rand())};
break;
}
}
f32 result;
for (u32 i = 0; i < TestIterations; ++i) {
result += TotalAreaSwitch4(Count, shapes);
}
printf("result %f\n", result);
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: %s <iterations>", argv[0]);
return 1;
}
u32 iterations = atoi(argv[1]);
// Uncomment one of the test cases
// TestTotalAreaVariant(iterations);
// TestTotalAreaVariant4(iterations);
TestTotalAreaSwitch(iterations);
// TestTotalAreaSwitch4(iterations);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment