Performance Erlang:处理二进制部件列表的高内存使用率

Performance Erlang:处理二进制部件列表的高内存使用率,performance,memory,erlang,Performance,Memory,Erlang,我在Erlang中遇到了大量内存使用的问题。将我的问题(MapReduce框架的一部分)减少到最小,考虑这个代码: {match, Idx} = re:run(SomeBinary, <<"[A-Za-z0-9_]+">>,[global]), List = [ {binary:part(SomeBinary, Pos, Len), 1} || [{Pos, Len}] <- Idx], Sorted = lists:keysort(1, List), {

我在Erlang中遇到了大量内存使用的问题。将我的问题(MapReduce框架的一部分)减少到最小,考虑这个代码:

{match, Idx} = re:run(SomeBinary, <<"[A-Za-z0-9_]+">>,[global]),
List = [ {binary:part(SomeBinary, Pos, Len), 1}  || [{Pos, Len}] <- Idx],   
Sorted = lists:keysort(1, List),
{match,Idx}=re:run(SomeBinary,[global]),

List=[{binary:part(SomeBinary,Pos,Len),1}|[{Pos,Len}]我的朋友给我看部分解。 与使用regexp不同,手动标记器的性能要好得多:

[{X, 1} || X <- words(Bin)].

words(Bin) ->
    words_2(Bin, [], []).

words_2(<<C, Rest/binary>>, CAcc, WAcc) when
        (C >= $A) and (C =< $Z);
        (C >= $a) and (C =< $z);
        (C >= $0) and (C =< $9);
        C =:= $_ ->
    words_2(Rest, [C | CAcc], WAcc);
words_2(<<_, Rest/binary>>, [], WAcc) ->
    words_2(Rest, [], WAcc);
words_2(<<>>, [], WAcc) ->
    lists:reverse(WAcc);
words_2(Rest, CAcc, WAcc) ->
    words_2(Rest, [], [list_to_binary(lists:reverse(CAcc)) | WAcc]).
[{X,1}| | X
单词_2(Bin,[],[])。
单词_2(,CAcc,WAcc)当
(C>=$A)和(C=<$Z);
(C>=$a)和(C=<$z);
(C>=$0)和(C=<$9);
C=:=$\uuuz->
词语2(剩余[C | CAcc],WAcc);
单词2(,[],WAcc)->
文字2(剩余,[],WAcc);
单词2(,[],WAcc)->
列表:反向(WAcc);
单词2(Rest、CAcc、WAcc)->
单词2(Rest,[],[list_to_binary(list:reverse(CAcc))| WAcc])。
这将regexp的1,2 GB内存使用量减少到可接受的值。 不幸的是,对于lists:keysort(…)来说,800MB看起来像是使用erlang的一种交易

RegExp的性能通常比“手工编写”的代码差得多。在速度不是限制因素的情况下,RegExp的可读性和易修改性很好


尽管存在一般的RegExps性能问题,但本例中的高内存使用率似乎是“re”模块中Erlang/PCRE绑定的内部实现中的问题。

一种标记可能非常快的二进制文件的方法是二进制文件:split/3(尽管我没有测试过它)。如果使用全局选项并拆分非字母数字的任何字符,则可以在一次调用中获得单词列表:

查看示例2

编辑:为了澄清,下面将在所有空格、点、逗号和括号上拆分二进制文件,并对结果进行排序:

列表:排序(二进制:拆分(Bin、[、]、[global])


但是,这可能会导致结果列表中出现空字符串,例如,如果一行中有多个空格。如果这是一个问题,则可以在以后对其进行筛选。

可能这与此相关:有趣的阅读,但我认为这不是同一个问题。它们对不再使用的二进制文件有问题,这些二进制文件会一直挂在堆中,直到装束为止年龄收集。这里只是一个大的二进制文件和它的许多部分引用。