diff --git a/src/Makefile.am b/src/Makefile.am index 9778194..dd599d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 += -fno-elide-constructors -Weffc++ -bin_PROGRAMS := ch01ex01 ch01ex03 ch01ex04 ch01ex05 ch01ex06 +bin_PROGRAMS := ch01ex01 ch01ex03 ch01ex04 ch01ex05 ch01ex06 \ + list_bench ch01ex01_SOURCES := ch01ex01.cc ch01ex03_SOURCES := ch01ex03.cc ch01ex04_SOURCES := ch01ex04.cc ch01ex05_SOURCES := ch01ex05.cc ch01ex06_SOURCES := ch01ex06.cc +list_bench_SOURCES := list_bench.cc diff --git a/src/ch01ex06.cc b/src/ch01ex06.cc index 1b5961a..a83b0e5 100644 --- a/src/ch01ex06.cc +++ b/src/ch01ex06.cc @@ -14,7 +14,7 @@ check_simplist(void) sl.add(1, 2); sl.add(2, 3); assert(sl.size() == 3); - + sl.add(0, 4); sl.add(1, 5); sl.add(2, 6); diff --git a/src/list_bench.cc b/src/list_bench.cc new file mode 100644 index 0000000..8811a9f --- /dev/null +++ b/src/list_bench.cc @@ -0,0 +1,130 @@ +// list_bench runs benchmarks against List implementations. +#include +#include +#include +#include +#include +#include +#include +#include + +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 dist(low, high); + return dist(rng); +} + +static int +randsizet(size_t low, size_t high) +{ + uniform_int_distribution dist(low, high); + return dist(rng); +} + +static void +benchmark(ods::List& 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& list, int ops) +{ + std::chrono::steady_clock clock; + + auto start = clock.now(); + benchmark(list, ops); + auto stop = clock.now(); + + std::chrono::duration 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 sl; + run("SimpList", sl, ops); + + ods::VList vl; + run("VList", vl, ops); +} \ No newline at end of file diff --git a/src/ods/simplist.h b/src/ods/simplist.h index f832aae..9b8fb37 100644 --- a/src/ods/simplist.h +++ b/src/ods/simplist.h @@ -9,7 +9,7 @@ namespace ods { template -class SimpList : List { +class SimpList : public List { public: SimpList(); ~SimpList(void); diff --git a/src/ods/simpuset.h b/src/ods/simpuset.h index f9066e4..73ea284 100644 --- a/src/ods/simpuset.h +++ b/src/ods/simpuset.h @@ -8,7 +8,7 @@ namespace ods { template -class SimpUSet : USet { +class SimpUSet : public USet { public: SimpUSet(void); ~SimpUSet(void); diff --git a/src/ods/vlist.h b/src/ods/vlist.h new file mode 100644 index 0000000..a9988b9 --- /dev/null +++ b/src/ods/vlist.h @@ -0,0 +1,78 @@ +#ifndef __ODS_ODS_VLIST__ +#define __ODS_ODS_VLIST__ + + +#include +#include +#include +#include + +namespace ods { + +// VList implements a vector-based list interface. +template +class VList : public List { +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 vec; +}; + +template +VList::~VList() +{ + this->vec.clear(); +} + +template +std::size_t +VList::size() +{ + return this->vec.size(); +} + +template +T +VList::get(std::size_t i) +{ + return this->vec.at(i); +} + +template +T +VList::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 +void +VList::add(std::size_t i, T value) +{ + auto p = this->vec.begin() + i; + this->vec.insert(p, value); +} + +template +T +VList::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__ \ No newline at end of file