/* Copyright (c) 2013 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #include #include #include "test.h" #include "pvector.h" #include "timeit.h" using namespace lean; // #define PVECTOR_PERF_TEST static void tst1() { pvector v; lean_assert(v.empty()); v.push_back(10); lean_assert(v.size() == 1); lean_assert(v.back() == 10); v.set(0, 20); lean_assert(v.back() == 20); v.pop_back(); lean_assert(v.size() == 0); v.push_back(10); v.push_back(20); pvector v2(v); lean_assert(v2.size() == 2); v2.push_back(30); lean_assert(v.size() == 2); lean_assert(v2.size() == 3); v2.pop_back(); lean_assert(v.size() == 2); v2.set(1, 100); lean_assert(v[1] == 20); lean_assert(v2[1] == 100); for (unsigned i = 0; i < 100; i++) v2.push_back(i); } template bool operator==(pvector v1, std::vector const & v2) { if (v1.size() != v2.size()) return false; for (unsigned i = 0; i < v1.size(); i++) { if (v1[i] != v2[i]) return false; } return true; } static void driver(unsigned max_sz, unsigned max_val, unsigned num_ops, double push_freq, double copy_freq) { std::vector v1; pvector v2; std::vector> copies; for (unsigned i = 0; i < num_ops; i++) { double f = static_cast(std::rand() % 10000) / 10000.0; if (f < copy_freq) copies.push_back(v2); f = static_cast(std::rand() % 10000) / 10000.0; if (f < push_freq) { if (v1.size() >= max_sz) continue; int a = std::rand() % max_val; v1.push_back(a); v2.push_back(a); } else { if (v1.size() == 0) continue; lean_assert(v1.back() == v2.back()); v1.pop_back(); v2.pop_back(); } lean_assert(v2 == v1); } std::cout << "Copies created: " << copies.size() << "\n"; } static void tst2() { driver(4, 32, 10000, 0.5, 0.01); driver(4, 32, 10000, 0.5, 0.1); driver(2, 32, 10000, 0.8, 0.4); driver(2, 32, 10000, 0.3, 0.5); driver(4, 32, 10000, 0.3, 0.7); driver(16, 32, 10000, 0.5, 0.1); driver(16, 32, 10000, 0.5, 0.01); driver(16, 32, 10000, 0.5, 0.5); driver(16, 32, 10000, 0.7, 0.1); driver(16, 32, 10000, 0.7, 0.5); driver(16, 32, 10000, 0.7, 0.01); driver(16, 32, 10000, 0.1, 0.5); driver(16, 32, 10000, 0.8, 0.2); driver(128, 1000, 10000, 0.5, 0.5); driver(128, 1000, 10000, 0.5, 0.01); driver(128, 1000, 10000, 0.5, 0.1); driver(128, 1000, 10000, 0.2, 0.5); driver(128, 1000, 10000, 0.2, 0.01); driver(128, 1000, 10000, 0.2, 0.1); } static void tst3() { timeit t(std::cout, "tst3"); unsigned N = 20000; unsigned M = 20000; pvector v; for (unsigned i = 0; i < N; i++) v.push_back(i); pvector v2 = v; for (unsigned i = 0; i < N / 2; i++) v2.push_back(i); // v2 has a long trail of deltas // Now, we only read v2 unsigned s = 0; for (unsigned i = 0; i < M; i++) { s += v2[i % v2.size()]; } } #ifdef PVECTOR_PERF_TEST static void perf_vector(unsigned n) { std::vector q; for (unsigned i = 0; i < n; i++) { q.push_back(i); } for (unsigned i = 0; i < n; i++) { q.pop_back(); } } static void perf_pvector(unsigned n) { pvector q; for (unsigned i = 0; i < n; i++) { q.push_back(i); } for (unsigned i = 0; i < n; i++) { q.pop_back(); } } static void tst_perf1() { unsigned N = 100000; unsigned M = 100; { timeit t(std::cout, "vector time"); for (unsigned i = 0; i < N; i++) perf_vector(M); } { timeit t(std::cout, "pvector time"); for (unsigned i = 0; i < N; i++) perf_pvector(M); } } static void perf_vector2(std::vector q, unsigned n) { for (unsigned i = 0; i < n; i++) { q.push_back(i); } for (unsigned i = 0; i < n; i++) { q.pop_back(); } } static void perf_pvector2(pvector q, unsigned n) { for (unsigned i = 0; i < n; i++) { q.push_back(i); } for (unsigned i = 0; i < n; i++) { q.pop_back(); } } static void tst_perf2() { unsigned N = 100000; unsigned SZ1 = 10000; unsigned M = 10; { timeit t(std::cout, "vector time"); std::vector q; for (unsigned i = 0; i < SZ1; i++) { q.push_back(i); } for (unsigned i = 0; i < N; i++) perf_vector2(q, M); } { timeit t(std::cout, "pvector time"); pvector q; for (unsigned i = 0; i < SZ1 + 1; i++) { q.push_back(i); } for (unsigned i = 0; i < N; i++) perf_pvector2(q, M); } } #endif int main() { tst1(); tst2(); tst3(); #ifdef PVECTOR_PERF_TEST tst_perf1(); tst_perf2(); #endif return has_violations() ? 1 : 0; }