Erlang之ETS学习03

今天我们来看看ets中两种获取表数据的方法之间的区别

  • ets:tab2list(Tab)
  • ets:match(Tab,‘_’)

二者都是返回一个 ETS 表的所有对象数据的列表
我们查看源码可以知道tab2list(Tab)底层是直接调用的ets:match_object(Tab, ‘‘)方法,现在我们只需要讨论ets:match(Tab,’’)和ets:match_object(Tab, ‘_’)的效率问题

1. 我们先来看一下代码

-module(auto_insert).
-export([start/1, insert_data/2]).

start(Count) ->
	% 创建一个名为my_table的set类型的ets表
	Tab = ets:new(my_table, [set, named_table, public]),
	% 插入大量数据
	insert_data(Tab, Count),
	% 测量ets:match/2的效率
	{MatchTime, _MatchResult} = timer:tc(fun() -> ets:match(Tab, '_') end),
	io:format("ets:match: ~p microseconds~n", [MatchTime]),
	% 测量ets:tab2list/1的效率
	{ListTime, _ListResult} = timer:tc(fun() -> ets:tab2list(Tab) end),
	io:format("ets:tab2list: ~p microseconds~n", [ListTime]).

insert_data(Tab, Count) ->
	Data = [ {N, "data" ++ integer_to_list(N)} || N <- lists:seq(1, Count) ],
	lists:foreach(fun({Key, Value}) -> ets:insert(Tab, {Key, Value}) end, Data).


我们逐渐递增插入数据库的数据,来看看两者的性能差距是如何

%% 这里可以看出在十万条数据的情况下两者性能只差了1000微秒也就是0.001秒
19> auto_insert:start(100000).
ets:match: 15000 microseconds
ets:tab2list: 16000 microseconds
ok
%%当我把数据提升到一百万时,两者之间的区别就可以明显看出来了,两者之间整整差了两倍还多
20> auto_insert:start(1000000).
ets:match: 94000 microseconds
ets:tab2list: 219000 microseconds
ok
%%当我把数据提升到五百万时,两者之间的区别就可以明显看出来了,两者之间比例正在逐渐拉大
21> auto_insert:start(1000000).
ets:match: 484000 microseconds
ets:tab2list: 1297000 microseconds
ok
%%当我把数据提升到一千万时,两者之间的区别就可以明显看出来了,两者之间差距接近三倍
22> auto_insert:start(10000000).
ets:match: 1078000 microseconds
ets:tab2list: 3031000 microseconds
ok

一千万时需要内存差不多5个G左右,一个亿就不测了大概需要50个G内存,碍于电脑内存瓶颈只有32G,影响测试
在这里插入图片描述
测试结果为当数据量越来越大时,两种方法的性能差距趋近于1:3.
为什么两者性能差距如此之大呢?

我们改变一下代码,输出一下两个方法返回的结果就知道了

-module(auto_insert).
-export([start/0, insert_data/2]).

start() ->
	% 创建一个名为my_table的set类型的ets表
	Tab = ets:new(my_table, [set, named_table, public]),
	% 插入大量数据
	insert_data(Tab, 5),
	% 测量ets:match/2的效率
	{MatchTime, _MatchResult} = timer:tc(fun() -> ets:match(Tab, '_') end),
	io:format("ets:match: ~p microseconds~n,Result:~p", [MatchTime, _MatchResult]),
	% 测量ets:tab2list/1的效率
	{ListTime, _ListResult} = timer:tc(fun() -> ets:tab2list(Tab) end),
	io:format("ets:tab2list: ~p microseconds~n,Result:~p", [ListTime, _ListResult]).

insert_data(Tab, Count) ->
	Data = [{N, "data" ++ integer_to_list(N)} || N <- lists:seq(1, Count)],
	lists:foreach(fun({Key, Value}) -> ets:insert(Tab, {Key, Value}) end, Data).
ets:match: 0 microseconds
Result:[[],[],[],[],[]]
ets:tab2list: 0 microseconds
Result:[{1,"data1"},{3,"data3"},{4,"data4"},{2,"data2"},{5,"data5"}]

ets:match(Tab,‘')只返回了空的数组而
ets:match_object(Tab, '
’)返回了所有正常数据
这是我们改变一下代码,使用变量’$1’代替’_’

-module(auto_insert).
-export([start/0, insert_data/2]).

start() ->
	% 创建一个名为my_table的set类型的ets表
	Tab = ets:new(my_table, [set, named_table, public]),
	% 插入大量数据
	insert_data(Tab, 100000),
	% 测量ets:match/2的效率
	{MatchTime, _MatchResult} = timer:tc(fun() -> ets:match(Tab, '$1') end),
	{ListTime, _ListResult} = timer:tc(fun() -> ets:tab2list(Tab) end),
	io:format("Result:~p~n", [_MatchResult]),
	io:format("Result:~p~n", [_ListResult]),
	io:format("ets:match: ~p microseconds~n", [MatchTime]),
	% 测量ets:tab2list/1的效率
	io:format("ets:tab2list: ~p microseconds~n", [ListTime]).

insert_data(Tab, Count) ->
	Data = [{N, "data" ++ integer_to_list(N)} || N <- lists:seq(1, Count)],
	lists:foreach(fun({Key, Value}) -> ets:insert(Tab, {Key, Value}) end, Data).
%%十万个数据时
ets:match: 31000 microseconds
ets:tab2list: 16000 microseconds
%%一百万个数据时
ets:match: 218000 microseconds
ets:tab2list: 235000 microseconds
%%这里一千万内存不足,只测了五百万万个数据时
ets:match: 2719000 microseconds
ets:tab2list: 2672000 microseconds

这是我们发现在十万个数据量的情况下前者是后者的接近两倍,但是在一百万和一千万时是两者性能几乎相同
so
ets:match/2返回一个包含匹配项的列表,每个匹配项是一个元组,其中包含键和值。
ets:match_object/2返回一个包含匹配项的列表,每个匹配项是一个元组,其中只包含值。
因此,ets:match/2需要将每个匹配项的键和值都包含在返回值中,而ets:match_object/2只需要将值包含在返回值中。这可能会导致ets:match/2的性能比ets:match_object/2差。
此外,ets:match/2和ets:match_object/2的性能还取决于ets表的大小和类型。一般来说,ets表越大,性能越差。如果你需要频繁地查找匹配项,可以考虑使用其他数据结构,如Ets的索引或B树。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值