Technomenace

Linux, technology, opensource etc.

Erlang Ets Types Readwrite Performance Tests

Posted at — Jan 29, 2016

ETS read/write performance tests.

-module(ets_try2).
-import(lists, [foldl/3, reverse/1]).
-export([ match_times_test/0 ]).

%% ====================================================================
%% API functions
%% ====================================================================

match_times_test() ->
	io:format("==> Fetching GPL License v3.0 text ....       "),
	Data = get_gpl_license(),
	io:format("DONE!~n"),
	WordList = fetch_all_words(Data),
	InsertList = reverse(foldl(fun(Wrd, Acc) -> [ { Wrd , length(Acc) + 1 } | Acc] end, [], WordList)),

	Test = fun(TbType, TbName) ->
				    garbage_collect(),
				   	Tb = create_ets_test_table(TbType, TbName),
				   	{InsertTime, _} = timer:tc(fun() -> [ets:insert(Tb, Rec) || Rec <- InsertList] end),
				   	TbSize = ets:info(Tb, size),
					
					RandKeys = ["program", "should", "GNU", "see", "interactive",
									"the", "please", "type", "even", "and"],
					LookupFn = fun() ->
										T = foldl(fun(Key, Acc) -> {Tt, _} = timer:tc(ets, lookup, [Tb, Key]), Tt + Acc end, 0, RandKeys),
										T / 10
										end,
					
					{ReadTime, _} = timer:tc(fun() -> traverse_through_all_records(Tb) end),
					
					LookupTime = LookupFn(),
	
					Type = ets:info(Tb, type),
					Size = ets:info(Tb, size),
					Memory = ets:info(Tb, memory),
					io:format("~n==> Information regarding ets table '~p' :-~n", [TbName]),
					io:format("Type: ~p , # of Records: ~p , Total Memory: ~p, Words/Rec: ~f~n", 
							  [Type, Size, Memory, Memory/Size]),
					
					
					io:format("Time taken to insert data      : ~f ms/record~n", [InsertTime / TbSize]),
					io:format("Time taken to traverse through : ~f ms/record~n", [ReadTime / TbSize]),
					io:format("(Avg) Time for lookup/2 fn     : ~f ms~n", [LookupTime]),
					ets:delete(Tb)
				   end,
	
	Test(set, setTb), 						%% set
	Test(ordered_set, orderedsetTb), 		%% ordered_set
	Test(bag, bagTb),				 		%% ordered_set
	Test(duplicate_bag, duplicatebagTb). 	%% ordered_set
	
	


%% ====================================================================
%% Internal functions
%% ====================================================================

traverse_through_all_records(TableId) ->
	Loop = fun Loop(_TableId, '$end_of_table') -> ok;
			   Loop(TableId, Key) -> 
					Loop(TableId, ets:next(TableId, Key))
		   end,
					
	case ets:first(TableId) of
		'$end_of_table' -> ok;
		Key -> Loop(TableId, Key)
	end.

get_gpl_license() ->
	application:start(inets),
	{ok, Res} = httpc:request("http://www.gnu.org/licenses/gpl-3.0.txt"),
	{_, _, Body} = Res,
	application:stop(inets),
	Body.

create_ets_test_table(Type, TableName) -> 
	TableId = ets:new(TableName, [Type]),
	TableId.

fetch_all_words(Body) ->
	fetch_all_words(Body, []).

fetch_all_words([], Acc) ->
	reverse(Acc);
fetch_all_words(Body, Acc) ->
	{Word, Rest} = fetch_next_word(Body),
	case Word of
		[] -> fetch_all_words(Rest, Acc);
		_ -> fetch_all_words(Rest, [Word | Acc])
	end.

fetch_next_word(Body) ->
	fetch_next_word(Body, []).

fetch_next_word([$\s|T], Acc)	-> {reverse(Acc), T};
fetch_next_word([$\r|T], Acc)	-> {reverse(Acc), T};
fetch_next_word([$\n|T], Acc)	-> {reverse(Acc), T};
fetch_next_word([$\t|T], Acc)	-> {reverse(Acc), T};
fetch_next_word([$\.|T], Acc)	-> {reverse(Acc), T};
fetch_next_word([H|T], Acc)		-> fetch_next_word(T, [H|Acc]);
fetch_next_word([], Acc)		-> {reverse(Acc), []}.

% EOF

Run:

1> ets_try2:match_times_test().
==> Fetching GPL License v3.0 text ....       DONE!

==> Information regarding ets table 'setTb' :-
Type: set , # of Records: 1486 , Total Memory: 31821, Words/Rec: 21.413863
Time taken to insert data      : 1.250336 ms/record
Time taken to traverse through : 0.423284 ms/record
(Avg) Time for lookup/2 fn     : 1.200000 ms

==> Information regarding ets table 'orderedsetTb' :-
Type: ordered_set , # of Records: 1486 , Total Memory: 33097, Words/Rec: 22.272544
Time taken to insert data      : 2.591521 ms/record
Time taken to traverse through : 0.421938 ms/record
(Avg) Time for lookup/2 fn     : 1.700000 ms

==> Information regarding ets table 'bagTb' :-
Type: bag , # of Records: 5654 , Total Memory: 97749, Words/Rec: 17.288468
Time taken to insert data      : 2.165900 ms/record
Time taken to traverse through : 0.196675 ms/record
(Avg) Time for lookup/2 fn     : 13.600000 ms

==> Information regarding ets table 'duplicatebagTb' :-
Type: duplicate_bag , # of Records: 5654 , Total Memory: 97749, Words/Rec: 17.288468
Time taken to insert data      : 0.885037 ms/record
Time taken to traverse through : 0.225327 ms/record
(Avg) Time for lookup/2 fn     : 14.400000 ms
true