在Haskell中读取和处理多个文件

时间:2015-11-11 11:04:26

标签: haskell io

想法。逐行读取多个文件,连接它们,处理所有文件中的行列表。

实施。can可通过以下方式实施:

import qualified Data.ByteString.Char8 as B

readFiles :: [FilePath] -> IO B.ByteString
readFiles = fmap B.concat . mapM B.readFile

...

main = do
    files <- getArgs
    allLines <- readFiles files

问题。这种情况无法忍受。值得注意的是,实际或用户时间比系统时间高几个数量级(使用UNIX time测量),因此我认为问题在于在IO中花费太多时间。 我没有设法找到一种简单有效的方法来解决Haskell中的这个问题。

例如,处理两个文件(30.000行和每个1.2M)需​​要

   20.98 real        18.52 user         0.25 sys

这是运行+RTS -s时的输出:

     157,972,000 bytes allocated in the heap
       6,153,848 bytes copied during GC
       5,716,824 bytes maximum residency (4 sample(s))
       1,740,768 bytes maximum slop
              10 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0       295 colls,     0 par    0.01s    0.01s     0.0000s    0.0006s
  Gen  1         4 colls,     0 par    0.00s    0.00s     0.0010s    0.0019s

  INIT    time    0.00s  (  0.01s elapsed)
  MUT     time   16.09s  ( 16.38s elapsed)
  GC      time    0.01s  (  0.02s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time   16.11s  ( 16.41s elapsed)

  %GC     time       0.1%  (0.1% elapsed)

  Alloc rate    9,815,312 bytes per MUT second

  Productivity  99.9% of total user, 98.1% of total elapsed

       16.41 real        16.10 user         0.12 sys

为什么使用上面代码连接文件的速度太慢? 我应该如何在Haskell中编写readFiles函数以使其更快?

1 个答案:

答案 0 :(得分:3)

您应该准确地向我们展示您的处理步骤。

即使在您使用的多种输入文件(1.2 MB,每行30k行)上运行,该程序也非常高效:

import Control.Monad
import Data.List
import System.Environment
import qualified Data.ByteString.Char8 as B

readFiles :: [FilePath] -> IO B.ByteString
readFiles = fmap B.concat . mapM B.readFile

main = do
    files <- getArgs
    allLines <- readFiles files
    print $ foldl' (\s _ -> s+1) 0 (B.words allLines)

以下是我创建输入文件的方法:

import Control.Monad

main = do
  forM_ [1..30000] $ \i -> do
    putStrLn $ unwords ["line", show i, "this is a test of the emergency"]

运行时间:

time ./program input               -- 27 milliseconds
time ./program input input         -- 49 milliseconds
time ./program input input input   -- 69 milliseconds