2011-09-22 1 views
7

하스켈에서 많은 양의 데이터를 읽는 데 [Char]을 사용하지 않는 것은 일반적인 사실입니다. 하나는 ByteString을 사용하여 작업을 수행합니다. 이것에 대한 일반적인 설명은 Char이 크고 목록이 오버 헤드를 추가한다는 것입니다.[Char] 기반 입력이 Haskell의 [Char] 기반 출력보다 훨씬 느린 이유는 무엇입니까?

그러나 출력에 문제가없는 것으로 보입니다. 첫 번째 프로그램의 출력을 공급하는 경우

import Data.List 

sum' :: [Int] -> Int 
sum' = foldl' (+) 0 

main = interact $ show . sum' . map read . words 

가 3.38 초 정도 걸립니다 : 예를 들어

다음 프로그램 : 한 다음 동안

main = interact $ const $ unwords $ map show $ replicate 500000 38000000 

내 컴퓨터에서 실행 단지 131 밀리 초 소요 입력으로!

String을 사용하여 입력 성능과 출력 성능 사이에 이러한 불일치가 발생하는 이유는 무엇입니까?

+1

내 빠른 프로파일 링은 입력 프로그램이 출력 프로그램보다 13 배 많은 메모리를 할당한다는 것을 보여줍니다. 이것은 분명히 불균형에 기여합니다. –

답변

10

이 문제가 반드시 I/O와 관련 있다고 생각하지 않습니다. 오히려 IntRead 인스턴스가 매우 비효율적이라는 것을 보여줍니다.

먼저, 지연 목록을 처리하는 다음 프로그램을 고려하십시오. 수기로 read 기능을 대체

main = print $ sum' $ map length $ words 
     $ unwords $ map show $ replicate 500000 38000000 

또한 : length으로 read 기능 장착

main = print $ sum' $ map read $ words 
     $ unwords $ map show $ replicate 500000 38000000 

다운 시간 0.48s 방울 : 그것은 (-O2 컴파일) 내 시스템에서 4.1s 소요 0.52s의 시간 버전의 결과는 왜 read에 관해서

main = print $ sum' $ map myread $ words 
     $ unwords $ map show $ replicate 500000 38000000 

myread :: String -> Int 
myread = loop 0 
    where 
    loop n [] = n 
    loop n (d:ds) = let d' = fromEnum d - fromEnum '0' :: Int 
         n' = 10 * n + d' 
        in loop n' ds 

내 생각 엔 내가 너무 비효율적 인 이유는 구현시 Text.ParserCombinators.ReadP 모듈을 사용하기 때문입니다.이 모듈은 단일 정수를 읽는 단순한 경우가 아니기 때문에 가장 적합하지 않을 수 있습니다.

+1

오, 그래서'String'을 사용하지 않는 주된 이유는'String'과 관련이 없습니다. 이것은 너무 불공평하다. – Rotsor

+2

'읽기'는 오류 검사, 공백 건너 뛰기, 음수, 16 진수, 8 진수 및 심지어 (깜짝!) 지수 표기법과 같이 'myread'가 수행하지 않는 몇 가지 작업을 수행합니다. –

+0

'read'에 대해 어떻게 8 진수로 쓰죠? '0'으로 시작하는 접두사가 없기를 바랍니다. – Rotsor

관련 문제