Erlang 将ets表用于gen_服务器状态

Erlang 将ets表用于gen_服务器状态,erlang,gen-server,Erlang,Gen Server,我正在编写一个gen_服务器,我想将一个ets表作为状态保存,然后在其他地方创建了一个ets表。如何将其添加到gen_服务器的状态 我想使用ets表,而不是为它创建一个新字典,因为我想节省内存 另外,如何迭代ets表?我想迭代或读取表中的每个值并检查值,然后根据值执行两个选项之一 将ets表转换为列表并遍历列表是否更容易 谢谢一些建议: 阅读ETS手册页:erl-man ETS ETS表格通过其名称(在命名表格选项的情况下)或其表格id进行标识。将该信息传递给gen_服务器并保持其状态: -r

我正在编写一个gen_服务器,我想将一个ets表作为状态保存,然后在其他地方创建了一个ets表。如何将其添加到gen_服务器的状态

我想使用ets表,而不是为它创建一个新字典,因为我想节省内存

另外,如何迭代ets表?我想迭代或读取表中的每个值并检查值,然后根据值执行两个选项之一

将ets表转换为列表并遍历列表是否更容易

谢谢

一些建议:

  • 阅读ETS手册页:
    erl-man ETS
  • ETS表格通过其名称(在
    命名表格
    选项的情况下)或其表格id进行标识。将该信息传递给gen_服务器并保持其状态:

    -record(state, { ..., tbl = none }).
    
    
    init([TableID]) ->
        ...,
        {ok, #state { tbl = TableID }}.
    
ETS可能不会节省那么多内存。稍后的Erlang/OTP版本将出现一个新的标志,其中ETS表可以
压缩
,因此它们的内容在存储前压缩,在读取时解压缩(这会带来计算开销)

要遍历ETS表,有几个选项
ets:first/1ets:next/2
就是这样一个接口<代码>ets:foldl/3 ets:foldr/3另一个<代码>ets:match/3为您提供了一个可以继续行走的光标<代码>ets:select比match更通用

把它变成一个列表会更容易吗?这要看情况。ETS表的强大之处在于,它们有一个选项
{keypos,N}
来定义存储元素的键<代码>ets:查找(?制表符,键)非常快,因此可以快速查找键。清单并非如此。但另一方面,如果总是遍历所有列表,则可能是一个更简单的解决方案(只要不在进程之间传递大型列表)

也许应该避免将整个表变成一个列表并遍历它。您将在内存中生成列表,然后遍历它,这是非常昂贵的。最好一次遍历一点,这样活动内存量就比较少。

一些建议:

  • 阅读ETS手册页:
    erl-man ETS
  • ETS表格通过其名称(在
    命名表格
    选项的情况下)或其表格id进行标识。将该信息传递给gen_服务器并保持其状态:

    -record(state, { ..., tbl = none }).
    
    
    init([TableID]) ->
        ...,
        {ok, #state { tbl = TableID }}.
    
ETS可能不会节省那么多内存。稍后的Erlang/OTP版本将出现一个新的标志,其中ETS表可以
压缩
,因此它们的内容在存储前压缩,在读取时解压缩(这会带来计算开销)

要遍历ETS表,有几个选项
ets:first/1ets:next/2
就是这样一个接口<代码>ets:foldl/3 ets:foldr/3另一个<代码>ets:match/3为您提供了一个可以继续行走的光标<代码>ets:select比match更通用

把它变成一个列表会更容易吗?这要看情况。ETS表的强大之处在于,它们有一个选项
{keypos,N}
来定义存储元素的键<代码>ets:查找(?制表符,键)非常快,因此可以快速查找键。清单并非如此。但另一方面,如果总是遍历所有列表,则可能是一个更简单的解决方案(只要不在进程之间传递大型列表)


也许应该避免将整个表变成一个列表并遍历它。您将在内存中生成列表,然后遍历它,这是非常昂贵的。最好一次遍历一点,这样活动内存量就比较少。

谢谢。我想正确处理一些问题。在创建二进制位字段之前,我们为torrent表示创建一个ets表。我想阅读ets表并从所需的块中创建一个队列。对等处理程序将访问此队列以避免重复请求。正确接收区块后,将从队列中删除该项目,并更新位字段或torrent状态。我想跟踪torrent状态,以便GUI显示进度条等。我想知道是应该从ets表创建字典,还是直接编辑该表?etorrent使用两个阶段的过程。每个对等方单独读取ETS表并决定它想要什么。但是表是受保护的,因此所有实际的分配都发生在第二个阶段:调用控制块管理器,它序列化对表的访问,这样就不会有两个进程意外地获取同一块。它在提供进度和安全性的同时产生有效的并行性。如果数据块不在内存中(例如ets表),则数据块不在磁盘上。我想区块管理器可以跟踪正在抓取的内容并阻止重复抓取,但通过抓取或访问数据,这是在发送整个二进制文件之前完成的吗?因为你会问:我直接将16K区块二进制数据发送到磁盘上的正确位置,而从不将它们保留在内存中。因此,我们可以尽快使用kernels磁盘缓存层(它比我们做得更好),并将内存保留在客户机中。ETS表中存储的是磁盘上的内容,而不是磁盘上的内容。在工件完成后,我们从磁盘读取整个工件,并对其进行SHA1,然后对其进行验证/失效。如果我们很快得到一块,磁盘缓存会保存所有的东西,所以价格不高。谢谢。我想正确处理一些问题。在创建二进制位字段之前,我们为torrent表示创建一个ets表。我想阅读ets表并从所需的块中创建一个队列。对等处理程序将访问此队列以避免重复请求。正确接收区块后,将从队列中删除该项目,并将其删除