我有qlc
RefsBlocked = qlc:e(qlc:q([
Ref1 ||
{{Ref1, {pattern, {_Status1, _Pattern1, Limit1}}}, Count} <- dict:to_list(
qlc:fold(
fun({Key, _Ref2}, Acc) ->
dict:update_counter(Key, 1, Acc)
end,
dict:new(),
qlc:q([
{{Ref1, {pattern, {Status1, Pattern1, Limit1}}}, Ref2} ||
{Ref2, {status, Status2}} <- ets:table(Tmp),
{Ref3, {tag, Tag3}} <- ets:table(Tmp),
Ref2 =:= Ref3,
{Ref1, {pattern, {Status1, Pattern1, Limit1}}} <- ets:table(Tmp),
Ref =:= Ref1,
Status1 =:= Status2,
Pattern1 =:= Tag3
])
)
),
Count >= Limit1
], unique))
Run Code Online (Sandbox Code Playgroud)
其中Tmp是bag类型的ets,Ref是我需要测试的特定标识符.
Ets包含数百到数千个条目
{Ref1, {definition, {Tuple1}}}
{Ref1, {status, scheduled}}
{Ref1, …Run Code Online (Sandbox Code Playgroud) 我正在进入一个现有的(游戏)项目,其服务器组件完全用erlang编写.有时,从拥有它的过程中获取该系统的一部分数据(我对玩家56有多少个小部件感兴趣)可能会非常难以忍受.假设我可以找到拥有数据的进程,我可以将消息传递给该进程并等待它传回消息,但这不能很好地扩展到多台机器并且它会导致响应时间.
我一直在考虑用一个系统替换游戏中存在的许多任务,在这个系统中,多个进程经常访问的信息将存储在受保护的ets表中.表的所有者除了接收更新消息(玩家刚刚花了五个小部件)之外什么都不做,并相应地更新表.它会捕获所有异常,然后继续下一个更新消息.任何想知道玩家是否有足够的小部件来购买虚构的过程都只需要偷看桌子.(是的,我知道缓冲区中可能有一条消息可以减少小部件的数量,但我可以控制该问题.)
我担心我的问题不是一个问题而是更多的评论请求.我会推荐任何有用且充分解释或引用的内容.
这种实施的可能缺点是什么?我对锁定争用的细节很感兴趣,我可能会看到有一个作者 - 多个读者,我将在多台机器上分发这种问题,特别是:来自已经完成的人的输入这之前.
我正在构建一个erlang服务器.用户向服务器发送http请求以更新其状态.服务器上的http请求进程将用户状态消息保存在内存中.服务器每隔一分钟将所有消息发送到远程服务器并清除内存.如果用户在一分钟内多次更新其状态,则最后一条消息将覆盖前一条消息.重要的是,在读取所有消息并清除它们之间,没有其他进程能够写入状态消息.
实施它的最佳方法是什么?
带有字典的gen_server.密钥将是用户ID.dict:store/3将更新或创建状态.gen_server解决了"交易"问题.
mnesia表与ram_copies.处理事务,我不需要实现gen_server.这个解决方案有太多的开销吗?
ETS表更轻,并具有gen_server.是否可以在ETS中进行交易?在读取所有消息并清除它们之间锁定表格?
谢谢
((请原谅我,我在一个帖子中提出了不止一个问题.我认为它们是相关的.))
您好,我想知道,Erlang中有关每模块预编译数据的最佳实践.
示例:我有一个模块,它在一个熟悉的知识,复杂的正则表达式上运行.re:compile/2的文档说:"编译一次并执行多次比每次想要匹配时编译效率要高得多".由于没有指定re的mp()数据类型,因此如果你想要一个目标独立的梁,就不能在编译时放入,因此必须在运行时编译RegEx.((注意: re:compile/2只是一个例子.任何复杂的memoize函数都适合我的问题.))
Erlang的模块(可以)有一个-on_load(F/A)属性,表示在加载模块时应该执行一次的方法.因此,我可以将我的正则表达式编译为此方法并将结果保存在名为的新ets表中?MODULE.
我的问题是:
工作范例:
-module(memoization).
-export([is_ipv4/1, fillCacheLoop/0]).
-record(?MODULE, { re_ipv4 = re_ipv4() }).
-on_load(fillCache/0).
fillCacheLoop() ->
receive
{ replace, NewData, Callback, Ref } ->
true = ets:insert(?MODULE, [{ data, {self(), NewData} }]),
Callback ! { on_load, Ref, ok },
?MODULE:fillCacheLoop();
purge ->
ok
end
.
fillCache() ->
Callback = self(),
Ref = make_ref(),
process_flag(trap_exit, true),
Pid = …Run Code Online (Sandbox Code Playgroud) 我听说通过代码中的元组指定记录是一种不好的做法:我应该总是使用记录字段(#record_name{record_field = something})而不是普通元组{record_name, value1, value2, something}.
但是如何将记录与ETS表匹配?如果我有一个包含记录的表,我只能匹配以下内容:
ets:match(Table, {$1,$2,$3,something}
Run Code Online (Sandbox Code Playgroud)
很明显,一旦我在记录定义中添加了一些新字段,这种模式匹配就会停止工作.
相反,我想使用这样的东西:
ets:match(Table, #record_name{record_field=something})
Run Code Online (Sandbox Code Playgroud)
不幸的是,它返回一个空列表.
给具有数据的ETS表中,方式/ 1函数返回表中的各种属性,包括一个尺寸值是特定于行数,而不是实际尺寸.
有没有办法计算ETS表占用的内存量?
ets:new( mytable, [bag, named_table, compressed]),
ets:insert( mytable, { Key, Value } ),
....
ets:info ( mytable ).
Run Code Online (Sandbox Code Playgroud) ets:select vs mnesia:select哪个更好用.并且在插入和删除的情况下我们应该使用这两个中的一个.我正在研究ejabberd.Any指针?
我正在考虑使用Erlang的ETS作为新Elixir项目中用户搜索的缓存.根据用户输入,系统将使用昂贵的第三方API进行查找.
为了避免对同一个用户输入进行重复调用,我打算在外部API前放置一个缓存层,而ETS似乎是一个很好的选择.但是,由于用户输入的变化没有限制,我担心ETS表所需的存储空间将无限制地增长.
在我关于ETS的阅读中,我还没有看到其他人讨论过关于ETS中表格大小的问题.那是因为这是ETS的异常用例吗?
乍一看,我的偏好是限制ETS表中的条目数,并在达到限制后拒绝(即删除)最旧的条目...
在ETS中处理无限数量的条目是否有共同的策略?
假设我有一个ETS表所示:
I = ets:new(mytable, [named_table, set]).
ets:insert(I, {10,{10, 4 ,"description"}).
Run Code Online (Sandbox Code Playgroud)
我想更新的元素4使用ets:update_counter。
我以其他方式尝试过,但找不到解决方案,例如:
ets:update_counter(I, 10 , {3,1}).
** exception error: bad argument
in function ets:update_counter/3
called as ets:update_counter(mytable,10,{3,1})
Run Code Online (Sandbox Code Playgroud)
我想有结果为:
{10,{10, 5 ,"description"}
Run Code Online (Sandbox Code Playgroud) 我围绕ets表的选择性能进行了一些测试,并注意到了奇怪的行为。例如,我们有一个简单的ets表(没有任何特定选项),该表存储键/值-随机字符串和数字:
:ets.new(:table, [:named_table])
for _i <- 1..2000 do
:ets.insert(:table, {:crypto.strong_rand_bytes(10)
|> Base.url_encode64
|> binary_part(0, 10), 100})
end
Run Code Online (Sandbox Code Playgroud)
还有一个具有已知密钥的条目:
:ets.insert(:table, {"test_string", 200})
Run Code Online (Sandbox Code Playgroud)
现在有一个简单的愚蠢的基准测试函数,它试图test_string从ets表中多次选择并测量每次选择的时间:
test_fn = fn() ->
Enum.map(Enum.to_list(1..10_000), fn(x) ->
:timer.tc(fn() ->
:ets.select(:table, [{{:'$1', :'$2'},
[{:'==', :'$1', "test_string"}],
[:'$_']}])
end)
end) |> Enum.unzip
end
Run Code Online (Sandbox Code Playgroud)
现在,如果我看看最大时间,Enum.max(timings)它将返回的值大约是所有其他选择值的10倍。因此,例如:
iex(1)> {timings, _result} = test_fn.()
....
....
....
iex(2)> Enum.max(timings)
896
iex(3)> Enum.sum(timings) / length(timings)
96.8845
Run Code Online (Sandbox Code Playgroud)
在这里我们可以看到最大值几乎是平均值的10倍。
这里发生了什么事?它与GC,内存分配时间或诸如此类有关吗?您是否有任何想法,为什么从ets表中进行选择有时会导致这种变慢,或者如何进行分析。
UPD。
ets ×10
erlang ×9
elixir ×2
big-o ×1
dictionary ×1
ejabberd ×1
gen-server ×1
join ×1
memoization ×1
mnesia ×1
optimization ×1
performance ×1
process ×1
record ×1
tuples ×1