Skip to content

Instantly share code, notes, and snippets.

@vladiant
Created March 16, 2023 18:17
Show Gist options
  • Save vladiant/9e5a13f1590568e6576faada88df8793 to your computer and use it in GitHub Desktop.
Save vladiant/9e5a13f1590568e6576faada88df8793 to your computer and use it in GitHub Desktop.
"Clean" Code, Horrible Performance and the forgotten variant
// https://www.reddit.com/r/cpp/comments/11rzncu/clean_code_horrible_performance_and_the_forgotten/
// https://quick-bench.com/q/mW30pqwTvtWZ-aT6COu1oiUycYc
#include <cmath>
#include <cstdlib>
#include <cstddef>
#include <ctime>
#include <memory>
#include <variant>
#include <vector>
namespace utils {
inline float random_float() {
return static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
}
inline constexpr float pi = 3.14159265358979323846f;
} // namespace utils
namespace clean {
class shape_base {
public:
shape_base() {}
virtual float Area() const = 0;
};
class square : public shape_base {
public:
square(float SideInit) : Side(SideInit) {}
virtual float Area() const { return Side * Side; }
private:
float Side;
};
class rectangle : public shape_base {
public:
rectangle(float WidthInit, float HeightInit)
: Width(WidthInit), Height(HeightInit) {}
virtual float Area() const { return Width * Height; }
private:
float Width, Height;
};
class triangle : public shape_base {
public:
triangle(float BaseInit, float HeightInit)
: Base(BaseInit), Height(HeightInit) {}
virtual float Area() const { return 0.5f * Base * Height; }
private:
float Base, Height;
};
class circle : public shape_base {
public:
circle(float RadiusInit) : Radius(RadiusInit) {}
virtual float Area() const { return utils::pi * Radius * Radius; }
private:
float Radius;
};
inline std::vector<std::unique_ptr<shape_base>>
shape_builder(std::size_t count) {
std::srand(std::time(nullptr));
std::vector<std::unique_ptr<shape_base>> shapes;
shapes.reserve(count);
for (std::size_t i = 0; i < count; i++) {
switch (std::rand() % 4) {
case 0:
shapes.push_back(std::make_unique<square>(utils::random_float()));
break;
case 1:
shapes.push_back(std::make_unique<rectangle>(utils::random_float(),
utils::random_float()));
break;
case 2:
shapes.push_back(std::make_unique<triangle>(utils::random_float(),
utils::random_float()));
break;
case 3:
shapes.push_back(std::make_unique<circle>(utils::random_float()));
break;
}
}
return shapes;
}
inline float
total_area(const std::vector<std::unique_ptr<shape_base>> &shapes) {
float total_area{};
for (const auto &shape : shapes) {
total_area += shape->Area();
}
return total_area;
}
} // namespace clean
namespace switchcase {
enum shape_type {
Shape_Square,
Shape_Rectangle,
Shape_Triangle,
Shape_Circle,
Shape_Count,
};
struct shape_union {
shape_type Type;
float Width;
float Height;
};
inline float GetAreaSwitch(shape_union Shape) {
float 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 = utils::pi * Shape.Width * Shape.Width;
} break;
case Shape_Count: {
} break;
}
return Result;
}
inline std::vector<shape_union> shape_builder(std::size_t count) {
std::srand(std::time(nullptr));
std::vector<shape_union> shapes;
shapes.reserve(count);
for (std::size_t i = 0; i < count; i++) {
shapes.push_back(shape_union{static_cast<shape_type>(std::rand() % 4),
utils::random_float(), utils::random_float()});
}
return shapes;
}
inline float total_area(const std::vector<shape_union> &shapes) {
float total_area{};
for (const auto &shape : shapes) {
total_area += GetAreaSwitch(shape);
}
return total_area;
}
} // namespace switchcase
namespace variant {
class square {
public:
square(float SideInit) : Side(SideInit) {}
float Area() const { return Side * Side; }
private:
float Side;
};
class rectangle {
public:
rectangle(float WidthInit, float HeightInit)
: Width(WidthInit), Height(HeightInit) {}
float Area() const { return Width * Height; }
private:
float Width, Height;
};
class triangle {
public:
triangle(float BaseInit, float HeightInit)
: Base(BaseInit), Height(HeightInit) {}
float Area() const { return 0.5f * Base * Height; }
private:
float Base, Height;
};
class circle {
public:
circle(float RadiusInit) : Radius(RadiusInit) {}
float Area() const { return utils::pi * Radius * Radius; }
private:
float Radius;
};
using any_shape = std::variant<square, rectangle, triangle, circle>;
inline std::vector<any_shape> shape_builder(std::size_t count) {
std::srand(std::time(nullptr));
std::vector<any_shape> shapes;
shapes.reserve(count);
for (std::size_t i = 0; i < count; i++) {
switch (std::rand() % 4) {
case 0:
shapes.push_back(square(utils::random_float()));
break;
case 1:
shapes.push_back(rectangle(utils::random_float(), utils::random_float()));
break;
case 2:
shapes.push_back(triangle(utils::random_float(), utils::random_float()));
break;
case 3:
shapes.push_back(circle(utils::random_float()));
break;
}
}
return shapes;
}
inline float shape_area(const any_shape &s) {
return std::visit([](const auto &shape) { return shape.Area(); }, s);
}
inline float total_area(const std::vector<any_shape> &shapes) {
float total_area{};
for (const auto &shape : shapes) {
total_area += shape_area(shape);
}
return total_area;
}
} // namespace variant
inline constexpr std::size_t shape_count = 1000;
static void clean_code(benchmark::State &state) {
const auto shapes = clean::shape_builder(shape_count);
for (auto _ : state) {
benchmark::DoNotOptimize(clean::total_area(shapes));
}
}
static void switch_case(benchmark::State &state) {
const auto shapes = switchcase::shape_builder(shape_count);
for (auto _ : state) {
benchmark::DoNotOptimize(switchcase::total_area(shapes));
}
}
static void std_variant(benchmark::State &state) {
const auto shapes = variant::shape_builder(shape_count);
for (auto _ : state) {
benchmark::DoNotOptimize(variant::total_area(shapes));
}
}
BENCHMARK(clean_code);
BENCHMARK(switch_case);
BENCHMARK(std_variant);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment