Thiago Adams
unread,Jun 29, 2020, 7:03:40 AM6/29/20You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
I did a performance test comparing a tagged union in C
against std::variant.
C was faster in my tests.
Here is the complete code for C and C++ in case someone wants
to check the C++ version.
#define MAXCOUNT 10000000
#ifndef __cplusplus
//C version
#include <assert.h>
#include <stdio.h>
#include <time.h>
struct circle {
double radius;
};
#define CIRCLE_TAG 1
struct square {
double side;
};
#define SQUARE_TAG 2
struct rectangle {
double width;
double height;
};
#define RECTANGLE_TAG 3
struct shape {
int tag;
union {
struct circle circle;
struct square square;
struct rectangle rectangle;
};
};
double shape_area(struct shape* s) {
switch (s->tag) {
case CIRCLE_TAG:
return 3.14 * s->circle.radius * s->circle.radius;
case SQUARE_TAG:
return s->square.side * s->square.side;
case RECTANGLE_TAG:
return s->rectangle.width * s->rectangle.height;
default:
assert(0);
break;
}
return 0;
}
int run_test(const char* message, int (*test)(void)) {
time_t start = clock();
int r = test();
printf("%s %d\n", message, (int)(clock() - start));
return r;
}
void TestC() {}
int main() {
struct shape s[] = {
{.tag = CIRCLE_TAG, .circle.radius = 5},
{.tag = SQUARE_TAG, .square.side = 2},
{.tag = RECTANGLE_TAG, .rectangle.width = 4, .rectangle.height = 5},
{.tag = CIRCLE_TAG, .circle.radius = 5},
{.tag = SQUARE_TAG, .square.side = 2},
{.tag = RECTANGLE_TAG, .rectangle.width = 4, .rectangle.height = 5},
{.tag = CIRCLE_TAG, .circle.radius = 5},
{.tag = SQUARE_TAG, .square.side = 2},
{.tag = RECTANGLE_TAG, .rectangle.width = 4, .rectangle.height = 5} };
double area = 0;
time_t start = clock();
for (int j = 0; j < MAXCOUNT; j++) {
area = 0;
for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++) {
area += shape_area(&s[i]);
}
}
printf("%d\n", (int)(clock() - start));
printf("%f", area);
return 0;
}
#else
//C++ version
#include <ctime>
#include <iostream>
#include <memory>
#include <variant>
#include <vector>
struct circle {
circle(double const radius_) : radius(radius_) {}
double radius;
};
struct square {
square(double const side_) : side(side_) {}
double side;
};
struct rectangle {
rectangle(double width_, double height_)
: width(width_), height(height_) {}
double width;
double height;
};
double area(circle const& c) {
return 3.14 * c.radius * c.radius;
}
double area(square const& s) {
return s.side * s.side;
}
double area(rectangle const& r) {
return r.width * r.height;
}
using shape = std::variant<circle, square, rectangle>;
int main() {
shape shapes[] = { circle(5), square(2), rectangle(4, 5),
circle(5), square(2), rectangle(4, 5),
circle(5), square(2), rectangle(4, 5) };
double total_area = 0;
time_t start = clock();
for (int j = 0; j < MAXCOUNT; j++) {
total_area = 0;
for (int i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++) {
std::visit([&](auto const& shape) { total_area += area(shape); },
shapes[i]);
}
}
printf("time: %d\n\n", (int)(clock() - start));
std::cout << "Area total: " << total_area << std::endl;
return 0;
}
#endif