Last active
August 29, 2015 14:03
-
-
Save sile/7a7ae89380b0e8cac28e to your computer and use it in GitHub Desktop.
Erlang/OTP 17.1でmapsを使用する場合の注意点 ref: http://qiita.com/sile/items/48f1268d2e03915ca479
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(bench). | |
-export([bench/0]). | |
-spec bench() -> [Result] when | |
Result :: {module(), ElementSize::pos_integer(), InsertAverageNanoSeconds::non_neg_integer()}. | |
bench() -> | |
ElementSizeList = [1, 10, 100, 1000, 10000, 100000], | |
InputList = [shuffle(lists:seq(0, Size - 1)) || Size <- ElementSizeList], | |
ModuleList = [dict, gb_trees, maps], | |
lists:sort( | |
[do_bench(Module, Input) || Module <- ModuleList, | |
Input <- InputList]). | |
-spec do_bench(module(), [non_neg_integer()]) -> Result when | |
Result :: {module(), ElementSize::pos_integer(), InsertAverageNanoSeconds::non_neg_integer()}. | |
do_bench(Module, Input) -> | |
ElementSize = length(Input), | |
LoopCount = 100000 div ElementSize, % 一回のベンチマーク中の挿入操作の回数を等しくさせるために、ループ数で調整する | |
Empty = make_empty(Module), | |
Fun = get_insert_fun(Module), | |
{TotalMicroSeconds, _} = | |
timer:tc(fun () -> bench_loop(LoopCount, Empty, Fun, Input) end), | |
AverageNanoSeconds = round((TotalMicroSeconds * 1000) / 100000), | |
{Module, ElementSize, AverageNanoSeconds}. | |
-spec make_empty(module()) -> term(). | |
make_empty(dict) -> dict:new(); | |
make_empty(gb_trees) -> gb_trees:empty(); | |
make_empty(maps) -> maps:new(). | |
-spec get_insert_fun(module()) -> fun ((term(), term(), term()) -> term()). | |
get_insert_fun(dict) -> fun dict:store/3; | |
get_insert_fun(gb_trees) -> fun gb_trees:enter/3; | |
get_insert_fun(maps) -> fun maps:put/3. | |
-spec shuffle(list()) -> list(). | |
shuffle(List) -> | |
[X||{_,X} <- lists:keysort(1, [{random:uniform(), N} || N <- List])]. | |
-spec bench_loop(non_neg_integer(), term(), function(), [non_neg_integer()]) -> ok. | |
bench_loop(0, _, _, _) -> ok; | |
bench_loop(LoopCount, Empty, Fun, Input) -> | |
_ = lists:foldl(fun (N, Acc) -> Fun(N, N, Acc) end, Empty, Input), | |
bench_loop(LoopCount - 1, Empty, Fun, Input). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* maps:get/2 | |
* return value if key *matches* a key in the map | |
* exception bad_key if none matches | |
*/ | |
int erts_maps_get(Eterm key, Eterm map, Eterm *value) { | |
Eterm *ks,*vs; | |
map_t *mp; | |
Uint n,i; | |
mp = (map_t*)map_val(map); | |
n = map_get_size(mp); | |
if (n == 0) | |
return 0; | |
ks = map_get_keys(mp); | |
vs = map_get_values(mp); | |
if (is_immed(key)) { | |
for( i = 0; i < n; i++) { | |
if (ks[i] == key) { | |
*value = vs[i]; | |
return 1; | |
} | |
} | |
} | |
for( i = 0; i < n; i++) { | |
if (EQ(ks[i], key)) { | |
*value = vs[i]; | |
return 1; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment