我尝试创建一个Erlang内存数据存储区来接收消息并将它们添加到列表中。这是目前的化身。问题是,我每秒收到大约200条消息,这很容易耗尽可用的内存。
每分钟一次,我发送一条{write,Pid}消息,该消息应清除并清理此列表,但它看起来不像是垃圾收集。
我做错了什么?我想我是从完全错误的方向接近这个......
datastore(Db) ->
receive
{put, Data} ->
datastore(lists:concat([Data,Db]));
{write, Responder} ->
ScratchName = "ScratchFile.dat",
{ok, ScratchDevice} = file:open(ScratchName,[write]),
file:write(ScratchDevice,Db),
ok = file:close(ScratchDevice),
Responder ! {load, ScratchName},
datastore([])
end.
答案 0 :(得分:1)
第一个自发评论是文件:open将打开文件,截断它,然后写入它。因此,每次循环都会覆盖以前的任何数据。因此,如果响应者加载文件的速度很慢,那么可能会有文件中没有您想要的数据。
第二反应是你不必自己做这个缓冲。如果你打开带有{delayed_write,Size,Delay}选项的文件,并将Size和Delay设置为适合你目的的值,那么你只需要一直写下来就可以得到你想要实现的内容。
第三个反应是,如果您使用文件在系统的不同部分之间进行通信,那么您可能做错了。你想做什么?
PS。
如果您需要一个新的随机文件名,您可以使用erlang轻松生成一个:now / 0和io_lib:format / 2。作为额外的奖励,他们将按创作顺序排序。
答案 1 :(得分:0)
这是Erlang中一种非常错误的缓冲方式。 ETS
(http://www.erlang.org/doc/man/ets.html
)等数据结构设计用于轻松处理数千和数百万的IN-MEMORY Erlang数据结构。请不要使用Lists
或Queues
来处理太多数据。如果您的代码的一部分将处理应用程序的其他部分应该使用的数据,但是您知道与生成或获取数据的部分相比,消费者将以更慢的速度执行此操作,那么您需要一种更强大的缓冲方式(ETS Tables
)。
另一件事是,通常,流程是系统中的一个故障点。如果一个进程用于缓冲或保留非常重要的数据,即使该数据是即时的但对系统至关重要,那么当进程退出或死亡时会发生什么? ETS表的设计方式使得它们可以提供对所有进程的数据访问,甚至是同一VM(类型public
)内的应用程序。通过这种方式,所有进程都可以使用数据,尽可能多地读取数据(并发),但您要做的是通过使用一个writer / updater来确保一致性。
与流程失败的频率相比,ETS表在应用程序中很少失败。最近,我们引入了一种帮助我们在失败的ETS表中兑换数据的方法( ets:give_away/3
)。
另一方面,在上面的评论中,您提到您正在为一家大公司工作。通常,对于大型团队,根据您正在开发的应用程序的性质,您可以更好地评估多个选项并针对多个选项进行密集测试。为避免副作用,最好确定哪些数据结构最适合用于哪些数据结构。例如,对于内存存储,每秒能够处理200条消息,如果测试正确,Lists
和Files
将失败对抗ETS Tables
。