Performance of dict and ets

Sean Hinde Sean.Hinde@REDACTED
Sat Dec 2 13:37:22 CET 2000


I've been doing some performance comparison between the new R7B dict module
and ets which I thought I'd share.

My benchmark program creates the table/dict, stores 20,000 elements in it
with keys 1..20000, then runs through all keys again and reads then deletes
each entry.

If I store lists of varying lengths I get the following results (microsecs
per op on a 167MHz SPARC)
list length	ets_rd_del	ets_write	ets_tot	dict_rd_del
dict_write	Dict_tot
1	13	12	25	54	62	117
100	43	30	73	55	62	117
200	71	42	113	54	64	119
300	102	60	162	55	62	117
400	140	73	213	55	63	118

As expected dict is the same speed across the board, but ets shows linear
growth with the size of the term being stored.

Storing any less than 20,000 rows doesn't seem to make much difference.

In the write case the breakeven is at about 300 elements in the list, in the
read/delete case at about 130 elements. Overall breakeven is at 230 approx

If I store a binary it becomes a bit more interesting...

The dict module performs identically to it's lists case.

The ets module gives the startling result that almost irrespective of the
size of the binary each op takes only around 14 microsecs. This seems to
imply that storing a binary in an ets table involves no copying...

My first guess is that the copying involved in storing something in an ets
table is an instantaneous term_to_binary type operation rather than anything
inherent in transferring data to ets???

Can anyone explain this ets copying business fully?


- Sean

BTW while playing with this I added a couple of functions to dict which
retrieve and delete the entry in one operation. This is about 20% faster
than doing them separately (which may be worth it for someone :~) )


-export([find_erase/2, fetch_erase/2]).

%% find_erase(Key, Dictionary) -> {ok, Value, Dictionary} | error

find_erase(Key, D0) ->
    Slot = get_slot(D0, Key),
    case on_bucket(fun (B0) -> find_erase_key(Key, B0) end,
		   D0, Slot) of
	{D1,error} ->
	{D1, Val} ->
	    D2 = maybe_contract(D1, 1), % I think this is always true
	    {ok, Val, D2}
find_erase_key(Key, [?kv(Key,Val)|Bkt]) -> {Bkt,Val};
find_erase_key(Key, [E|Bkt0]) ->
    {Bkt1,Val} = find_erase_key(Key, Bkt0),
find_erase_key(Key, []) -> {[],error}.

%% fetch_erase(Key, Dictionary) -> {Value, Dictionary}

fetch_erase(Key, D0) ->
    Slot = get_slot(D0, Key),
    {D1, Val} = on_bucket(fun (B0) -> fetch_erase_key(Key, B0) end,
			  D0, Slot),
    D2 = maybe_contract(D1, 1),
    {Val, D2}.
fetch_erase_key(Key, [?kv(Key,Val)|Bkt]) -> {Bkt,Val};
fetch_erase_key(Key, [E|Bkt0]) ->
    {Bkt1,Val} = fetch_erase_key(Key, Bkt0),

This email (including attachments) is confidential.  If you have received
this email in error please notify the sender immediately and delete this
email from your system without copying or disseminating it or placing any
reliance upon its contents.  We cannot accept liability for any breaches of
confidence arising through use of email.  Any opinions expressed in this
email (including attachments) are those of the author and do not necessarily
reflect our opinions.  We will not accept responsibility for any commitments
made by our employees outside the scope of our business.  We do not warrant
the accuracy or completeness of such information.

More information about the erlang-questions mailing list