10 #include "../macros.h"
11 #include "../varkey.h"
12 #include "../thread.h"
14 #include "../spinbarrier.h"
16 #include "../record/encoder.h"
23 static size_t nproducts;
24 static const float pricefactor = 10000.0; // bids range from [0, 10000.0)
26 #define BIDUSER_REC_KEY_FIELDS(x, y) \
28 #define BIDUSER_REC_VALUE_FIELDS(x, y) \
30 DO_STRUCT(biduser_rec, BIDUSER_REC_KEY_FIELDS, BIDUSER_REC_VALUE_FIELDS)
32 #define BID_REC_KEY_FIELDS(x, y) \
35 #define BID_REC_VALUE_FIELDS(x, y) \
38 DO_STRUCT(bid_rec, BID_REC_KEY_FIELDS, BID_REC_VALUE_FIELDS)
40 #define BIDMAX_REC_KEY_FIELDS(x, y) \
42 #define BIDMAX_REC_VALUE_FIELDS(x, y) \
44 DO_STRUCT(bidmax_rec, BIDMAX_REC_KEY_FIELDS, BIDMAX_REC_VALUE_FIELDS)
46 class bid_worker : public bench_worker {
49 unsigned int worker_id,
50 unsigned long seed, abstract_db *db,
51 const map<string, abstract_ordered_index *> &open_tables,
52 spin_barrier *barrier_a, spin_barrier *barrier_b)
53 : bench_worker(worker_id, false, seed, db,
54 open_tables, barrier_a, barrier_b),
55 bidusertbl(open_tables.at("biduser")),
56 bidtbl(open_tables.at("bid")),
57 bidmaxtbl(open_tables.at("bidmax"))
64 void *txn = db->new_txn(txn_flags, arena, txn_buf());
66 // pick user at random
67 biduser_rec::key biduser_key(r.next() % nusers);
68 ALWAYS_ASSERT(bidusertbl->get(txn, Encode(obj_k0, biduser_key), obj_v0));
69 biduser_rec::value biduser_value_temp;
70 const biduser_rec::value *biduser_value = Decode(obj_v0, biduser_value_temp);
72 // update the user's bid
73 const uint32_t bid = biduser_value->bid;
74 biduser_value_temp.bid++;
75 bidusertbl->put(txn, Encode(str(), biduser_key), Encode(str(), biduser_value_temp));
78 const bid_rec::key bid_key(biduser_key.uid, bid);
79 const bid_rec::value bid_value(r.next() % nproducts, r.next_uniform() * pricefactor);
80 bidtbl->insert(txn, Encode(str(), bid_key), Encode(str(), bid_value));
82 // update the max value if necessary
83 const bidmax_rec::key bidmax_key(bid_value.pid);
84 ALWAYS_ASSERT(bidmaxtbl->get(txn, Encode(obj_k0, bidmax_key), obj_v0));
85 bidmax_rec::value bidmax_value_temp;
86 const bidmax_rec::value *bidmax_value = Decode(obj_v0, bidmax_value_temp);
88 if (bid_value.amount > bidmax_value->amount) {
89 bidmax_value_temp.amount = bid_value.amount;
90 bidmaxtbl->put(txn, Encode(str(), bidmax_key), Encode(str(), bidmax_value_temp));
93 if (likely(db->commit_txn(txn)))
94 return txn_result(true, 0);
95 } catch (abstract_db::abstract_abort_exception &ex) {
98 return txn_result(false, 0);
102 TxnBid(bench_worker *w)
104 return static_cast<bid_worker *>(w)->txn_bid();
107 virtual workload_desc_vec
111 w.push_back(workload_desc("Bid", 1.0, TxnBid));
116 inline ALWAYS_INLINE string &
119 return *arena.next();
122 abstract_ordered_index *bidusertbl;
123 abstract_ordered_index *bidtbl;
124 abstract_ordered_index *bidmaxtbl;
126 // scratch buffer space
132 class bid_loader : public bench_loader {
134 bid_loader(unsigned long seed,
136 const map<string, abstract_ordered_index *> &open_tables)
137 : bench_loader(seed, db, open_tables)
144 abstract_ordered_index *bidusertbl = open_tables.at("biduser");
145 abstract_ordered_index *bidmaxtbl = open_tables.at("bidmax");
148 const size_t batchsize = (db->txn_max_batch_size() == -1) ?
149 10000 : db->txn_max_batch_size();
150 ALWAYS_ASSERT(batchsize > 0);
153 const size_t nbatches = nusers / batchsize;
155 void *txn = db->new_txn(txn_flags, arena, txn_buf());
156 for (size_t j = 0; j < nusers; j++) {
157 const biduser_rec::key key(j);
158 const biduser_rec::value value(0);
160 bidusertbl->insert(txn, Encode(key), Encode(buf0, value));
163 cerr << "batch 1/1 done" << endl;
164 ALWAYS_ASSERT(db->commit_txn(txn));
166 for (size_t i = 0; i < nbatches; i++) {
167 size_t keyend = (i == nbatches - 1) ? nusers : (i + 1) * batchsize;
168 void *txn = db->new_txn(txn_flags, arena, txn_buf());
169 for (size_t j = i * batchsize; j < keyend; j++) {
170 const biduser_rec::key key(j);
171 const biduser_rec::value value(0);
173 bidusertbl->insert(txn, Encode(key), Encode(buf0, value));
176 cerr << "batch " << (i + 1) << "/" << nbatches << " done" << endl;
177 ALWAYS_ASSERT(db->commit_txn(txn));
181 cerr << "[INFO] finished loading BIDUSER table" << endl;
185 const size_t nbatches = nproducts / batchsize;
187 void *txn = db->new_txn(txn_flags, arena, txn_buf());
188 for (size_t j = 0; j < nproducts; j++) {
189 const bidmax_rec::key key(j);
190 const bidmax_rec::value value(0.0);
192 bidmaxtbl->insert(txn, Encode(key), Encode(buf0, value));
195 cerr << "batch 1/1 done" << endl;
196 ALWAYS_ASSERT(db->commit_txn(txn));
198 for (size_t i = 0; i < nbatches; i++) {
199 size_t keyend = (i == nbatches - 1) ? nproducts : (i + 1) * batchsize;
200 void *txn = db->new_txn(txn_flags, arena, txn_buf());
201 for (size_t j = i * batchsize; j < keyend; j++) {
202 const bidmax_rec::key key(j);
203 const bidmax_rec::value value(0.0);
205 bidmaxtbl->insert(txn, Encode(key), Encode(buf0, value));
208 cerr << "batch " << (i + 1) << "/" << nbatches << " done" << endl;
209 ALWAYS_ASSERT(db->commit_txn(txn));
213 cerr << "[INFO] finished loading BIDMAX table" << endl;
216 } catch (abstract_db::abstract_abort_exception &ex) {
217 // shouldn't abort on loading!
218 ALWAYS_ASSERT(false);
224 class bid_bench_runner : public bench_runner {
226 bid_bench_runner(abstract_db *db)
229 open_tables["biduser"] = db->open_index("biduser", sizeof(biduser_rec));
230 open_tables["bid"] = db->open_index("bid", sizeof(bid_rec));
231 open_tables["bidmax"] = db->open_index("bidmax", sizeof(bidmax_rec));
235 virtual vector<bench_loader *>
238 vector<bench_loader *> ret;
239 ret.push_back(new bid_loader(0, db, open_tables));
243 virtual vector<bench_worker *>
246 fast_random r(36578943);
247 vector<bench_worker *> ret;
248 for (size_t i = 0; i < nthreads; i++)
251 i, r.next(), db, open_tables,
252 &barrier_a, &barrier_b));
258 bid_do_test(abstract_db *db, int argc, char **argv)
260 nusers = size_t(scale_factor * 1000.0);
261 nproducts = size_t(scale_factor * 1000.0);
262 ALWAYS_ASSERT(nusers > 0);
263 ALWAYS_ASSERT(nproducts > 0);
264 bid_bench_runner r(db);