1

我想对 ETS 表中的所有元组应用一个函数:

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

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

{Key, X, Y, VX, VY}

所有值都是::integer()

我想要做的是有一个特定的值 Elapsed 并用一个函数更新我所有的元组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,我的插入可能会在折叠期间被遍历,并导致无限(非常长)循环。

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

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

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

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

我需要每 1 - 5 秒进行一次更新。那么,对于 10 个元组,哪种解决方案最有效?有 100 个元组?有更多?

谢谢你 !

I Keep a list of boats,Key是Boat ID,X和Y是地理坐标,VX和VY代表运动向量:一秒的位移。Elapsed 是一个比率,即自上次更新以来的秒数。该表有助于随时了解每艘船的位置。

4

2 回答 2

1

我可能为此使用 ets:foldl。

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

另一种方法(我会采用)是放置一个船监督器并为每艘船创建一个 gen_server。这样每艘船都有自己的状态,你实际上不需要遍历任何列表。

还可以查看 qlc http://www.erlang.org/doc/man/qlc.html qlc 让您在 ets 或 mnesia 表上使用列表理解。不过,它可能具有与 foldl 相同的性能。

于 2013-02-20T09:03:47.207 回答
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 秒更新一次表。您基本上只会在每次船报告时更新表格。

于 2013-02-20T09:17:04.133 回答