Permalink
Browse files

Added cache stats and get_info/1

The new operation get_info/1 returns the following information about a cache:

- number of cache hits;
- number of cache misses;
- the total size of the cache (a constant, specified when the cache was created);
- the current amount of free space in the cache (in bytes);
- the number of items the cache is storing
  • Loading branch information...
1 parent 25be910 commit 436ae44da037c806f162959cd0c2c801cb5512f1 @fdmanana committed Jan 18, 2011
Showing with 284 additions and 20 deletions.
  1. +33 −5 src/term_cache_dict.erl
  2. +32 −5 src/term_cache_ets.erl
  3. +31 −5 src/term_cache_pdict.erl
  4. +155 −0 src/term_cache_tests.erl
  5. +33 −5 src/term_cache_trees.erl
View
@@ -26,7 +26,7 @@
% public API
-export([start_link/1, stop/1]).
-export([get/2, get/3, put/3, update/3]).
--export([flush/1]).
+-export([flush/1, get_info/1]).
% gen_server callbacks
-export([init/1, handle_call/3, handle_info/2, handle_cast/2]).
@@ -43,7 +43,9 @@
ttl, % milliseconds
items,
atimes,
- take_fun
+ take_fun,
+ hits = 0,
+ misses = 0
}).
%% @type cache() = pid() | atom()
@@ -85,6 +87,13 @@ flush(Cache) ->
ok = gen_server:cast(Cache, flush).
+%% @spec get_info(cache()) -> {ok, [info()]}
+%% @type info() = {size, integer()} | {free, integer() | {items, integer()} |
+%% {hits, integer()} | {misses, integer()}
+get_info(Cache) ->
+ gen_server:call(Cache, get_info).
+
+
%% @spec start_link(options()) -> {ok, pid()}
%% @type options() = [ option() ]
%% @type option() = {name, atom()} | {policy, policy()} | {size, size()} |
@@ -186,7 +195,9 @@ handle_cast(flush, #state{items = Items, cache_size = Size} = State) ->
handle_call({get, Key}, _From, State) ->
- #state{items = Items, atimes = ATimes, ttl = T} = State,
+ #state{
+ items = Items, atimes = ATimes, ttl = T, hits = Hits, misses = Misses
+ }= State,
case dict:find(Key, Items) of
{ok, {Item, ItemSize, ATime, Timer}} ->
cancel_timer(Key, Timer),
@@ -197,13 +208,30 @@ handle_call({get, Key}, _From, State) ->
Key, {Item, ItemSize, NewATime, set_timer(Key, T)}, Items),
NewState = State#state{
items = Items2,
- atimes = ATimes2
+ atimes = ATimes2,
+ hits = Hits + 1
},
{reply, {ok, Item}, NewState};
error ->
- {reply, not_found, State}
+ {reply, not_found, State#state{misses = Misses + 1}}
end;
+
+handle_call(get_info, _From, State) ->
+ #state{
+ atimes = ATimes,
+ free = Free,
+ cache_size = CacheSize,
+ hits = Hits,
+ misses = Misses
+ } = State,
+ Info = [
+ {size, CacheSize}, {free, Free}, {items, gb_trees:size(ATimes)},
+ {hits, Hits}, {misses, Misses}
+ ],
+ {reply, {ok, Info}, State};
+
+
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
View
@@ -25,7 +25,7 @@
% public API
-export([start_link/1, stop/1]).
-export([get/2, get/3, put/3, update/3]).
--export([flush/1]).
+-export([flush/1, get_info/1]).
% gen_server callbacks
-export([init/1, handle_call/3, handle_info/2, handle_cast/2]).
@@ -42,7 +42,9 @@
ttl, % milliseconds
items,
atimes,
- take_fun
+ take_fun,
+ hits = 0,
+ misses = 0
}).
%% @type cache() = pid() | atom()
@@ -84,6 +86,13 @@ flush(Cache) ->
ok = gen_server:cast(Cache, flush).
+%% @spec get_info(cache()) -> {ok, [info()]}
+%% @type info() = {size, integer()} | {free, integer() | {items, integer()} |
+%% {hits, integer()} | {misses, integer()}
+get_info(Cache) ->
+ gen_server:call(Cache, get_info).
+
+
%% @spec start_link(options()) -> {ok, pid()}
%% @type options() = [ option() ]
%% @type option() = {name, atom()} | {policy, policy()} | {size, size()} |
@@ -177,7 +186,9 @@ handle_cast(flush,
handle_call({get, Key}, _From, State) ->
- #state{items = Items, atimes = ATimes, ttl = Ttl} = State,
+ #state{
+ items = Items, atimes = ATimes, ttl = Ttl, hits = Hits, misses = Misses
+ } = State,
case ets:lookup(Items, Key) of
[{Key, {Item, ItemSize, ATime, Timer}}] ->
cancel_timer(Key, Timer),
@@ -186,11 +197,27 @@ handle_call({get, Key}, _From, State) ->
true = ets:insert(ATimes, {NewATime, Key}),
NewTimer = set_timer(Key, Ttl),
true = ets:insert(Items, {Key, {Item, ItemSize, NewATime, NewTimer}}),
- {reply, {ok, Item}, State};
+ {reply, {ok, Item}, State#state{hits = Hits + 1}};
[] ->
- {reply, not_found, State}
+ {reply, not_found, State#state{misses = Misses + 1}}
end;
+
+handle_call(get_info, _From, State) ->
+ #state{
+ atimes = ATimes,
+ free = Free,
+ cache_size = CacheSize,
+ hits = Hits,
+ misses = Misses
+ } = State,
+ Info = [
+ {size, CacheSize}, {free, Free}, {items, ets:info(ATimes, size)},
+ {hits, Hits}, {misses, Misses}
+ ],
+ {reply, {ok, Info}, State};
+
+
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
View
@@ -25,7 +25,7 @@
% public API
-export([start_link/1, stop/1]).
-export([get/2, get/3, put/3, update/3]).
--export([flush/1]).
+-export([flush/1, get_info/1]).
% gen_server callbacks
-export([init/1, handle_call/3, handle_info/2, handle_cast/2]).
@@ -41,7 +41,9 @@
policy,
ttl, % milliseconds
atimes,
- take_fun
+ take_fun,
+ hits = 0,
+ misses = 0
}).
%% @type cache() = pid() | atom()
@@ -83,6 +85,13 @@ flush(Cache) ->
ok = gen_server:cast(Cache, flush).
+%% @spec get_info(cache()) -> {ok, [info()]}
+%% @type info() = {size, integer()} | {free, integer() | {items, integer()} |
+%% {hits, integer()} | {misses, integer()}
+get_info(Cache) ->
+ gen_server:call(Cache, get_info).
+
+
%% @spec start_link(options()) -> {ok, pid()}
%% @type options() = [ option() ]
%% @type option() = {name, atom()} | {policy, policy()} | {size, size()} |
@@ -178,20 +187,37 @@ handle_cast(flush, #state{cache_size = Size} = State) ->
},
{noreply, NewState}.
-handle_call({get, Key}, _From, #state{atimes = ATimes, ttl = T} = State) ->
+handle_call({get, Key}, _From,
+ #state{atimes = ATimes, ttl = T, hits = Hits, misses = Misses} = State) ->
case erlang:get({key, Key}) of
undefined ->
- {reply, not_found, State};
+ {reply, not_found, State#state{misses = Misses + 1}};
{item, Item, ItemSize, ATime, Timer} ->
cancel_timer(Key, Timer),
NewATime = erlang:now(),
ATimes2 = gb_trees:insert(
NewATime, Key, gb_trees:delete(ATime, ATimes)),
erlang:put(
{key, Key}, {item, Item, ItemSize, NewATime, set_timer(Key, T)}),
- {reply, {ok, Item}, State#state{atimes = ATimes2}}
+ {reply, {ok, Item}, State#state{atimes = ATimes2, hits = Hits + 1}}
end;
+
+handle_call(get_info, _From, State) ->
+ #state{
+ atimes = ATimes,
+ free = Free,
+ cache_size = CacheSize,
+ hits = Hits,
+ misses = Misses
+ } = State,
+ Info = [
+ {size, CacheSize}, {free, Free}, {items, gb_trees:size(ATimes)},
+ {hits, Hits}, {misses, Misses}
+ ],
+ {reply, {ok, Info}, State};
+
+
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
Oops, something went wrong.

0 comments on commit 436ae44

Please sign in to comment.