forked from membase/ep-engine
/
item_pager.cc
90 lines (73 loc) · 2.57 KB
/
item_pager.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "config.h"
#include <iostream>
#include <cstdlib>
#include "common.hh"
#include "item_pager.hh"
#include "ep.hh"
static const double threshold = 75.0;
/**
* As part of the ItemPager, visit all of the objects in memory and
* eject some within a constrained probability
*/
class PagingVisitor : public VBucketVisitor {
public:
/**
* Construct a PagingVisitor that will attempt to evict the given
* percentage of objects.
*
* @param pcnt percentage of objects to attempt to evict (0-1)
*/
PagingVisitor(EPStats &st, double pcnt) : stats(st), percent(pcnt),
ejected(0), failedEjects(0) {}
void visit(StoredValue *v) {
double r = static_cast<double>(std::rand()) / static_cast<double>(RAND_MAX);
if (percent >= r) {
if (v->ejectValue(stats)) {
++ejected;
} else {
++failedEjects;
}
}
}
/**
* Get the number of items ejected during the visit.
*/
size_t numEjected() { return ejected; }
/**
* Get the number of ejection failures.
*
* An ejection failure is the state when an ejection was
* requested, but did not work for some reason (either object was
* dirty, or too small, or something).
*/
size_t numFailedEjects() { return failedEjects; }
private:
EPStats &stats;
double percent;
size_t ejected;
size_t failedEjects;
};
bool ItemPager::callback(Dispatcher &d, TaskId t) {
double current = static_cast<double>(StoredValue::getCurrentSize(stats));
double upper = static_cast<double>(stats.mem_high_wat);
double lower = static_cast<double>(stats.mem_low_wat);
if (current > upper) {
++stats.pagerRuns;
double toKill = (current - static_cast<double>(lower)) / current;
std::stringstream ss;
ss << "Using " << StoredValue::getCurrentSize(stats)
<< " bytes of memory, paging out %0f%% of items." << std::endl;
getLogger()->log(EXTENSION_LOG_INFO, NULL, ss.str().c_str(),
(toKill*100.0));
PagingVisitor pv(stats, toKill);
store->visit(pv);
stats.numValueEjects.incr(pv.numEjected());
stats.numNonResident.incr(pv.numEjected());
stats.numFailedEjects.incr(pv.numFailedEjects());
getLogger()->log(EXTENSION_LOG_INFO, NULL,
"Paged out %d values\n", pv.numEjected());
}
d.snooze(t, 10);
return true;
}