%%%------------------------------------------------------------------- %%% File : get_records.erl %%% Author : Jay Nelson %%% Description : %%% Benchmark for stream_extract/3 performance. %%% %%% Created : 22 Jun 2005 by Jay Nelson %%%------------------------------------------------------------------- -module(get_records). %% API -export([ sampleRecord/1, setOfRecords/1, time/2, test/4, timesize/2, testsize/3, gen_rec_nums/1, gen_pos_and_size/2, convert_db_to_tuple/2, slow_collect/3, normal_collect/3, fast_collect/3, fastest_collect/3, slow_collect_size/2, normal_collect_size/2, fastest_collect_size/2 ]). %%==================================================================== %% Tests %%==================================================================== sampleRecord(Num) -> <<"This is record #", Num:32/integer>>. setOfRecords(Count) -> RecNums = lists:seq(1, Count), concat_binary([sampleRecord(Num) || Num <- RecNums]). time(Type=slow, Size=small) -> Bin = setOfRecords(25), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=normal, Size=small) -> Bin = setOfRecords(25), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=fast, Size=small) -> Bin = setOfRecords(25), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=fastest, Size=small) -> Bin = setOfRecords(25), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=slow, Size=large) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=normal, Size=large) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=fast, Size=large) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=fastest, Size=large) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 20]); time(Type=slow, Size=long) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 5000]); time(Type=normal, Size=long) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 5000]); time(Type=fast, Size=long) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 5000]); time(Type=fastest, Size=long) -> Bin = setOfRecords(25000), Recs = gen_rec_nums(Size), timer:tc(get_records, test, [Type, Bin, Recs, 5000]). test(slow, DB, Recs, Length) -> L = slow_collect(DB, Recs, Length), length(L); test(normal, DB, Recs, Length) -> L = normal_collect(DB, Recs, Length), length(L); test(fast, DB, Recs, Length) -> L = fast_collect(DB, Recs, Length), length(L); test(fastest, DB, Recs, Length) -> L = fastest_collect(DB, Recs, Length), length(L). timesize(Type=slow, Size=small) -> Bin = setOfRecords(25), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=normal, Size=small) -> Bin = setOfRecords(25), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); %% timesize(Type=fast, Size=small) -> %% Bin = setOfRecords(25), %% Recs = gen_pos_and_size(Size, 20), %% timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=fastest, Size=small) -> Bin = setOfRecords(25), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=slow, Size=large) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=normal, Size=large) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); %% timesize(Type=fast, Size=large) -> %% Bin = setOfRecords(25000), %% Recs = gen_pos_and_size(Size, 20), %% timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=fastest, Size=large) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 20), timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=slow, Size=long) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 5000), timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=normal, Size=long) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 5000), timer:tc(get_records, testsize, [Type, Bin, Recs]); %% timesize(Type=fast, Size=long) -> %% Bin = setOfRecords(25000), %% Recs = gen_pos_and_size(Size, 5000), %% timer:tc(get_records, testsize, [Type, Bin, Recs]); timesize(Type=fastest, Size=long) -> Bin = setOfRecords(25000), Recs = gen_pos_and_size(Size, 5000), timer:tc(get_records, testsize, [Type, Bin, Recs]). testsize(slow, DB, RecsAndSize) -> L = slow_collect_size(DB, RecsAndSize), length(L); testsize(normal, DB, RecsAndSize) -> L = normal_collect_size(DB, RecsAndSize), length(L); %% testsize(fast, DB, RecsAndSize) -> %% L = fast_collect_size(DB, RecsAndSize), %% length(L); testsize(fastest, DB, RecsAndSize) -> L = fastest_collect_size(DB, RecsAndSize), length(L). gen_rec_nums(small) -> random:seed0(), [ random:uniform(25) - 1 || _N <- lists:seq(1,10) ]; gen_rec_nums(large) -> random:seed0(), [ random:uniform(25000) - 1 || _N <- lists:seq(1,1000) ]; gen_rec_nums(long) -> random:seed0(), [ random:uniform(100) - 1 || _N <- lists:seq(1,1000) ]. gen_pos_and_size(small, Length) -> random:seed0(), [ {random:uniform(500 - Length) - 1, random:uniform(Length)} || _N <- lists:seq(1,10) ]; gen_pos_and_size(large, Length) -> random:seed0(), [ {random:uniform(500000 - Length) - 1, random:uniform(Length)} || _N <- lists:seq(1,1000) ]; gen_pos_and_size(long, Length) -> random:seed0(), [ {random:uniform(500000 - Length) - 1, random:uniform(Length)} || _N <- lists:seq(1,1000)]. %%==================================================================== %% API %%==================================================================== slow_collect(DB, Recs, Length) -> LDB = binary_to_list(DB), slow_collect(LDB, Recs, Length, []). slow_collect(_DB, [], _Length, RecsCollected) -> lists:reverse(RecsCollected); slow_collect(DB, [NextRec | Rest], Length, RecsCollected) -> ThisRec = lists:sublist(DB, NextRec * Length + 1, Length), slow_collect(DB, Rest, Length, [list_to_binary(ThisRec) | RecsCollected]). slow_collect_size(DB, RecsAndSize) -> LDB = binary_to_list(DB), slow_collect_size(LDB, RecsAndSize, []). slow_collect_size(_DB, [], RecsCollected) -> lists:reverse(RecsCollected); slow_collect_size(DB, [{Pos, Length} | Rest], RecsCollected) -> ThisRec = lists:sublist(DB, Pos + 1, Length), slow_collect_size(DB, Rest, [list_to_binary(ThisRec) | RecsCollected]). normal_collect(DB, Recs, Length) -> normal_collect(DB, Recs, Length, []). normal_collect(_DB, [], _Length, RecsCollected) -> lists:reverse(RecsCollected); normal_collect(DB, [NextRec | Rest], Length, RecsCollected) -> RecPos = NextRec * Length, << _Skip:RecPos/binary, ThisRec:Length/binary, _More/binary>> = DB, normal_collect(DB, Rest, Length, [ThisRec | RecsCollected]). normal_collect_size(DB, RecsAndSize) -> normal_collect_size(DB, RecsAndSize, []). normal_collect_size(_DB, [], RecsCollected) -> lists:reverse(RecsCollected); normal_collect_size(DB, [{Pos, Length} | Rest], RecsCollected) -> << _Skip:Pos/binary, ThisRec:Length/binary, _More/binary>> = DB, normal_collect_size(DB, Rest, [ThisRec | RecsCollected]). fast_collect(DB, Recs, Length) -> TDB = convert_db_to_tuple(DB, Length), fast_collect(TDB, Recs, Length, []). fast_collect(_DB, [], _Length, RecsCollected) -> lists:reverse(RecsCollected); fast_collect(DB, [NextRec | Rest], Length, RecsCollected) -> ThisRec = element(NextRec+1, DB), fast_collect(DB, Rest, Length, [ThisRec | RecsCollected]). fastest_collect(DB, Recs, Length) -> stream_extract(DB, Recs, Length). fastest_collect_size(DB, RecsAndSize) -> stream_extract(DB, RecsAndSize). %%==================================================================== %% Internal functions %%==================================================================== convert_db_to_tuple(DB, Length) -> convert_db_to_tuple(DB, Length, 0, size(DB), []). convert_db_to_tuple(_DB, _Length, Pos, DBSize, RecsCollected) when Pos >= DBSize -> list_to_tuple(lists:reverse(RecsCollected)); convert_db_to_tuple(DB, Length, Pos, DBSize, RecsCollected) -> <<_Skip:Pos/binary, Rec:Length/binary, _Rest/binary>> = DB, convert_db_to_tuple(DB, Length, Pos + Length, DBSize, [Rec | RecsCollected]).