string - 为什么 Haskell 中基于 [Char] 的输入比基于 [Char] 的输出慢得多?

标签 string performance haskell io

众所周知,在 Haskell 中不使用 [Char] 读取大量数据。使用 ByteString 来完成这项工作。 对此的通常解释是 Char 很大并且列表增加了它们的开销。

但是,这似乎不会导致输出出现任何问题。

例如以下程序:

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

在我的计算机上运行只需 131 毫秒,而以下一个:

import Data.List

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

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

如果将第一个程序的输出作为输入,则需要 3.38 秒!

使用String的输入和输出性能之间存在如此差异的原因是什么?

最佳答案

我认为这个问题不一定与 I/O 有关。相反,它表明 IntRead 实例效率相当低。

首先,考虑以下仅处理惰性列表的程序。在我的机器上需要 4.1 秒(使用 -O2 编译):

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

length 替换 read 函数可将时间降至 0.48 秒:

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

此外,将read函数替换为手写版本会导致时间为0.52秒:

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

我猜测为什么 read 效率如此低下,因为它的实现使用了 Text.ParserCombinators.ReadP 模块,这可能不是简单情况下最快的选择读取单个整数。

关于string - 为什么 Haskell 中基于 [Char] 的输入比基于 [Char] 的输出慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7510078/

相关文章:

Haskell类型的具体数据构造函数

haskell - 如何在 Haskell 中访问 Graphics.Gloss 事件类型?

php - 如何只从 PHP 字符串中取出数字?

asp.net - iis 7.5 ASP.net 挂起请求

java - Criteria API - 具有参数表达式的优点

SQL 为什么 SELECT COUNT(*) , MIN(col), MAX(col) 比 SELECT MIN(col), MAX(col) 更快

c - opendir 在 C 语言上无法获取缓冲区 char * 的内容?

ruby - 在 ruby​​ 中用不同的字符串交换每个出现的情况

在 C 中将 void 方法的输出转换为 String

haskell - 导管和网络导管 : Combine MonadResource and IO