2009-09-09 4 views
3

하나의 프로세스는 비동기 소켓에 각 메시지에 서버를 듣고 {TCP는, 소켓, 빈}이이 버퍼를 있어요 소요 : 일부 이벤트에gluing 바이너리 (list_to_binary)의 비용은 얼마입니까?

Data = list_to_binary([Buffer, Bin]), 
    {next_state, 'READY', State#state{buffer = Data}}. 

을가 플러시 버퍼 :

'READY'({flush}, #state{buffer = Buffer} = State) -> 
    {reply, {Buffer}, 'READY', State#state{buffer = <<>>}}. 

비싼가요 ? 목록을 만들고 list_to_binary (목록 : reverse())를 한 번만 플러시하는 것이 더 좋은가?

+3

이것은 현재 구현에 대한 이론화보다 벤치 마크에서 더 잘 대답하는 질문입니다. – Christian

+0

설정시 버퍼가 하나의 바이너리로 반환되어야합니다. 사용자가 버퍼를 '덩어리'로 처리하거나 iodata() 형식을 처리 할 수 ​​있습니까? – Zed

답변

2

첫 번째 방법은 (내 플랫폼에서 약 3000 배) 두 번째 방법보다 훨씬 느린 것으로 나타납니다

-module(test). 
-export([test/0, performance_test/4]). 

-define(ITERATIONS, 100000). 
-define(NEW_DATA, <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>). 

accumulate_1(AccumulatedData, NewData) -> 
    list_to_binary([AccumulatedData, NewData]). 

extract_1(AccumulatedData) -> 
    AccumulatedData. 

accumulate_2(AccumulatedData, NewData) -> 
    [NewData | AccumulatedData]. 

extract_2(AccumulatedData) -> 
    list_to_binary(lists:reverse(AccumulatedData)). 

performance_test(AccumulateFun, ExtractFun) -> 
    {Time, _Result} = timer:tc(test, performance_test, [AccumulateFun, ExtractFun, [], ?ITERATIONS]), 
    io:format("Test run: ~p microseconds~n", [Time]). 

performance_test(_AccumulateFun, ExtractFun, AccumulatedData, _MoreIterations = 0) -> 
    ExtractFun(AccumulatedData); 

performance_test(AccumulateFun, ExtractFun, AccumulatedData, MoreIterations) -> 
    NewAccumulatedData = AccumulateFun(AccumulatedData, ?NEW_DATA), 
    performance_test(AccumulateFun, ExtractFun, NewAccumulatedData, MoreIterations - 1). 

test() -> 
    performance_test(fun accumulate_1/2, fun extract_1/1), 
    performance_test(fun accumulate_2/2, fun extract_2/1), 
    ok. 

출력 : 현재 릴리스에서는

7> test:test(). 
Test run: 57204314 microseconds 
Test run: 18996 microseconds 
+0

벤치마킹 해 주셔서 감사합니다. :) 벤치 마크는 10 바이트 블록으로 1 백만 바이트 바이너리를 작성한다는 점에서 극단적입니다. 바이너리 크기로 복사하는 시간이 늘어납니다. 10 바이 트씩 10 kb 단위로 10 바이 트를 빌드하는 것이 더 빠릅니다. 또한 목록을 축적하는 목록은 똑같은 리터럴 작은 이진수를 목록에 추가하여 GC에 대한 압박감을 줄여 주므로 이점이 있습니다. – Christian

2

, 에뮬레이터의 바이너리 처리가 크게 향상되어 이제 간단한 경로를 사용하여 청크로 이진 청크를 생성 할 수 있습니다.

버퍼 = #state{buffer = <<Buffer/binary, Bin/binary>>}.

나는 다른 접근법에 대해 테스트하지 않았지만 나쁘지 않아야합니다. 서로 다른 구현 간의 성능은 동일한 버퍼에서이 작업을 수행하는 횟수와 각 청크의 크기에 따라 달라질 수 있습니다.

+0

http://www.erlang.org/doc/efficiency_guide/binaryhandling.html#4.2 – Christian

관련 문제