Skip to content

Commit 237c7df

Browse files
committed
range-list: send nearest cursor for missing keys
1 parent 4aea4b9 commit 237c7df

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

ds/range-list.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ export class RangeList {
9898
// get gets the value stored against an integer range (lo, hi)
9999
get(range) {
100100
const d = this.xget(range.lo, this.head);
101-
if (d == null || d.value == null) return null;
102-
return d.value;
101+
if (d[0] == null || d[0].value == null) return null;
102+
return d[0].value;
103103
}
104104

105105
// search searches for key k, starting at cursor, cursornode
@@ -125,7 +125,8 @@ export class RangeList {
125125
// exclude tail, not a valid search result
126126
this.avgGetIter =
127127
this.avgGetIter > 0 ? Math.round((this.avgGetIter + c) / 2) : c;
128-
return cur === this.tail ? null : cur;
128+
// returns [ans-node, iter-position]
129+
return cur === this.tail ? [null, cur] : [cur, cur];
129130
} else if (lt) {
130131
// for the next iteration, lookup siblings of cur
131132
node = cur;
@@ -137,11 +138,14 @@ export class RangeList {
137138
}
138139
}
139140

140-
return null;
141+
// returns [ans-node, iter-position]
142+
return [null, cur];
141143
}
142144

143145
delete(range) {
144-
const node = this.xget(range.lo, this.head);
146+
const res = this.xget(range.lo, this.head);
147+
const node = res[0];
148+
145149
if (node == null) return false;
146150

147151
// delete node from all its levels
@@ -227,14 +231,14 @@ export class RangeList {
227231

228232
// selects level which is max way off from what is expected
229233
levelup() {
230-
// max-diff between no. of nodes at expected at a level vs current
234+
// max-diff between no. of nodes expected at a level vs current
231235
let maxdiff = 0;
232236
// level i where max-diff is
233237
let maxi = -1;
234238
// tracks total no. of nodes across levels, from higher levels to lower
235239
let sum = 0;
236240

237-
// levels are 1 indexed, the array is 0 index, that is,
241+
// levels are 1 indexed, arrays are 0 indexed, that is,
238242
// level[0] => L1, level[1] => L2, level[7] => L8, and so on
239243
for (let i = this.levelhisto.length; i > 0; i--) {
240244
// number of nodes that level i
@@ -248,7 +252,7 @@ export class RangeList {
248252
}
249253
// a node which is on level[9] (L10) also exists at all other levels,
250254
// from 0..9 (L1..L10); that is, to get a count of nodes only on
251-
// level[0] (L1) but not on other levels, substract out the sum of
255+
// level[0] (L1) but not on other levels, subtract out the sum of
252256
// nodes on all other levels, 1..9 (L2..L10)
253257
sum += n;
254258
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@serverless-dns/lfu-cache",
3-
"version": "3.4.0",
3+
"version": "3.4.1",
44
"description": "Various LFU cache implementations",
55
"main": "lfu.js",
66
"type": "module",

strat/o1.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,18 @@ export class O1 {
9191
// search searches for key k, starting at cursor it
9292
search(k, it, f = 1) {
9393
const cursor = it != null ? it.cursor : null;
94-
const ans = this.store.search(k, cursor);
94+
const res = this.store.search(k, cursor);
95+
const ans = res[0];
96+
const cur = res[1];
9597
if (ans) {
9698
const entry = ans.value;
9799
logd("search-hit; key:", k, "freq:", entry.freq);
98100
entry.freq += f;
99101
this.move(entry.freq, entry.node);
100-
return mkcursor(ans, entry.value);
102+
return mkcursor(cur, entry.value);
101103
}
102104
logd("search-miss", k);
103-
return null;
105+
return mkcursor(cur, null);
104106
}
105107

106108
size() {

test/ds-perf.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ async function rangelistPerf(n) {
4040

4141
const r = spacedinput(n);
4242

43+
// insert (range, value) pairs
4344
const ts1 = Date.now();
4445
r.forEach((i) => s.set(mkrange(i, i + 1), "r" + i));
4546
const ts2 = Date.now();
4647

4748
console.log(tag, "setup duration", ts2 - ts1 + "ms");
4849

50+
// retrieve values of all valid keys
4951
const t = [];
5052
const miss = [];
5153
for (let i = 0; i < r.length; i++) {
@@ -60,7 +62,25 @@ async function rangelistPerf(n) {
6062
}
6163

6264
console.log(tag, "get:avg(nodes-visited)", log2(n), "~=", s.avgGetIter);
65+
s.avgGetIter = 0; // reset
6366

67+
// search nearby items, upto r.length no. of times
68+
const tf = [];
69+
const missf = [];
70+
for (let j = 0, i = 0, x = null; j < r.length; j++) {
71+
i = nearbyInt(i, 100, 0, n);
72+
73+
const t1 = Date.now();
74+
x = s.search(mkrange(i, i), x)[1];
75+
const t2 = Date.now();
76+
tf.push(t2 - t1);
77+
78+
if (x == null) missf.push(i);
79+
}
80+
81+
console.log(tag, "find:avg(nodes-visited)", log2(n), "~=", s.avgGetIter);
82+
83+
// delete all keys
6484
const td = [];
6585
const missd = [];
6686
for (let i = 0; i < r.length; i++) {
@@ -77,7 +97,7 @@ async function rangelistPerf(n) {
7797
logmissing(tag + " get:", miss);
7898
logmissing(tag + " del:", missd);
7999
logquantiles(tag, t, rlExpectedP99ForSize1M);
80-
logsums(tag, t, td, rlExpectedSumForSize1M);
100+
logsums(tag, t, tf, rlExpectedSumForSize1M);
81101

82102
console.log(tag, "---fin---");
83103

@@ -92,12 +112,14 @@ async function balancedRangeListPerf(n) {
92112

93113
const r = spacedinput(n);
94114

115+
// insert (range, value) pairs
95116
const ts1 = Date.now();
96117
r.forEach((i) => s.set(mkrange(i, i + 1), "r" + i));
97118
const ts2 = Date.now();
98119

99120
console.log(tag, "setup duration", ts2 - ts1 + "ms");
100121

122+
// balance rangelist
101123
const ts3 = Date.now();
102124
s = balancedCopy(s);
103125
const ts4 = Date.now();
@@ -128,7 +150,7 @@ async function balancedRangeListPerf(n) {
128150
i = nearbyInt(i, 100, 0, n);
129151

130152
const t1 = Date.now();
131-
x = s.search(mkrange(i, i), x);
153+
x = s.search(mkrange(i, i), x)[1];
132154
const t2 = Date.now();
133155
tf.push(t2 - t1);
134156

@@ -155,12 +177,14 @@ async function hashMapPerf(n) {
155177

156178
const r = spacedinput(n);
157179

180+
// insert (k, v) pairs
158181
const ot1 = Date.now();
159182
r.forEach((i) => s.set(i, "m" + i));
160183
const ot2 = Date.now();
161184

162185
console.log(tag, "setup duration", ot2 - ot1 + "ms");
163186

187+
// retrieve values of all valid keys
164188
const t = [];
165189
const miss = [];
166190
for (let i = 0; i < r.length; i++) {
@@ -174,6 +198,7 @@ async function hashMapPerf(n) {
174198
if (x == null) miss.push(i);
175199
}
176200

201+
// delete all keys
177202
const td = [];
178203
const missd = [];
179204
for (let i = 0; i < r.length; i++) {
@@ -254,7 +279,7 @@ function nearbyInt(i, jump, min, max) {
254279
const n = add ? i + vec : i - vec;
255280

256281
if (n < min) return min + vec;
257-
if (n > max) return max - vec;
282+
if (n >= max) return max - vec;
258283
return n;
259284
}
260285

0 commit comments

Comments
 (0)