更新Erlang ETS表中所有值的最快方法是什么?

时间:2013-02-19 22:55:36

标签: performance erlang ets

我想将函数应用于ETS表中的所有元组:

该表是一个集合,每个键只出现一次。

我的表只包含相同类型的元组:

{Key, X, Y, VX, VY}

所有值均为::integer()

我想要做的是获得一定的价值并更新全部 我的元组有一个函数apply_vector/2

apply_vector({K, X, Y, 0, 0}, _Elapsed) ->
    {K, X, Y, 0, 0};

apply_vector({K, X, Y, VX, VY}, Elapsed) ->
    NewX = X + (VX * Elapsed),
    NewY = Y + (VY * Elapsed),
    {K, NewX, NewY, VX, VY}.

可能的解决方案

  • 如果我使用ets:foldl,我的插入内容可以在折叠过程中遍历,并且 导致无限(非常长)的循环。

  • 我可以使用ets:foldl准备新元组,然后插入整个元组 列表

  • 我可以插入新表,然后用新表替换旧表, 但是我不希望通过调用a来限制对表的访问 gen_server,该表必须随时可访问。

  • 我无法使用ets:update_element,因为我需要读取VX和VY值 更新X和Y。

  • 我知道有一些迭代器实用程序,但似乎没有人允许 传递乐趣。

我需要每隔1到5秒进行一次此更新。所以,解决方案是 最有效的10元组?有100个元组?有更多?

谢谢!

我保留一份船只清单,钥匙是船只ID,X和Y是地理位置 坐标,VX和VY代表运动的矢量:一个移位 一秒钟Elapsed是一个比率,自上次以来的秒数 更新。该表有助于随时了解每艘船的位置。

2 个答案:

答案 0 :(得分:1)

我可能会使用ets:foldl。

在我看来,您只需要对此数据进行迭代访问即可。所以你可以在这里使用记录列表。

另一种方法(我会选择)是为船主管并为每艘船创建一个gen_server。这样每艘船都有自己的状态,你实际上不需要遍历任何列表。

同时结帐qlc http://www.erlang.org/doc/man/qlc.html qlc让你在ets或mnesia表上使用list comrehensions。它可能具有与foldl相同的性能。

答案 1 :(得分:1)

没有什么好方法可以做你正在做的事情。

最近,我遇到了类似的问题(更新〜5000行,每秒一次)

这使我采取了完全不同的方法 那么,你需要存储解释的值吗?或者你可以在查找时计算价值吗?

如何存储: {K,X,Y,VX,VY,LastUpdateTime}

然后做一些像(无法编译的例子):

boats:get_all() -> % Record syntax would be smarter here, but it's an example...
  ets:foldl(?TABLE,[],fun(Row={Id,_,_,_,_,_},Acc) -> [{Id,calc(Row)}|Acc] end).

boats:get(Id) ->
  [Row] = ets:lookup(?TABLE,Id),
  calc(Row).

calc({_K,X,Y,VX,VY,LastUpdate}) ->
  {X + (VX * (now() - LastUpdate)), Y + (VY * (now() - LastUpdate)}

这允许您不要阻止genserver,也不必每5秒更新一次表。您基本上只会在每次船只报告时更新表格。