【问题标题】:Cowboy web server application very slowCowboy Web 服务器应用程序非常慢
【发布时间】:2013-08-26 08:03:54
【问题描述】:

我目前正在使用最小的 Web 服务器,例如 Cowboy。我想在 URL 中传递一个数字,加载文件的行,对这些行进行排序并打印中间的元素以测试 IO 和排序。 因此代码会加载 /123 之类的路径,用数字填充“00123”,加载文件“input00123.txt”并对其内容进行排序,然后返回“input00123.txt 0.50000”之类的内容。

同时我有一个测试工具,它同时发出 50 个请求,其中只有 2 个得到答复,其余的超时。

我的处理程序如下所示:

-module(toppage_handler).  
-export([init/3]).   
-export([handle/2]).   
-export([terminate/3]).    

init(_Transport, Req, []) ->
    {ok, Req, undefined}.

readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    get_all_lines(Device, []).

get_all_lines(Device, Accum) ->
   case io:get_line(Device, "") of
       eof  -> file:close(Device), Accum;
       Line -> get_all_lines(Device, Accum ++ [Line])
   end.

handle(Req, State) ->
    {PathBin, _} = cowboy_req:path(Req),
    case PathBin of
       <<"/">> -> Output = <<"Hello, world!">>;
       _ -> PathNum = string:substr(binary_to_list(PathBin),2),
            Num = string:right(PathNum, 5, $0),
            Filename = string:concat("input",string:concat(Num, ".txt")),
            Filepath = string:concat("../data/",Filename),
            SortedLines = lists:sort(readlines(Filepath)),
            MiddleIndex = erlang:trunc(length(SortedLines)/2),
            MiddleElement = lists:nth(MiddleIndex, SortedLines),
            Output = iolist_to_binary(io_lib:format("~s\t~s",[Filename,MiddleElement]))
    end,
    {ok, ReqRes} = cowboy_req:reply(200, [], Output, Req),
    {ok, ReqRes, State}.

terminate(_Reason, _Req, _State) ->
    ok.

我在 Windows 上运行它以将其与 .NET 进行比较。有什么可以提高性能的,比如在线程中运行排序/IO,或者我该如何改进它?使用 cygwin 运行结果并没有太大变化,我得到了大约 5-6 个请求的响应。

提前致谢!

【问题讨论】:

  • 我可能是错的,但我想你的输出可能仍然是一个 iolist;它不需要转换。顺便提一下,Erlang 在 Windows 平台上并不是最优的,性能会受到严重影响。

标签: erlang webserver cowboy


【解决方案1】:

最明显的问题:get_all_lines 是 O(N^2),因为列表连接 (++) 是 O(N)。 Erlang 列表类型是一个单链表。这里的典型做法是使用“cons”运算符,附加到列表的头部,并在末尾使用反向累加器:

get_all_lines(Device, Accum) ->
   case io:get_line(Device, "") of
       eof  -> file:close(Device), lists:reverse(Accum);
       Line -> get_all_lines(Device, [Line | Accum])
   end.

binary 标志传递给file:open 以使用二进制文件而不是字符串(在Erlang 中只是字符列表),它们对内存和CPU 更友好。

【讨论】:

  • 酷,谢谢!现在所有请求都会得到答复,但这需要 26 秒,而其他应用程序则在 2 秒内响应。我会看看 Yaws,尤其是非阻塞 IO 应该会改善我猜的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
相关资源
最近更新 更多