2013-08-23 4 views
0

저는 현재 카우보이와 같은 최소한의 웹 서버로 놀고 있습니다. 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. 

나는 .NET과 비교하기 위해 Windows에서이 작업을 실행하고 있습니다. 스레드에서 정렬/IO를 실행하거나 성능을 향상시킬 수있는 것과 같이 성능을 향상시킬 수있는 방법이 있습니까? cygwin으로 실행하면 결과가 많이 바뀌지 않고 약 5-6 개의 요청이 응답됩니다.

미리 감사드립니다.

+0

내가 틀릴 수도 있지만 출력물이 iolist로 남을 수 있다고 상상해보십시오. 변환 할 필요가 없습니다. 필자는 Erlang이 Windows 플랫폼에서 최적이 아니라는 점을 지적 할 것입니다. 성능은 그리 평범하지 않습니다. – troutwine

답변

1

목록 연결 (++)이 O (N)이기 때문에 get_all_lines은 O (N^2)입니다. 얼랭 목록 유형은 단독으로 연결된 목록입니다.

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 친숙합니다.

+0

쿨, 고마워! 모든 요청이 지금 응답을 얻지 만 26 초가 걸리지 만 다른 애플리케이션은 2 초 안에 응답합니다. 나는 Yaws를 살펴볼 것입니다. 특히 비 차단 입출력은 내가 추측 한 결과를 향상시켜야합니다. – sibbl

관련 문제