Skip to content

Commit fd9d762

Browse files
authored
Merge pull request #58 from Shpaky/v3.0.0
'lfu' implementation was transformed to single thread model
2 parents f4f8ef5 + 13c75ff commit fd9d762

13 files changed

+390
-1518
lines changed

README.md

Lines changed: 27 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# 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.
33

44

55
Reference Guide
66
===============
77

88
## 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.
1010

1111
#### tasks:
1212

@@ -48,38 +48,6 @@ Note that the implementation of algorithm stores keys in binary, that is, for se
4848

4949
<<"moscow">>
5050

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-
8351
## launch options
8452

8553
[{lfu,[
@@ -194,262 +162,81 @@ max key size
194162
#### put key
195163
###### internal:
196164

197-
lfu:point(K).
165+
lfu:point(K). %% ok
198166

199167
###### external:
200168

201-
POINT:key %% "OK"
169+
POINT:key %% "OK"
202170

203171
#### get counter on key
204172
###### internal:
205173

206-
lfu:count(K).
174+
lfu:count(K). %% counter
207175

208176
###### external:
209177

210-
COUNT:key %% "NUMBER"
178+
COUNT:key %% "NUMBER"
211179

212-
#### get offset counter and counter all keys
180+
#### get least counter, most counter and quantity of keys
213181
###### internal:
214182

215-
lfu:state().
183+
lfu:state(). %% [least counter,most counter,quantity of keys]
216184

217185
###### external:
218186

219-
STATE %% JSON: "{O:NUMBER,Q:NUMBER}"
187+
STATE %% JSON: "{L:NUMBER,M:NUMBER,Q:NUMBER}"
220188

221189
#### store algorithm state to disk
222190
###### Please pay attantion, 'store' call executes asynchronously!
223191
###### internal:
224192

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
235194

236195
###### external:
237196

238-
SCORE %% "READY"
197+
STORE %% "OK"
239198

240-
#### execute scoring of offset counter and get keys by it into internal table
199+
#### get key with least counter
241200
###### internal:
242-
###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'!
243201

244-
T = lfu:fetch(). %% tid()
245-
ets:tab2list(T).
202+
lfu:fetch(). %% {counter,[<<"key">>]}
246203

247204
###### external:
248205

249-
FETCH %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]"
206+
FETCH %% JSON: "{counter:[key]}"
250207

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
263209
##### without confirm
264210
###### internal:
265-
###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'!
266211

267-
T = lfu:clean(). %% tid()
212+
lfu:clean(). %% {counter,[<<"key">>]}
268213
or
269-
T = lfu:clean(async). %% tid()
214+
lfu:clean(async). %% {counter,[<<"key">>]}
270215

271-
###### external:
216+
###### external
272217

273-
CLEAN %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]"
218+
CLEAN %% JSON: "{counter:[key]}"
274219
or
275-
CLEAN:ASYNC %% JSON: "[{number1:[key1,key2,key3]},{number2:[key1,key2,key3]},{number3:[key1,key2,key3]},...]"
220+
CLEAN:ASYNC %% JSON: "{counter:[key]}"
276221

277222
##### with confirm
223+
###### Please, pay attention timeout exists to confirm, equal '90' seconds by default
278224
###### internal:
279-
###### Please pay attantion, that exist of internal table expires after following request to fetching 'fetch/0' or to clean 'clean/0'!
280225

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).
283228

284229
###### external:
285230

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"
312233

313234
#### put list keys with conters
314235
###### initialization of state, for example, transfer of state from other implementation 'lfu'
315236
###### internal:
316237

317-
lfu:cheat([{K1,C1},{K2,C2},{K3,C3}]).
238+
lfu:cheat([{K1,C1},{K2,C2},{K3,C3}]). %% ok
318239

319240
###### external:
320241

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"

include/lfu.hrl

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
1-
-define(MIN_LIMIT,100000).
2-
-define(MAX_LIMIT,1000000000).
1+
-define(SERIE_SIZE,10000000).
2+
-define(MAX_COUNTER,1000000000000000).
33

4-
-define(MAX_ORDER,100000000000000). %% 1000000000 .. 100000000000000
5-
-define(MIN_ORDER,100).
6-
7-
-define(MIN_OFFSET,10). %% low limit for step to next rank
8-
-define(MAX_OFFSET,30). %% up limit for step to prev rank
9-
10-
-define(SCORE_OFFSET,0). %% must be less than ?MIN_ORDER && for example if it`s necessary begin score from 100 then need setting to 99
11-
12-
-define(TIMEOUT_STATE_OFFSET,90000).
13-
-define(TIMEOUT_STATE_SELECT,90000).
144
-define(TIMEOUT_STATE_DELETE,90000).
155

16-
-define(PREFIX_KEY,"lfu___").
17-
-define(POSTFIX_KEY,"__lfu").
18-
19-
-define(ETS_PIDS_STORE_TABLE_NAME,lfu_pid).
20-
-define(ETS_KEYS_STORE_TABLE_NAME,lfu_key).
6+
-define(ETS_KEYS_STORE_TABLE_NAME,lfu_key_store).
217
-define(ETS_KEYS_FETCH_TABLE_NAME,lfu_key_fetch).
228
-define(ETS_KEYS_FETCH_TABLE_OPTS,[
239
public,bag,{write_concurrency,true},
@@ -29,25 +15,11 @@
2915
%%
3016
%% following settings in progress develop
3117
%%
32-
-define(SPAWN_OPT_LFU,[
18+
-define(SPAWN_OPT_LRU,[
3319
% {max_heap_size,0},
3420
% {message_queue_data,off_heap},
3521
{fullsweep_after,65535}
3622
]).
37-
-define(SPAWN_OPT_EXACT_SCORE,[
38-
% {max_heap_size,0},
39-
% {message_queue_data,on_heap},
40-
% {min_bin_vheap_size,46422},
41-
% {min_heap_size,233},
42-
{fullsweep_after,65535}
43-
]).
44-
-define(SPAWN_OPT_QUICK_SCORE,[
45-
% {max_heap_size,0},
46-
% {message_queue_data,on_heap},
47-
% {min_bin_vheap_size,46422},
48-
% {min_heap_size,233},
49-
{fullsweep_after,65535}
50-
]).
5123

5224
-ifdef(support).
5325
-define(SUPPORT,true).

0 commit comments

Comments
 (0)