Add List benchmark.

This commit is contained in:
Kyle Isom 2017-12-21 15:41:20 -08:00
parent 89ea1fadf2
commit 8eb4ec4274
6 changed files with 214 additions and 4 deletions

View File

@ -3,9 +3,11 @@ AM_CPPFLAGS += -Wwrite-strings -Wmissing-declarations -Wno-long-long -Werror
AM_CPPFLAGS += -Wunused-variable -std=c++17 -D_XOPEN_SOURCE -O0 -g -I. AM_CPPFLAGS += -Wunused-variable -std=c++17 -D_XOPEN_SOURCE -O0 -g -I.
AM_CPPFLAGS += -fno-elide-constructors -Weffc++ AM_CPPFLAGS += -fno-elide-constructors -Weffc++
bin_PROGRAMS := ch01ex01 ch01ex03 ch01ex04 ch01ex05 ch01ex06 bin_PROGRAMS := ch01ex01 ch01ex03 ch01ex04 ch01ex05 ch01ex06 \
list_bench
ch01ex01_SOURCES := ch01ex01.cc ch01ex01_SOURCES := ch01ex01.cc
ch01ex03_SOURCES := ch01ex03.cc ch01ex03_SOURCES := ch01ex03.cc
ch01ex04_SOURCES := ch01ex04.cc ch01ex04_SOURCES := ch01ex04.cc
ch01ex05_SOURCES := ch01ex05.cc ch01ex05_SOURCES := ch01ex05.cc
ch01ex06_SOURCES := ch01ex06.cc ch01ex06_SOURCES := ch01ex06.cc
list_bench_SOURCES := list_bench.cc

View File

@ -14,7 +14,7 @@ check_simplist(void)
sl.add(1, 2); sl.add(1, 2);
sl.add(2, 3); sl.add(2, 3);
assert(sl.size() == 3); assert(sl.size() == 3);
sl.add(0, 4); sl.add(0, 4);
sl.add(1, 5); sl.add(1, 5);
sl.add(2, 6); sl.add(2, 6);

130
src/list_bench.cc Normal file
View File

@ -0,0 +1,130 @@
// list_bench runs benchmarks against List implementations.
#include <cassert>
#include <chrono>
#include <iostream>
#include <random>
#include <string>
#include <ods/list.h>
#include <ods/simplist.h>
#include <ods/vlist.h>
using namespace std;
static mt19937 rng;
static random_device devrand;
// reseed picks a new seed for the RNG using the system random device.
static void
reseed()
{
rng.seed(devrand());
}
static int
randint(int low, int high)
{
uniform_int_distribution<int> dist(low, high);
return dist(rng);
}
static int
randsizet(size_t low, size_t high)
{
uniform_int_distribution<size_t> dist(low, high);
return dist(rng);
}
static void
benchmark(ods::List<int>& list, int ops)
{
for (int i = 0; i < ops; i++) {
auto op = randint(0, 3);
size_t j = 0;
int newval, oldval;
if (list.size() > 0) {
j = randsizet(0, list.size()-1);
}
switch (op) {
// get
case 0:
if (list.size() == 0) {
i--;
continue;
}
cout << "\tget " << j << endl;
assert(list.get(j) != -1);
// set
case 1:
if (list.size() == 0) {
i--;
continue;
}
oldval = list.get(j);
newval = oldval;
while (newval == oldval) {
newval = randint(1, 1000000);
}
cout << "\tset " << j << " from " << oldval << " to " << newval << endl;
assert(list.set(j, newval) == oldval);
assert(list.get(j) == newval);
break;
// add
case 2:
newval = randint(1, 1000000);
list.add(j, newval);
cout << "\tadd " << j << " " << newval << endl;
assert(list.get(j) == newval);
break;
// remove
case 3:
if (list.size() == 0) {
i--;
continue;
}
auto old_size = list.size();
cout << "\tremove " << j << endl;
list.remove(j);
assert(list.size() == (old_size-1));
break;
}
}
}
static void
run(string label, ods::List<int>& list, int ops)
{
std::chrono::steady_clock clock;
auto start = clock.now();
benchmark(list, ops);
auto stop = clock.now();
std::chrono::duration<double> delta = stop - start;
cerr << label << " @ " << ops << " ops: " << delta.count() << "s" << endl;
}
int
main(int argc, char *argv[])
{
int ops = 1000;
if (argc == 2) {
ops = stoi(argv[1]);
}
reseed();
ods::SimpList<int> sl;
run("SimpList", sl, ops);
ods::VList<int> vl;
run("VList", vl, ops);
}

View File

@ -9,7 +9,7 @@
namespace ods { namespace ods {
template<typename T> template<typename T>
class SimpList : List<T> { class SimpList : public List<T> {
public: public:
SimpList(); SimpList();
~SimpList(void); ~SimpList(void);

View File

@ -8,7 +8,7 @@
namespace ods { namespace ods {
template<typename T> template<typename T>
class SimpUSet : USet<T> { class SimpUSet : public USet<T> {
public: public:
SimpUSet(void); SimpUSet(void);
~SimpUSet(void); ~SimpUSet(void);

78
src/ods/vlist.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef __ODS_ODS_VLIST__
#define __ODS_ODS_VLIST__
#include <cstdlib>
#include <optional>
#include <vector>
#include <ods/list.h>
namespace ods {
// VList implements a vector-based list interface.
template<typename T>
class VList : public List<T> {
public:
~VList(void);
std::size_t size(void);
T get(std::size_t);
T set(std::size_t, T);
void add(std::size_t, T);
T remove(std::size_t);
private:
std::vector<T> vec;
};
template<typename T>
VList<T>::~VList()
{
this->vec.clear();
}
template<typename T>
std::size_t
VList<T>::size()
{
return this->vec.size();
}
template<typename T>
T
VList<T>::get(std::size_t i)
{
return this->vec.at(i);
}
template<typename T>
T
VList<T>::set(size_t i, T value)
{
auto p = this->vec.begin() + i;
T old = this->vec.at(i);
this->vec.erase(p);
this->vec.insert(p, value);
return old;
}
template<typename T>
void
VList<T>::add(std::size_t i, T value)
{
auto p = this->vec.begin() + i;
this->vec.insert(p, value);
}
template<typename T>
T
VList<T>::remove(std::size_t i)
{
auto removed = this->vec.at(i);
auto p = this->vec.begin() + i;
this->vec.erase(p);
return removed;
}
} // namespace ods
#endif // __ODS_ODS_VLIST__