|
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