ETS不同表间的性能对比
1.测试目的
ETS表中存在4种不同类型,为探究不同类型表之间以及concurrency选项参数所带来的读写性能的差异,展开了此次测试。
2.测试环境
cpu:i5-7500
内存:16G
操作系统:Windows10 专业版
环境版本:Erlang OTP 19.3
3.测试流程
1、创建6种ETS表;
2、生成20万测试数据;
3、在单进程下测试写入和读取的耗时并记录;
4、对每种表开启3个进程进行写入和读取并记录耗时;
4.测试代码
单进程读写:
-module(test).
-author("Administrator").
-include("info.hrl").
%% API
-export([main/0]).
-compile(export_all).
main() ->
ets:new(?ETS_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_ORDERED_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_BAG, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_ORDERED_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_BAG_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
Data = test_data(),
Tabs = [?ETS_SET, ?ETS_SET_CON, ?ETS_ORDERED_SET, ?ETS_ORDERED_SET_CON, ?ETS_BAG, ?ETS_BAG_CON],
lists:foreach(
fun(Tab) ->
{Insert_Time, _} = timer:tc(test, insert, [Tab, Data]),
io:format("insert ~p:~p MincSeconds~n", [Tab, Insert_Time]),
{Lookup_Time, _} = timer:tc(test, lookup, [Tab, Data]),
io:format("lookup ~p:~p MincSeconds~n", [Tab, Lookup_Time]),
ets:delete_all_objects(Tab)
end, Tabs),
ok
.
insert(Tab, Data) ->
lists:foreach(fun(Item) -> ets:insert(Tab, Item), ets:insert(Tab, Item), ets:insert(Tab, Item) end, Data),
ok.
lookup(Tab, Data) ->
lists:foreach(fun(Item) -> ets:lookup(Tab, element(1, Item)) end, Data),
ok.
test_data() ->
lists:map(
fun(_) ->
{rand_str(8), rand_str(11), rand:uniform(98), rand:uniform(2)}
end, lists:seq(1, 200000))
.
rand_str(Length) ->
Str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
lists:map(fun(_) -> lists:nth(rand:uniform(string:len(Str)), Str) end, lists:seq(1, Length)).
多进程读:
-module(t).
-author("Administrator").
-include("info.hrl").
%% API
-export([main/0]).
-compile(export_all).
main() ->
ets:new(?ETS_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_ORDERED_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_BAG, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_ORDERED_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_BAG_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
Data = test_data(),
Tabs = [?ETS_SET, ?ETS_SET_CON, ?ETS_ORDERED_SET, ?ETS_ORDERED_SET_CON, ?ETS_BAG, ?ETS_BAG_CON],
lists:foreach(
fun(Tab) ->
insert(Tab, Data)
end, Tabs),
lists:foreach(
fun(_) -> lists:foreach(
fun(Tab) -> spawn(
fun() ->
{Insert_Time, _} = timer:tc(test, lookup, [Tab, Data]),
io:format("lookup ~p:~p MincSeconds~n", [Tab, Insert_Time])
end)
end, Tabs)
end, lists:seq(1, 3)),
ok
.
insert(Tab, Data) ->
lists:foreach(fun(Item) -> ets:insert(Tab, Item) end, Data),
ok.
lookup(Tab, Data) ->
lists:foreach(fun(Item) -> ets:lookup(Tab, element(1, Item)) end, Data),
ok.
test_data() ->
lists:map(
fun(_) ->
{rand_str(8), rand_str(11), rand:uniform(98), rand:uniform(2)}
end, lists:seq(1, 200000))
.
rand_str(Length) ->
Str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
lists:map(fun(_) -> lists:nth(rand:uniform(string:len(Str)), Str) end, lists:seq(1, Length)).
多进程写:
-module(t1).
-author("Administrator").
-include("info.hrl").
%% API
-export([main/0]).
-compile(export_all).
main() ->
ets:new(?ETS_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_ORDERED_SET, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_BAG, [named_table, public, set, {read_concurrency, false}, {write_concurrency, false}]),
ets:new(?ETS_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_ORDERED_SET_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
ets:new(?ETS_BAG_CON, [named_table, public, set, {read_concurrency, true}, {write_concurrency, true}]),
Data = test_data(),
Tabs = [?ETS_SET, ?ETS_SET_CON, ?ETS_ORDERED_SET, ?ETS_ORDERED_SET_CON, ?ETS_BAG, ?ETS_BAG_CON],
lists:foreach(
fun(_) -> lists:foreach(
fun(Tab) -> spawn(
fun() ->
{Insert_Time, _} = timer:tc(test, insert, [Tab, Data]),
io:format("insert ~p:~p MincSeconds~n", [Tab, Insert_Time])
end)
end, Tabs)
end, lists:seq(1, 3)),
ok
.
insert(Tab, Data) ->
lists:foreach(fun(Item) -> ets:insert(Tab, Item) end, Data),
ok.
lookup(Tab, Data) ->
lists:foreach(fun(Item) -> ets:lookup(Tab, element(1, Item)) end, Data),
ok.
test_data() ->
lists:map(
fun(_) ->
{rand_str(8), rand_str(11), rand:uniform(98), rand:uniform(2)}
end, lists:seq(1, 200000))
.
rand_str(Length) ->
Str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
lists:map(fun(_) -> lists:nth(rand:uniform(string:len(Str)), Str) end, lists:seq(1, Length)).
5.测试结果
单进程:
数据量:20W
耗时(毫秒) | insert | lookup |
---|---|---|
set | 344 | 203 |
set(concurrency) | 360 | 234 |
ordered_set | 468 | 391 |
ordered_set(concurrency) | 454 | 390 |
bag | 344 | 234 |
bag(concurrency) | 375 | 266 |
多进程:
数据量:20W
耗时(毫秒) | insert | lookup |
---|---|---|
set | 1719 | 1515 |
set(concurrency) | 1318 | 1025 |
ordered_set | 2113 | 1890 |
ordered_set(concurrency) | 1433 | 1208 |
bag | 1827 | 1661 |
bag(concurrency) | 1771 | 1411 |
6.测试总结
整体读写性能:set>bag>ordered_set;
在单进程中,currency选项参数对性能影响不大;
在多进程中,currency选项参数能提高整体读写性能;