当前位置 : 主页 > 网络安全 > 测试自动化 >

性能 – Erlang:用于处理二进制部件列表的高内存使用率

来源:互联网 收集:自由互联 发布时间:2021-06-22
我在Erlang中有大量内存使用问题.将我的问题(MapReduce框架的一部分)减少到最小,请考虑以下代码: {match, Idx} = re:run(SomeBinary, "[A-Za-z0-9_]+",[global]),List = [ {binary:part(SomeBinary, Pos, Len), 1} || [
我在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),

处理15 MB二进制UTF-8编码文本,包含2672923个字,内存使用上限为2 GB.
regexp部分为1,2 GB,keysort()为800 MB.

即使有所有链接列表的东西,引用等,这怎么可能?
当我在计算后“暂停”进程时,内存使用量在几秒钟后减少到300MB.我在archlinux上运行Erlang R16B03.

PS 1:我也尝试直接从regexp返回二进制文件,但内存使用情况相同,性能稍差.

PS 2:处理30 MB文件完全杀死我的RAM并导致交换.

PS 3:在Rust中实现相同的逻辑,链接到PCRE lib for regexp(erlang也使用PCRE)的内存容量为200 MB

谢谢.

我的朋友告诉我部分解决方案.
而不是使用正则表达式,手动标记器执行得更好:

[{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]).

这会将正则表达式的1,2 GB内存使用量降低到可接受的值.
不幸的是,800 MB的列表:keysort(…)似乎是使用erlang的交易.

RegExps的执行速度通常比“手写”代码差.如果速度不是限制因素,RegExp有利于它的可读性和易于修改.

尽管一般的RegExps性能问题,在这个例子中高内存使用似乎是“re”模块中Erlang / PCRE绑​​定的内部实现中的问题.

网友评论