我正在通过在mnesia下的数据库表中插入大约1000个用户和每个有1000个联系人的用户来测试应用程序,并且在插入某些部分时我得到的错误如下:
Crash dump was written to: erl_crash.dump
binary_alloc: Cannot allocate 422879872 bytes of memory (of type "binary").
Aborted
我用 erl + MBas af (B-binary allocator af-a)启动了erl模拟器并再次尝试,但错误相同,
note ::我正在使用erlang r12b版本,系统ram在ubuntu 10.04上是8gb 我可以知道如何解决它吗?
记录定义是:
%%数据库 的 -record(数据库,{DBID,GUID,数据})。
%%更改日志 的 -record(更新日志,{DBID,时间戳,变更表,类型})。
这里的数据是vcard(联系信息),dbid和type是“contacts”,guid是服务器自动生成的整数
数据库记录包含所有用户的所有vcard数据。如果有1000个用户,每个用户有1000个联系人,那么我们将有10 ^ 6个记录。
changelog记录将包含在该时间戳对数据库表进行的更改
创建表的代码是::
mnesia:create_table(database, [{type,bag}, {attributes,Record_of_database},
{record_name,database},
{index,guid},
{disc_copies,[node()]}])
mnesia:create_table(changelog, [{type,set}, {attributes,Record_of_changelog},
{record_name,changelog},
{index,timestamp},
{disc_copies,[node()]}])
在桌面上插入记录是:
commit_data(DataList = [#database{dbid=DbID}|_]) ->
io:format("commit data called~n"),
[mnesia:dirty_write(database,{database,DbId,Guid,Key})|| {database,DbId,Guid,X}<-DataList].
write_changelist(Username,Dbname,Timestamp,ChangeList) ->
Type="contacts",
mnesia:dirty_write(changelog,{changelog,DbID,Timestamp,ChangeList,Type}).
答案 0 :(得分:0)
我认为列表DataList
很大,不应该立即从远程节点发送。它应该以小件发送。客户端可以从客户端生成的DataList中逐个发送项目。此外,因为在插入过程中出现此问题,我认为我们应该并行列表理解。我们可以有一个并行映射,对于列表中的每个项目,插入在单独的过程中完成。然后,我也认为列表理解仍然存在问题。变量Key
未绑定,变量X
未使用。否则,整个方法可能需要改变。让我们看看别人怎么想。感谢
答案 1 :(得分:0)
当ERTS内存分配器名为binary_alloc没有为二进制堆分配内存时,通常会发生此错误。使用erlang检查当前二进制堆大小:system_info()或erlang:memory()或erlang:memory(二进制)命令。如果二进制堆大小很大,则运行erlang:garbage_collect()以释放二进制堆中所有未引用的二进制对象。这将释放记忆..
答案 2 :(得分:0)
如果您使用长字符串(它只是erlang中的列表)用于vcard或其他一些字符串,它们会占用大量内存。 如果是这种情况,则将它们更改为二进制以禁止内存使用(在插入到mnesia之前使用list_to_binary)。
这可能没有用,因为我不知道你的数据结构(类型,长度等)......