Haskell - Lempel-Ziv 78压缩 - 非常慢,为什么?

时间:2015-06-13 18:28:55

标签: haskell compression

所以我已经完成了Lempel-Ziv压缩/解压缩,但与C ++相比,它的速度令人难以置信, 我试过了 http://norvig.com/big.txt文件,但我的程序无法处理它,而在C ++中它只用了1秒钟。你们中的任何人都可以查看我的代码并告诉我是否存在一些明显的缺陷吗?

在添加前置而不是附加后,我设法将时间从16秒减少到0.4!

哈斯克尔的懒惰是如此的欺骗,它是印刷和压缩完成的'几乎立即,但实际上是压缩使程序运行如此缓慢

import System.IO  
import Control.Monad
import qualified Data.Map as Map
import Debug.Trace
main = do  
  contents <- readFile "plik.txt"  
  let compressed = reverse $ compress contents Map.empty 1 "" []  
  let decompressed = reverse $ decompress compressed Map.empty 1 ""
  --print $ contents
  print $ length compressed
  print $ length decompressed
  --print $ contents == decompressed
compress :: String -> Map.Map String Int -> Int -> String -> [(Int,Char)]-> [(Int,Char)]
compress (s:x) m i c out = do
    if Map.member (c++[s]) m == False 
        then do 
            if c == ""
                then do
                    let newMap = Map.insert [s] i m
                    compress x newMap (i+1) c ((0,s):out)
                else do
                    let newMap = Map.insert (c++[s]) i m
                    compress x newMap (i+1) "" ((newMap Map.! c, s):out)
        else compress x m i (c++[s]) out

compress s m i c out = compress2 out

compress2 ::  [(Int,Char)]-> [(Int,Char)]
compress2 out = trace("COMPRESSION FINISHED") out



decompress :: [(Int,Char)] -> Map.Map Int String -> Int -> String -> String
decompress (s:x) m i out = do
    if fst s ==  0
        then do
            let newMap = Map.insert i [snd s] m
            decompress x newMap (i+1) ((snd s):out)
        else do
            let newMap =  Map.insert i ((m Map.! fst s)++[snd s]) m
            decompress x newMap (i+1) ((snd s):(reverse (newMap Map.! fst s))++out)

decompress s m i out = out

decompress2 ::  String -> String
decompress2 out =  trace("DECOMPRESSION FINISHED") out

1 个答案:

答案 0 :(得分:1)

其他人已在评论中说过:

  • 避免使用String;它使用了大量的RAM,处理速度很慢。使用ByteString(如果您希望处理原始二进制数据)或Text(如果您期望使用Unicode文本)。

  • 不要附加到列表中。 (String也是一个列表 - 但首先不要使用String。)如果很容易,请提前添加。如果不是,请根据需要使用Data.SequenceData.SetData.Map。或者甚至可能是TextByteStringVector

  • 如果你看到Haskell程序真的很慢并且使用了大量的RAM,即使输入和输出文件很小,你可能也有些东西太懒了。

作为一个例子,我有一个程序来产生一个字节直方图。花了大约20分钟消耗了8 GB的RAM。我将数据构造函数更改为严格,只需向其添加一个!即可。现在该程序只需几分之一秒!如果你弄错了,懒惰可以产生一个荒谬的巨大差异。

查看您发布的代码,这可能涵盖了所有内容。 (我不确定你已经尝试过哪些改变以及你现在所处的位置。)