Temporal: add test program to evaluate performance of various ways of using int64_t atomically
This commit is contained in:
parent
56795a97a3
commit
3beffbd3ee
259
libs/temporal/test2.cc
Normal file
259
libs/temporal/test2.cc
Normal file
@ -0,0 +1,259 @@
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
static int loop_count = 10000000;
|
||||
|
||||
using namespace std;
|
||||
|
||||
int64_t
|
||||
get_microseconds ()
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
|
||||
/* EEEK! */
|
||||
return 0;
|
||||
}
|
||||
return (int64_t)ts.tv_sec * 1000000 + (ts.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
void
|
||||
single_atomic ()
|
||||
{
|
||||
struct alignas(16) thing {
|
||||
std::atomic<int64_t> v;
|
||||
thing() : v (0) { }
|
||||
};
|
||||
|
||||
thing t;
|
||||
int odd = 0;
|
||||
int64_t before = get_microseconds ();
|
||||
|
||||
for (int n = 0; n < loop_count; ++n) {
|
||||
t.v = random ();
|
||||
t.v = t.v + 1;
|
||||
if (t.v % 2) {
|
||||
odd++;
|
||||
}
|
||||
}
|
||||
int64_t after = get_microseconds ();
|
||||
std::cout << "odd: " << odd << " usecs = " << after - before << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
bitfields ()
|
||||
{
|
||||
struct alignas(16) thing {
|
||||
int b : 1;
|
||||
int64_t v : 62;
|
||||
thing() : b (0), v (0) {}
|
||||
thing (int bc, int64_t vc) : b (bc), v (vc) {}
|
||||
|
||||
thing operator+(int n) { return thing (b, v + n); }
|
||||
thing& operator=(thing const & other) { b = other.b; v = other.v; return *this; }
|
||||
};
|
||||
|
||||
thing t;
|
||||
int odd = 0;
|
||||
int64_t before = get_microseconds ();
|
||||
|
||||
for (int n = 0; n < loop_count; ++n) {
|
||||
t.v = random ();
|
||||
t.v = t.v + 1;
|
||||
if (t.v % 2) {
|
||||
odd++;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t after = get_microseconds ();
|
||||
std::cout << "odd: " << odd << " usecs = " << after - before << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
masks ()
|
||||
{
|
||||
struct alignas(16) thing {
|
||||
private:
|
||||
int64_t v;
|
||||
|
||||
bool is_beats() const { return v&(1LL<<62); }
|
||||
int64_t val() const { return v & ~(1LL<<62); }
|
||||
static int64_t build (bool bc, int64_t v) { return (bc ? (1LL<<62) : 0) | v; }
|
||||
|
||||
public:
|
||||
thing() : v (0) {}
|
||||
thing (bool bc, int64_t vc) : v (build (bc, vc)) {}
|
||||
|
||||
thing operator+(int n) const { return thing (is_beats(), val() + n); }
|
||||
thing& operator=(thing const & other) { v = other.v; return *this; }
|
||||
thing& operator+=(int64_t n) { v = build (is_beats(), val() + n); return *this; }
|
||||
thing& operator=(int64_t n) { v = build (is_beats(), n); return *this; }
|
||||
operator int64_t () const { return val(); }
|
||||
bool operator==(int64_t vv) const { return val() == vv; }
|
||||
};
|
||||
|
||||
thing t;
|
||||
int odd = 0;
|
||||
int64_t before = get_microseconds ();
|
||||
|
||||
for (int n = 0; n < loop_count; ++n) {
|
||||
t = random ();
|
||||
t = t + 1;
|
||||
if ((t % 2) == 0) {
|
||||
odd++;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t after = get_microseconds ();
|
||||
std::cout << "odd: " << odd << " usecs = " << after - before << std::endl;
|
||||
}
|
||||
|
||||
#include "pbd/int62.h"
|
||||
|
||||
void
|
||||
atomic_masks ()
|
||||
{
|
||||
|
||||
int62_t t;
|
||||
int odd = 0;
|
||||
int64_t before = get_microseconds ();
|
||||
|
||||
for (int n = 0; n < loop_count; ++n) {
|
||||
t = random ();
|
||||
if ((t.val() % 2LL) == 0LL) {
|
||||
odd++;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t after = get_microseconds ();
|
||||
std::cout << "odd: " << odd << " usecs = " << after - before << std::endl;
|
||||
|
||||
int62_t x;
|
||||
|
||||
x = 1;
|
||||
cerr << "should be 1: " << x.val() << endl;
|
||||
x -= 1;
|
||||
cerr << "should be 0: " << x.val() << endl;
|
||||
x -= 1;
|
||||
cerr << "should be -1: " << x.val() << endl;
|
||||
|
||||
x = int62_t::build (false, int62_t::min);
|
||||
cerr << "should be " << int62_t::min << ' ' << x.val() << endl;
|
||||
|
||||
x = int62_t::build (true, int62_t::min);
|
||||
cerr << "should still be " << int62_t::min << ' ' << x.val() << " and also flag: " << x.flagged() << endl;
|
||||
x += -x;
|
||||
cerr << "invert+add should be zero: " << x.val() << " and also flag: " << x.flagged() << endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_ints ()
|
||||
{
|
||||
int62_t i62;
|
||||
int64_t i64 (0);
|
||||
int64_t arg;
|
||||
int64_t old62;
|
||||
int64_t old64;
|
||||
int skips = 0;
|
||||
|
||||
for (int n = 0; n < loop_count; ++n) {
|
||||
|
||||
arg = random();
|
||||
old62 = i62.val();
|
||||
old64 = i64;
|
||||
|
||||
char opchar;
|
||||
int op = random() % 4;
|
||||
|
||||
switch (op) {
|
||||
case 0:
|
||||
if (INT64_MAX - arg >= i64) {
|
||||
i64 += arg;
|
||||
if (i64 <= std::numeric_limits<int62_t>::max() && i64 >= std::numeric_limits<int62_t>::min()) {
|
||||
i62 += arg;
|
||||
} else {
|
||||
i64 = old64;
|
||||
skips++;
|
||||
}
|
||||
}
|
||||
opchar = '+';
|
||||
break;
|
||||
case 1:
|
||||
if (INT64_MIN + arg <= i64) {
|
||||
i64 -= arg;
|
||||
if (i64 <= std::numeric_limits<int62_t>::max() && i64 >= std::numeric_limits<int62_t>::min()) {
|
||||
i62 -= arg;
|
||||
} else {
|
||||
i64 = old64;
|
||||
skips++;
|
||||
}
|
||||
}
|
||||
opchar = '-';
|
||||
break;
|
||||
case 2:
|
||||
if (arg == 0) {
|
||||
i64 = 0;
|
||||
i62 = 0;
|
||||
} else {
|
||||
if (INT64_MAX / arg > i64) {
|
||||
i64 *= arg;
|
||||
if (i64 <= std::numeric_limits<int62_t>::max() && i64 >= std::numeric_limits<int62_t>::min()) {
|
||||
i62 *= arg;
|
||||
} else {
|
||||
i64 = old64;
|
||||
skips++;
|
||||
}
|
||||
}
|
||||
}
|
||||
opchar = '*';
|
||||
break;
|
||||
case 3:
|
||||
|
||||
if (arg == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i64 /= arg;
|
||||
if (i64 <= std::numeric_limits<int62_t>::max() && i64 >= std::numeric_limits<int62_t>::min()) {
|
||||
i62 /= arg;
|
||||
} else {
|
||||
i64 = old64;
|
||||
skips++;
|
||||
}
|
||||
opchar = '/';
|
||||
break;
|
||||
}
|
||||
|
||||
if (i62.val() != i64) {
|
||||
cerr << "failure after " << n << " op = " << opchar << " arg " << arg << " old was " << old62 << " cur " << i62.val() << " vs. " << i64 << " whose old was " << old64 << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// cerr << old64 << ' ' << opchar << ' ' << arg << " = " << i64 << endl;
|
||||
}
|
||||
|
||||
cerr << "Had to skip " << skips << " of " << loop_count << endl;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
if (argc > 1) {
|
||||
loop_count = atoi (argv[1]);
|
||||
}
|
||||
|
||||
srandom (time ((time_t *) 0));
|
||||
|
||||
//single_atomic ();
|
||||
//bitfields ();
|
||||
//masks ();
|
||||
atomic_masks ();
|
||||
test_ints ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user