2014-05-25 3 views
2

현재 성능을 향상시킬 수 있는지 여부를 확인하기 위해 프로그램을 벤치마킹하고 있습니다. 현재 내 프로그램은 입력 파일을 받아 여러 파일로 분할하는 알고리즘을 실행합니다.Conduit 파이프 라인 최적화

파일을 3 부분으로 분할하는 데 약 12 ​​초가 소요되며 -O2 라이브러리 및 실행 파일 컴파일 플래그가 있습니다.

ghc-options:   -Wall -fno-warn-orphans -O2 -auto-all 

sinkFile에서의 시간의 약 60 %를 지출하고, 나는 다음과 같은 코드를 개선하기 위해 할 수있는 일이 있는지 궁금 해서요 것 같습니다. 많은 시간을 복용 sinkFile을 보여줍니다

                        individual  inherited 
COST CENTRE        MODULE         no.  entries %time %alloc %time %alloc 

    splitFile.sink      HaskSplit.Conduit.Split    289   1 0.0 0.0 66.8 74.2 
     sinkMultiFiles      HaskSplit.Conduit.Split    290   1 27.4 33.2 66.8 74.2 
     idxSinkFile      HaskSplit.Conduit.Split    303   3 7.9 11.3 39.4 41.0 
     idxSinkFile.ccm     HaskSplit.Conduit.Split    319   3 3.1 3.6  3.1 3.6 
     idxSinkFile.cbs     HaskSplit.Conduit.Split    317   3 3.5 4.2  3.5 4.2 
     idxSinkFile.sf     HaskSplit.Conduit.Split    307   3 24.9 21.9 24.9 21.9 
     sinkMultiFiles.len    HaskSplit.Conduit.Split    291   1 0.0 0.0  0.0 0.0 

: 여기

-- | Get the sink file, a list of FilePaths and the share number of the file to output to. 
idxSinkFile :: MonadResource m 
      => [FilePath] 
      -> Int 
      -> Consumer [Word8] m() 
idxSinkFile outFileNames shareNumber = 
    let ccm = CC.concatMap $ flip atMay shareNumber 
     cbs = CC.map BS.singleton 
     sf = sinkFile (outFileNames !! shareNumber) 
    in ccm =$= cbs =$= sf 

-- | Generate a sink which will take a list of bytes and write each byte to its corresponding file share 
sinkMultiFiles :: MonadResource m 
       => [FilePath] 
       -> [Int] 
       -> Sink [Word8] m() 
sinkMultiFiles outFileNames xs = 
    let len = [0..length xs - 1] 
    in getZipSink $ otraverse_ (ZipSink . idxSinkFile outFileNames) len 

는 GHC의 프로파일의 출력됩니다. (내가 궁금해하는 경우 목록 액세스 등을 벤치마킹 한 결과 0 %의 처리율을 보임)

이 IO와 같은 작은 프로그램은 종종 병목 현상이 있음을 알고 있지만, 내 프로그램의 런타임 성능을 향상시킬 수 있습니다.

건배!

+0

'conduit'과'conduit-extra'를'-auto-all'으로 다시 컴파일하는 것이 더 유익 할 것입니다. 시간을 보냈습니다. –

+0

@MichaelSnoyman, 흠, 내가 옳지 않은 일이라고 더 많이 기대하고있었습니다. 나는 더 깊은 발굴을 시도 할 것이다. 과거 경험에서'sinkFile' 속도의 거친 예제가 있습니까? –

+0

이것이 프로그램과 관련이 있는지는 모르겠지만 way/warp와 같은 일부 웹 서버는 blaze-builder를 사용하여 효율적으로 출력 할 수있는 ByteString을 작성합니다. – yokto

답변

1

nh2의 조언에 따라 각 Word8 인스턴스에서 BS.singleton을 수행하는 대신에 ByteStrings을 256 바이트 청크로 포장하기로 결정했습니다.

cbs = CL.sequence (CL.take 256) =$= CC.map BS.pack 
대신

cbs = CC.map BS.singleton 

아래 있듯이 나는 꽤 크게 메모리 사용량뿐만 아니라 실행 시간을 단축 할 수있어 :

원래 실행을

total time =  194.37 secs (194367 ticks @ 1000 us, 1 processor) 
total alloc = 102,021,859,892 bytes (excludes profiling overheads) 

신규 CL.take

몇 가지 심각한 개선의
total time =  35.88 secs (35879 ticks @ 1000 us, 1 processor) 
total alloc = 21,970,152,800 bytes (excludes profiling overheads) 

으로, 실행! 더 많은 것을 최적화하고 싶습니다. 그러나 다른 질문을 위해서입니다.