Adds finer-grain GC
[junction.git] / test / junction_driver.cpp
1 #include <junction/ConcurrentMap_Grampa.h>
2 #include <junction/ConcurrentMap_Linear.h>
3 #include <junction/ConcurrentMap_Leapfrog.h>
4 #include <junction/ConcurrentMap_Crude.h>
5 #include <iostream>
6 #include <memory>
7 #include <chrono>
8 #include <cassert>
9
10 namespace {
11
12 const unsigned s_nInsertPercentage = 10;
13 const char* kTestName = "InsDelFind";
14 // Run GC after "kGCFrequency" operations.
15 const size_t kGCFrequency = 3000;
16
17 const size_t kCrudeMapSize = 10000;
18 const size_t kCrudePassCount = 40000;
19 const char* kCrudeBenchmarkName = "JunctionMapCrude";
20
21 const size_t kGrampaMapSize = 20000;
22 const size_t kGrampaPassCount = 30000;
23 const char* kGrampaBenchmarkName = "JunctionMapGrampa";
24
25 const size_t kLinearMapSize = 20000;
26 const size_t kLinearPassCount = 70000;
27 const char* kLinearBenchmarkName = "JunctionMapLinear";
28
29 const size_t kLeapfrogMapSize = 20000;
30 const size_t kLeapfrogPassCount = 75000;
31 const char* kLeapfrogBenchmarkName = "JunctionMapLeapfrog";
32
33 } // namespace
34
35 typedef junction::ConcurrentMap_Grampa<size_t, size_t> GrampaMap;
36 typedef junction::ConcurrentMap_Linear<size_t, size_t> LinearMap;
37 typedef junction::ConcurrentMap_Leapfrog<size_t, size_t> LeapfrogMap;
38 typedef junction::ConcurrentMap_Crude<size_t, size_t> CrudeMap;
39
40 template <typename Map>
41 void run_crude_map(size_t map_size, size_t pass_count, const char* bench_name) {
42     std::cout << "[ RUN      ] " << kTestName << "." << bench_name << "\n";
43     auto start_time = std::chrono::system_clock::now();
44
45     size_t nInsertedNum = 0;
46     size_t nFindSuccess = 0;
47     size_t nOperations = 0;
48     // Seems like the crude map won't resize, so better have a large enough
49     // capacity.
50     std::unique_ptr<Map> map(new Map(map_size * 32));
51     auto qsbrContext = junction::DefaultQSBR.createContext();
52     for (size_t count = 0; count < pass_count; count++) {
53         for (size_t i = 0; i < map_size; ++i) {
54             // The number to operate on the map.
55             size_t n = map_size + i;
56             // Insert
57             if (i % s_nInsertPercentage == 1) {
58                 map->assign(i, n);
59                 nInsertedNum++;
60 //                std::cout << "Inserted" << i << "\n";
61             }
62             // Find
63             {
64                 if (map->get(i)) {
65                     ++nFindSuccess;
66 //                    std::cout << "Found" << i << "\n";
67                 }
68             }
69             // Delete
70             if (i % s_nInsertPercentage == 1) {
71                 if (map->get(i)) {
72                     map->assign(n, 0);
73 //                    std::cout << "Erased" << i << "\n";
74                 }
75             }
76             if (++nOperations > kGCFrequency) {
77               junction::DefaultQSBR.update(qsbrContext);
78               nOperations = 0;
79             }
80         }
81     }
82     junction::DefaultQSBR.update(qsbrContext);
83     auto finish_time = std::chrono::system_clock::now();
84     auto dur = finish_time - start_time;
85     auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
86
87     if (nFindSuccess != nInsertedNum) {
88         std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
89                   << nInsertedNum << "\n";
90         std::cout << "[       FAILED ] " << kTestName << "." << bench_name
91                   << "(" << milisecs.count() << " ms)\n";
92         assert(false && "ConcurrentMap ERROR");
93     } else {
94         std::cout << "[       OK ] " << kTestName << "." << bench_name
95                   << "(" << milisecs.count() << " ms)\n";
96     }
97 }
98
99 template <typename Map>
100 void run_test(size_t map_size, size_t pass_count, const char* bench_name) {
101     std::cout << "[ RUN      ] " << kTestName << "." << bench_name << "\n";
102     auto start_time = std::chrono::system_clock::now();
103
104     size_t nInsertedNum = 0;
105     size_t nFindSuccess = 0;
106     size_t nOperations = 0;
107     std::unique_ptr<Map> map(new Map());
108     auto qsbrContext = junction::DefaultQSBR.createContext();
109     for (size_t count = 0; count < pass_count; count++) {
110         for (size_t i = 0; i < map_size; ++i) {
111             // The number to operate on the map.
112             size_t n = map_size + i;
113             // Insert
114             if (i % s_nInsertPercentage == 1) {
115                 auto iter = map->insertOrFind(i);
116                 if (!iter.getValue()) {
117                   iter.assignValue(n);
118                   nInsertedNum++;
119 //                  std::cout << "Inserted" << i << "\n";
120                 }
121             }
122             // Find
123             {
124                 auto iter = map->find(i);
125                 if (iter.getValue()) {
126                     ++nFindSuccess;
127 //                    std::cout << "Found" << i << "\n";
128                 }
129             }
130             // Delete
131             if (i % s_nInsertPercentage == 1) {
132                 auto iter = map->find(i);
133                 if (iter.getValue()) {
134                     iter.eraseValue();
135 //                    std::cout << "Erased" << i << "\n";
136                 }
137             }
138             if (++nOperations > kGCFrequency) {
139                 junction::DefaultQSBR.update(qsbrContext);
140                 nOperations = 0;
141             }
142         }
143     }
144     auto finish_time = std::chrono::system_clock::now();
145     auto dur = finish_time - start_time;
146     auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
147
148     if (nFindSuccess != nInsertedNum) {
149         std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
150                   << nInsertedNum << "\n";
151         std::cout << "[       FAILED ] " << kTestName << "." << bench_name
152                   << "(" << milisecs.count() << " ms)\n";
153         assert(false && "ConcurrentMap ERROR");
154     } else {
155         std::cout << "[       OK ] " << kTestName << "." << bench_name
156                   << "(" << milisecs.count() << " ms)\n";
157     }
158 }
159
160 int main() {
161     run_test<LinearMap>(kLinearMapSize, kLinearPassCount, kLinearBenchmarkName);
162     run_test<LeapfrogMap>(kLeapfrogMapSize, kLeapfrogPassCount, kLeapfrogBenchmarkName);
163     run_test<GrampaMap>(kGrampaMapSize, kGrampaPassCount, kGrampaBenchmarkName);
164     run_crude_map<CrudeMap>(kCrudeMapSize, kCrudePassCount, kCrudeBenchmarkName);
165     return 0;
166 }