dreamxyp 发表于 2013-10-21 00:48:10

异步gen_server进行port访问时性能严重下降的原因和应对方法...

在进行项目开发时,有这么一个需求:一个生产者不断产生消息,并将消息异步投递给消费者,异步投递不受任何限制,消费者进程内部将消息写入文件或者通过套接字发送该消息。看到这个需求,我想也没想,熟练地写下了如下代码:
API:start_link(FileName, DsgHost, DstPort) ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, , []).


deliver_to_file(Msg) -> deliver_to(file, Msg).
deliver_to_net(Msg) -> deliver_to(net, Msg).

deliver_to(Type, Msg) ->
    gen_server:cast(?SERVER, {deliver_to, Type, Msg}).gen_server callback:init() ->
    {ok, FD} = file:open(FileName,
      ),
    {ok, Socket} = gen_tcp:connect(DsgHost, DstPort,
      ),
    {ok, #state{file = FD, socket = Socket}}.



handle_cast({deliver_to, Type, Msg}, State) ->
    handle_msg(Type, Msg, State),
    {noreply, State};


handle_msg(Type, Msg, #state{file = File, socket = Socket}) when is_binary(Msg) ->
    case Type of
      file -> file:write(File, Msg);
      net -> gen_tcp:send(Socket, Msg)
    end;
handle_msg(Type, Msg, State) ->
    handle_msg(Type, term_to_binary(Msg), State).
压测函数编写如下:deliver_to_with_len_and_times(Type, Len, Times) ->
    Msg = makeup_log_by_len(Len),
    deliver_to_times(Type, Msg, Times).

deliver_to_times(Type, Msg, Times) when Times > 0 ->
    deliver_to(Type, Msg);
deliver_to_times(_Type, _Msg, 0) ->
    ok.

makeup_log_by_len(Len) ->
    list_to_binary(lists:duplicate(Len, $a)).
函数主要目的为异步地向consumer投递Times个长度为Len的消息。这段看似简单的代码,却在压测的时候产生了意想不到的效果:当投递消息个数较小时(<1000),handle_msg的处理qps上万,但是随着投递消息数目的增加(>10000),性能却急剧下降,最后仅有300+,使用vmstat、ifstat和top工具观察,磁盘写入和网络发送数据量均不大,但是cpu消耗却不小,这是肿么回事呢?
未完待续...

茶叶feng 发表于 2018-10-8 10:03:43

没后续了?
页: [1]
查看完整版本: 异步gen_server进行port访问时性能严重下降的原因和应对方法...