1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 //
19 // C++ Implementation: bcTest
20 //
21 // Description: A simple Test driver for the Disk Block Buffer Cache
22 //
23 // Author: Jason Rodriguez <jrodriguez@calpont.com>, (C) 2007
24 //
25 //
26
27 #include <vector>
28 #include <string>
29 #include <iomanip>
30 #include <iostream>
31 #include <sys/time.h>
32 #include <unistd.h>
33 #include <boost/thread/thread.hpp>
34
35 #include "blockrequestprocessor.h"
36 #include "blockcacheclient.h"
37 #include "stats.h"
38 #include "brm.h"
39 #include "logger.h"
40 #include "iomanager.h"
41
42 using namespace BRM;
43 using namespace dbbc;
44 using namespace std;
45 using namespace logging;
46 using namespace primitiveprocessor;
47
48 Stats* gPMStatsPtr = NULL;
49 bool gPMProfOn = false;
50 uint32_t gSession = 0;
51 uint32_t lastRangeListIdx = 0;
52 const uint32_t maxLoadBlocks(1024 * 1024);
53
timespec_sub(const struct timespec & tv1,const struct timespec & tv2,double & tm)54 void timespec_sub(const struct timespec& tv1,
55 const struct timespec& tv2,
56 double& tm)
57 {
58 tm = (double)(tv2.tv_sec - tv1.tv_sec) + 1.e-9 * (tv2.tv_nsec - tv1.tv_nsec);
59 }
60
61 namespace primitiveprocessor
62 {
63 Logger ml;
64 }
65
66
67 class BCTest
68 {
69
70 public:
71
72 struct OidRanges
73 {
74 OID_t oid;
75 HWM_t hwm;
76 LBIDRange_v ranges;
OidRangesBCTest::OidRanges77 OidRanges(const OID_t o, const HWM_t h, const LBIDRange_v r)
78 {
79 oid = o;
80 hwm = h;
81 ranges = r;
82 }
83 }; //struct OidRanges
84
85 BCTest(const int cacheSz = 64 * 1024, int readThr = 2, int readAhead = 1024);
86
87 typedef OidRanges OidRanges_t;
88 typedef vector<OidRanges_t>OidRangesList_t;
89 OidRangesList_t OidRangesList;
90
91 DBRM dbrm;
92 uint32_t extentSize;
93 BRM::OID_t maxOid;
94
95 int fCacheSz;
96 int fReadThr;
97 int fReadAhead;
98 uint32_t maxBlocksAvailable;
99 uint32_t fExtentSize;
100
101 void setUp();
102 int LoadOid(const OidRanges_t& o, uint32_t& loadCount);
103 void LoadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver);
104 int ReadOidRanges(const OidRanges_t& v, uint32_t* hits, uint32_t* miss);
105 void ReadOidLbids(const BRM::LBID_t lbid, const BRM::VER_t ver);
106
107 BlockRequestProcessor BRP;
108
109 }; // class BCTest
110
111
BCTest(int cacheSz,int readThr,int readAhead)112 BCTest::BCTest(int cacheSz, int readThr, int readAhead) :
113 fCacheSz(cacheSz),
114 fReadThr(readThr),
115 fReadAhead(readAhead),
116 BRP(fCacheSz, fReadThr, fReadAhead)
117 {
118 setUp();
119 } // ctor
120
121 //
setUp()122 void BCTest::setUp()
123 {
124 LBIDRange_v r;
125 HWM_t hwm;
126 OID_t oid = 1000;
127 extentSize = dbrm.getExtentSize();
128 maxBlocksAvailable = 0;
129 int i = 0;
130 fExtentSize = dbrm.getExtentSize();
131
132 while ( oid < 5000 )
133 {
134 int ret = 0;
135 ret = dbrm.lookup(oid, r);
136
137 if (ret == 0 && r.size() > 0)
138 {
139 dbrm.getHWM(oid, hwm);
140 maxBlocksAvailable += (r.size() * extentSize);
141 OidRanges_t oid_range(oid, hwm, r);
142 OidRangesList.push_back(oid_range);
143 //cout << "Setup i: " << i++ << " o: " << oid
144 // << " r: " << ret << " s: " << r.size()
145 // << " m: " << maxBlocksAvailable
146 // << endl;
147 hwm = 0;
148 r.clear();
149 }
150
151 oid++;
152 }
153
154 //cout << "\t" << OidRangesList.size() << " oid ranges loaded " << endl << endl;
155 i = 0;
156 } // setUp()
157
LoadOid(const OidRanges_t & o,uint32_t & loadCount)158 int BCTest::LoadOid(const OidRanges_t& o, uint32_t& loadCount)
159 {
160 blockCacheClient bc(BRP);
161 uint32_t rCount = 0;
162
163 for (uint32_t i = 0; i < o.ranges.size() ; i++)
164 {
165 const InlineLBIDRange r = {o.ranges[i].start, o.ranges[i].size};
166
167 if (r.size > 0)
168 {
169 bc.check(r, 0, rCount);
170 //cout << "i: " << i << " c: " << rCount << " " << o.ranges[i].size << endl;
171 loadCount += rCount;
172 }
173
174 rCount = 0;
175 } // for
176
177 //cout << "hwm: " << o.hwm << " tot: " << loadCount << " " << o.ranges.size() << endl;
178
179 return loadCount;
180
181 } // LoadOid
182
ReadOidRanges(const OidRanges_t & v,uint32_t * hits,uint32_t * miss)183 int BCTest::ReadOidRanges(const OidRanges_t& v, uint32_t* hits, uint32_t* miss)
184 {
185
186 blockCacheClient bc(BRP);
187 uint32_t readBlocks = 0;
188 uint32_t missBlocks = 0;
189 uint8_t inBuff[8192];
190 int ret;
191
192 for (uint32_t i = 0; i < v.ranges.size() && i < lastRangeListIdx; i++)
193 {
194 FileBuffer fb(-1, -1);
195 const InlineLBIDRange r = {v.ranges[i].start, v.ranges[i].size};
196
197 for (int j = r.start; j < r.start + r.size; j++)
198 {
199 ret = bc.read(j, 0, fb);
200 FileBuffer* ptr = bc.getBlockPtr(j, 0);
201
202 if (ptr)
203 {
204 readBlocks++;
205 memcpy(inBuff, ptr->getData(), 8192);
206 }
207 else
208 missBlocks++;
209 }
210
211 *hits += readBlocks;
212 *miss += missBlocks;
213
214 //cout << " -- Read range idx: " << i << " hits: " << readBlocks << " miss: " << missBlocks << " hwm: " << v.hwm << endl;
215 }
216
217 return readBlocks;
218
219 } // ReadRange
220
221 // add one block to block cache
222 //
LoadLbid(const BRM::LBID_t lbid,const BRM::VER_t ver)223 void BCTest::LoadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver)
224 {
225 blockCacheClient bc(BRP);
226 bool b;
227 bc.check(lbid, ver, false, b);
228 } // LoadLbid
229
230 // get one block out of block cache
231 //
ReadOidLbids(const BRM::LBID_t lbid,const BRM::VER_t ver)232 void BCTest::ReadOidLbids(const BRM::LBID_t lbid, const BRM::VER_t ver)
233 {
234 uint8_t d[8192] = {'\0'};
235 blockCacheClient bc(BRP);
236 bc.read(lbid, ver, d);
237 } // ReadLbid
238
239
240 struct loadThr
241 {
loadThrloadThr242 loadThr(BCTest& bc, int reps = 1) : fBC(bc), fReps(reps)
243 {
244 }
245
operator ()loadThr246 void operator()()
247 {
248 uint32_t loadedBlocks = 0;
249 uint32_t oidBlocks;
250 uint32_t i = 0;
251 uint32_t rc = 0;
252 struct timespec tm1;
253 struct timespec tm2;
254
255 tm1.tv_sec = 0;
256 tm1.tv_nsec = 0;
257 tm2.tv_sec = 0;
258 tm2.tv_nsec = 0;
259 double tm3 = 0;
260 clock_gettime(CLOCK_REALTIME, &tm1);
261
262 for (i = 0; (loadedBlocks + (fBC.OidRangesList[i].ranges.size()*fBC.extentSize)) < fBC.fCacheSz && i < fBC.OidRangesList.size(); i++)
263 {
264 oidBlocks = 0;
265 rc = fBC.LoadOid(fBC.OidRangesList[i], oidBlocks);
266 //cout
267 // << "-- Load " << i << " " << fBC.OidRangesList[i].oid
268 // << " h: " << fBC.OidRangesList[i].hwm
269 // << "/" << oidBlocks << " " << loadedBlocks
270 // << endl;
271 loadedBlocks += oidBlocks;
272 } // for (i...
273
274 lastRangeListIdx = i;
275
276 clock_gettime(CLOCK_REALTIME, &tm2);
277 timespec_sub(tm1, tm2, tm3);
278
279 cout << "load ld: " << loadedBlocks
280 << " sz: " << fBC.fCacheSz
281 << " rng: " << lastRangeListIdx
282 << " tm: " << right << setw(10) << fixed << tm3
283 << endl;
284
285 } // operator()
286
287 BCTest& fBC;
288 uint32_t fReps;
289
290 };
291
292 struct readThr
293 {
294
readThrreadThr295 readThr(BCTest& bc, int reps = 1) : fBC(bc), fReps(reps) {}
296
operator ()readThr297 void operator()()
298 {
299 uint32_t rc = 0;
300 uint32_t readBlocks = 0;
301 uint32_t hits = 0;
302 uint32_t miss = 0;
303 uint32_t hitsTot = 0;
304 uint32_t missTot = 0;
305 struct timespec tm1;
306 struct timespec tm2;
307 tm1.tv_sec = 0;
308 tm1.tv_nsec = 0;
309 tm2.tv_sec = 0;
310 tm2.tv_nsec = 0;
311 double tm3 = 0;
312 clock_gettime(CLOCK_REALTIME, &tm1);
313
314 for (uint32_t k = 0; k < fReps; k++)
315 {
316 for (uint32_t i = 0; i < lastRangeListIdx && i < fBC.OidRangesList.size() ; i++)
317 {
318 rc = fBC.ReadOidRanges(fBC.OidRangesList[i], &hits, &miss);
319 //cout << "-- ReadTest " << fBC.OidRangesList[i].oid << " h: " << fBC.OidRangesList[i].hwm << "/" << rc << endl;
320 readBlocks += rc;
321 rc = 0;
322 }
323
324 hitsTot += hits;
325 missTot += miss;
326 hits = 0;
327 miss = 0;
328 }
329
330 clock_gettime(CLOCK_REALTIME, &tm2);
331 timespec_sub(tm1, tm2, tm3);
332
333 cout << "readtest rd: " << hitsTot << "/" << missTot
334 << " sz: " << fBC.fCacheSz
335 << " tm: " << right << setw(10) << fixed << tm3
336 << endl;
337
338 } // operator()
339
340
341 BCTest& fBC;
342 uint32_t fReps;
343
344 };
345
usage()346 void usage()
347 {
348 cout << "testbc <cacheSz/1024> <reader threads> <read ahead> <client threads> <reps>" << endl;
349 }
350
351 //
main(int argc,char * argv[])352 int main(int argc, char* argv[])
353 {
354
355 int cacheSz = 128; // K number of blocks
356 int thr = 1;
357 int ra = 1024;
358 int clients = 1;
359 int reps = 1;
360
361 if (argc > 1 && atoi(argv[1]) > 0)
362 cacheSz = atoi(argv[1]) * 1024;
363
364 if (argc > 2 && atoi(argv[2]) > 0)
365 thr = atoi(argv[2]);
366
367 if (argc > 3 && atoi(argv[3]) > 0)
368 ra = atoi(argv[3]);
369
370 if (argc > 4 && atoi(argv[4]) > 0)
371 clients = atoi(argv[4]);
372
373 if (argc > 5 && atoi(argv[5]) > 0)
374 reps = atoi(argv[5]);
375
376 BCTest bc(cacheSz, thr, ra);
377
378 cout <<
379 "Cache Size: " << cacheSz <<
380 " read Threads: " << thr <<
381 " read Ahead: " << ra <<
382 " clients: " << clients <<
383 " repetitions: " << reps <<
384 " max Blocks: " << bc.maxBlocksAvailable <<
385 endl;
386
387 // loader cache
388 struct loadThr loader1(bc, 1);
389 struct readThr reader1(bc, reps);
390 vector<boost::thread*> v;
391
392 boost::thread* th1 = new boost::thread(loader1);
393 th1->join();
394
395 for (int i = 0; i < clients; i++)
396 {
397 boost::thread* rd1 = new boost::thread(reader1);
398 v.push_back(rd1);
399 }
400
401 for (int i = 0; i < clients; i++)
402 {
403 boost::thread* rd1 = v[i];
404 rd1->join();
405 delete rd1;
406 }
407
408 v.clear();
409
410 delete th1;
411
412 return 0;
413
414 } // end main
415