|
1 | 1 | # Least Frequently Used |
2 | | -Potent implementation of LFU algorithm based on processes-counters with support of counter by every keys up to once quadrillion hits. |
| 2 | +Potent implementation of LFU algorithm based counters with support of counter by every keys up to once quadrillion hits. |
3 | 3 |
|
4 | 4 |
|
5 | 5 | Reference Guide |
6 | 6 | =============== |
7 | 7 |
|
8 | 8 | ## description |
9 | | -This is implementation of LFU algorithm based on processes-counters with support of counter by every keys up to once quadrillion hits. |
| 9 | +This is implementation of LFU algorithm based on counters with support of counter by every keys up to once quadrillion hits. |
10 | 10 |
|
11 | 11 | #### tasks: |
12 | 12 |
|
@@ -48,38 +48,6 @@ Note that the implementation of algorithm stores keys in binary, that is, for se |
48 | 48 |
|
49 | 49 | <<"moscow">> |
50 | 50 |
|
51 | | -#### notice: |
52 | | -Note this implementation lfu algorithm use named processes-counters, that is atoms. |
53 | | -System quantity atoms is permissible 1048576 by default. |
54 | | -Maximum possible number named processes dynamic create, counts as follows: |
55 | | - |
56 | | -###### processes of high-order counters |
57 | | - |
58 | | - (MAX_ORDER-1) div MAX_LIMIT |
59 | | - |
60 | | -###### by default configuration: |
61 | | - |
62 | | - (100000000000000-1) div 1000000000 |
63 | | - |
64 | | -###### processes of low-order counters |
65 | | - |
66 | | - MAX_LIMIT div MIN_LIMIT |
67 | | - |
68 | | -###### by default configuration: |
69 | | - |
70 | | - 1000000000 div 100000 |
71 | | - |
72 | | -###### full expression: |
73 | | - |
74 | | - ((100000000000000-1) div 1000000000) + (1000000000 div 100000) = 109 998 |
75 | | - |
76 | | -But it is value may be more if MAX_ORDER raise to quadrillion: |
77 | | - |
78 | | - ((1000000000000000-1) div 1000000000) + (1000000000 div 100000) = 1 009 998 |
79 | | - |
80 | | -In this case you necessary is launch the Erlang-node with key '+t'. |
81 | | - |
82 | | - |
83 | 51 | ## launch options |
84 | 52 |
|
85 | 53 | [{lfu,[ |
@@ -194,262 +162,81 @@ max key size |
194 | 162 | #### put key |
195 | 163 | ###### internal: |
196 | 164 |
|
197 | | - lfu:point(K). |
| 165 | + lfu:point(K). %% ok |
198 | 166 |
|
199 | 167 | ###### external: |
200 | 168 |
|
201 | | - POINT:key %% "OK" |
| 169 | + POINT:key %% "OK" |
202 | 170 |
|
203 | 171 | #### get counter on key |
204 | 172 | ###### internal: |
205 | 173 |
|
206 | | - lfu:count(K). |
| 174 | + lfu:count(K). %% counter |
207 | 175 |
|
208 | 176 | ###### external: |
209 | 177 |
|
210 | | - COUNT:key %% "NUMBER" |
| 178 | + COUNT:key %% "NUMBER" |
211 | 179 |
|
212 | | -#### get offset counter and counter all keys |
| 180 | +#### get least counter, most counter and quantity of keys |
213 | 181 | ###### internal: |
214 | 182 |
|
215 | | - lfu:state(). |
| 183 | + lfu:state(). %% [least counter,most counter,quantity of keys] |
216 | 184 |
|
217 | 185 | ###### external: |
218 | 186 |
|
219 | | - STATE %% JSON: "{O:NUMBER,Q:NUMBER}" |
| 187 | + STATE %% JSON: "{L:NUMBER,M:NUMBER,Q:NUMBER}" |
220 | 188 |
|
221 | 189 | #### store algorithm state to disk |
222 | 190 | ###### Please pay attantion, 'store' call executes asynchronously! |
223 | 191 | ###### internal: |
224 | 192 |
|
225 | | - lfu:store(). |
226 | | - |
227 | | -###### external: |
228 | | - |
229 | | - STORE %% "OK" |
230 | | - |
231 | | -#### execute scoring of offset counter |
232 | | -###### internal: |
233 | | - |
234 | | - lfu:score(). |
| 193 | + lfu:store(). %% ok |
235 | 194 |
|
236 | 195 | ###### external: |
237 | 196 |
|
238 | | - SCORE %% "READY" |
| 197 | + STORE %% "OK" |
239 | 198 |
|
240 | | -#### execute scoring of offset counter and get keys by it into internal table |
| 199 | +#### get key with least counter |
241 | 200 | ###### internal: |
242 | | -###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'! |
243 | 201 |
|
244 | | - T = lfu:fetch(). %% tid() |
245 | | - ets:tab2list(T). |
| 202 | + lfu:fetch(). %% {counter,[<<"key">>]} |
246 | 203 |
|
247 | 204 | ###### external: |
248 | 205 |
|
249 | | - FETCH %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]" |
| 206 | + FETCH %% JSON: "{counter:[key]}" |
250 | 207 |
|
251 | | -#### execute scoring of offset counter and get keys by it into external table |
252 | | -###### Please pay attantion, that it`s preferably using interface with internal table 'fetch/0', because it ensures a data consistency with your system! |
253 | | -###### internal: |
254 | | - |
255 | | - T = ets:new(stub,[ %% tid() |
256 | | - bag,public,{write_concurrency,true}, |
257 | | - {decentralized_counters,true} |
258 | | - ]). |
259 | | - lfu:fetch(T). |
260 | | - ets:tab2list(T). |
261 | | - |
262 | | -#### execute scoring of offset counter and get keys by it into internal table for follow delete (support both interaction types) |
| 208 | +#### get and delete key with least counter |
263 | 209 | ##### without confirm |
264 | 210 | ###### internal: |
265 | | -###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'! |
266 | 211 |
|
267 | | - T = lfu:clean(). %% tid() |
| 212 | + lfu:clean(). %% {counter,[<<"key">>]} |
268 | 213 | or |
269 | | - T = lfu:clean(async). %% tid() |
| 214 | + lfu:clean(async). %% {counter,[<<"key">>]} |
270 | 215 |
|
271 | | -###### external: |
| 216 | +###### external |
272 | 217 |
|
273 | | - CLEAN %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]" |
| 218 | + CLEAN %% JSON: "{counter:[key]}" |
274 | 219 | or |
275 | | - CLEAN:ASYNC %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]" |
| 220 | + CLEAN:ASYNC %% JSON: "{counter:[key]}" |
276 | 221 |
|
277 | 222 | ##### with confirm |
| 223 | +###### Please, pay attention timeout exists to confirm, equal '90' seconds by default |
278 | 224 | ###### internal: |
279 | | -###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'! |
280 | 225 |
|
281 | | - {T,R} = lfu:clean(sync). %% {tid(),ref()} |
282 | | - lfu:clean(R,T). |
| 226 | + {K,R} = lfu:clean(sync). %% {{counter,[<<"key">>]},ref()} |
| 227 | + lfu:clean(R,K). |
283 | 228 |
|
284 | 229 | ###### external: |
285 | 230 |
|
286 | | - CLEAN:SYNC %% JSON: "{[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]:UNIQ_REF}" |
287 | | - CLEAN:UNIQ_REF %% OK |
288 | | - |
289 | | -#### execute scoring of offset counter and get keys by it into external table for follow delete (support only internal interaction type) |
290 | | -###### Please pay attantion, that it`s preferably using interface with internal table 'clean/0', because it ensures a data consistency with your system! |
291 | | -##### without confirm |
292 | | -###### internal: |
293 | | - |
294 | | - T = ets:new(stub,[ %% tid() |
295 | | - bag,public,{write_concurrency,true}, |
296 | | - {decentralized_counters,true} |
297 | | - ]). |
298 | | - T = lfu:clean(T). %% ref() |
299 | | - or |
300 | | - T = lfu:clean(async,T). %% ref() |
301 | | - |
302 | | -##### with confirm |
303 | | -###### internal: |
304 | | - |
305 | | - T = ets:new(stub,[ %% tid() |
306 | | - bag,public,{write_concurrency,true}, |
307 | | - {decentralized_counters,true} |
308 | | - ]). |
309 | | - {T,R} = lfu:clean(sync,T). %% ref() |
310 | | - lfu:clean(R,T). |
311 | | - |
| 231 | + CLEAN:SYNC %% JSON: "{{counter:[key]}:UNIQ_REF}" |
| 232 | + CLEAN:UNIQ_REF %% "OK" |
312 | 233 |
|
313 | 234 | #### put list keys with conters |
314 | 235 | ###### initialization of state, for example, transfer of state from other implementation 'lfu' |
315 | 236 | ###### internal: |
316 | 237 |
|
317 | | - lfu:cheat([{K1,C1},{K2,C2},{K3,C3}]). |
| 238 | + lfu:cheat([{K1,C1},{K2,C2},{K3,C3}]). %% ok |
318 | 239 |
|
319 | 240 | ###### external: |
320 | 241 |
|
321 | | - CHEAT:key1,counter1;key2,counter2;key3,counter3 %% OK |
322 | | - |
323 | | - |
324 | | -## configuration (under the hood) |
325 | | -#### Before corrects settings make sure you understand the implementation! |
326 | | - |
327 | | - -define(MIN_LIMIT,100000). |
328 | | - -define(MAX_LIMIT,1000000000). |
329 | | - |
330 | | - -define(MAX_ORDER,100000000000000). %% 1000000000 .. 100000000000000 |
331 | | - -define(MIN_ORDER,100). %% |
332 | | - |
333 | | - -define(MIN_OFFSET,10). %% low limit for step to next rank |
334 | | - -define(MAX_OFFSET,30). %% up limit for step to prev rank |
335 | | - |
336 | | - -define(SCORE_OFFSET,0). %% !!!!! must be less ?MIN_ORDER !!!!! && for example if it`s necessary begin score from 100 then need setting to 99 |
337 | | - |
338 | | - -define(TIMEOUT_STATE_OFFSET,90000). |
339 | | - -define(TIMEOUT_STATE_SELECT,90000). |
340 | | - -define(TIMEOUT_STATE_DELETE,90000). |
341 | | - |
342 | | - -define(PREFIX_KEY,"lfu___"). |
343 | | - -define(POSTFIX_KEY,"__lfu"). |
344 | | - |
345 | | - -define(ETS_PIDS_STORE_TABLE_NAME,lfu_pid). |
346 | | - -define(ETS_KEYS_STORE_TABLE_NAME,lfu_key). |
347 | | - |
348 | | - -define(ETS_KEYS_FETCH_TABLE_NAME,lfu_key_fetch). |
349 | | - -define(ETS_KEYS_FETCH_TABLE_OPTS,[ |
350 | | - public,bag,{write_concurrency,true}, |
351 | | - {decentralized_counters,true}]). |
352 | | - |
353 | | -#### MIN_LIMIT |
354 | | - |
355 | | -Range of values for the processes of low-order counters. |
356 | | - |
357 | | -###### Quantity the processes of low-order counters: |
358 | | - |
359 | | - 'MAX_LIMIT' div 'MIN_LIMIT' |
360 | | - |
361 | | -#### MAX_LIMIT |
362 | | - |
363 | | -Range of values for the processes of high-order counters. |
364 | | - |
365 | | -###### Quantity the processes of high-order counters: |
366 | | - |
367 | | - ('MAX_ORDER'-1) div 'MAX_LIMIT' |
368 | | - |
369 | | -#### MIN_ORDER |
370 | | - |
371 | | -Low (initial) value offset counter. |
372 | | - |
373 | | -#### MAX_ORDER |
374 | | - |
375 | | -Up (end) value for key counters and offset counter. |
376 | | -Keys counters reached this value will be no longer incremented. |
377 | | - |
378 | | -###### Allow values depending on system performance: |
379 | | - |
380 | | - 1000000000 |
381 | | - 10000000000 |
382 | | - 100000000000 |
383 | | - 1000000000000 |
384 | | - 10000000000000 |
385 | | - 100000000000000 |
386 | | - 1000000000000000 |
387 | | - |
388 | | -#### MIN_OFFSET |
389 | | - |
390 | | -Defines minimum permissible percentage of the number of keys, with a counter value equal to or less than the current measured value of the offset counter, of the total number of keys. |
391 | | -When the value is reached, the offset counter is incremented by one digit (provided that the following calculate value does not exceed 'MAX_OFFSET' value) and so on until an acceptable percentage is reached. |
392 | | - |
393 | | -The smaller it is, the fewer keys will be available for follow deletion. |
394 | | - |
395 | | -#### MAX_OFFSET |
396 | | - |
397 | | -Defines maximum permissible percentage of the number of keys, with a counter value equal to or less than the current measured value of the offset counter, of the total number of keys. |
398 | | -When the value is reached, the offset counter is decreases by one digit (provided that the following calculate value will more 'MIN_OFFSET' value) and so on until an acceptable percentage is reached. |
399 | | - |
400 | | - |
401 | | -The larger it is, the more keys will be available for follow deletion. |
402 | | - |
403 | | -#### SCORE_OFFSET |
404 | | - |
405 | | -The value of the key counter when a key begins to take into account by the algorithm. |
406 | | - |
407 | | -###### Must be less: |
408 | | - |
409 | | - 'MIN_ORDER' |
410 | | - |
411 | | -###### example: |
412 | | - |
413 | | - if it`s necessary begin score from 100 then need set to 99 |
414 | | - |
415 | | -#### TIMEOUT_STATE_OFFSET |
416 | | - |
417 | | -The timeout in timing that 'lfu' main process will waiting response on 'score' command from counter processes. |
418 | | - |
419 | | -This value can be incresed provided overload system. |
420 | | - |
421 | | -#### TIMEOUT_STATE_SELECT |
422 | | - |
423 | | -The timeout in timing that 'lfu' main process will waiting response on 'fetch' command from counter processes. |
424 | | - |
425 | | -This value can be incresed provided overload system. |
426 | | - |
427 | | -#### TIMEOUT_STATE_DELETE |
428 | | - |
429 | | -The timeout in timing that 'lfu' main process will waiting confirming response on 'clean' command from outside client. |
430 | | - |
431 | | -This value can be control depending on how long external client will handle the keys list. |
432 | | - |
433 | | -#### PREFIX_KEY |
434 | | - |
435 | | -The prefix key for service name of key for to store process counter pids in 'lfu_key' ets. |
436 | | - |
437 | | -#### POSTFIX_KEY |
438 | | - |
439 | | -The postfix key for service name of key for to store process counter pids in 'lfu_key' ets. |
440 | | - |
441 | | -#### ETS_PIDS_STORE_TABLE_NAME |
442 | | - |
443 | | -The ets for to store process counter pids. |
444 | | - |
445 | | -#### ETS_KEYS_STORE_TABLE_NAME |
446 | | - |
447 | | -The ets for to store counters by keys. |
448 | | - |
449 | | -#### ETS_KEYS_FETCH_TABLE_NAME |
450 | | - |
451 | | -The ets for fetching keys into internal table by commands: 'fetch/0', 'clean/0'. |
452 | | - |
453 | | -#### ETS_KEYS_FETCH_TABLE_OPTS |
454 | | - |
455 | | -The list of options for creating 'ETS_KEYS_FETCH_TABLE_OPTS' ets. |
| 242 | + CHEAT:key1,counter1;key2,counter2;key3,counter3 %% "OK" |
0 commit comments