簡體   English   中英

Haskell或F#高吞吐量二進制I / O.

[英]Haskell or F# high throughput binary I/O

這兩種語言中二進制I / O庫的性能有多好>我正在考慮重新編寫一個丑陋(但非常快)的C ++代碼,它使用標准的fread和fwrite函數處理大約5-10GB的二進制文件。 對於F#和Haskell中的優化實現,我應該期待什么減速因子?

編輯:這是計算零字節的C實現(堆上分配的緩沖區)。

#include <stdio.h>
#include <stdlib.h>

#define SIZE 32*1024
int main(int argc, char* argv[])
{
    FILE *fp;
    char *buf;
    long i = 0, s = 0, l = 0;
    fp = fopen(argv[1], "rb");
    if (!fp) {
        printf("Openning %s failed\n", argv[1]);
        return -1;
    }
    buf = (char *) malloc(SIZE);
    while (!feof(fp)) {
        l = fread(buf, 1, SIZE, fp);
        for (i = 0; i &lt l; ++i) {
            if (buf[i] == 0) {
                ++s;
            }
        }
    }
    printf("%d\n", s);
    fclose(fp);
    free(buf);
    return 0;
}

結果:


$ gcc -O3 -o ioc io.c
$ ghc --make -O3 -o iohs io.hs
Linking iohs ...
$ time ./ioc 2.bin
462741044

real    0m16.171s
user    0m11.755s
sys     0m4.413s
$ time ./iohs 2.bin
4757708340

real    0m16.879s
user    0m14.093s
sys     0m2.783s
$ ls -lh 2.bin
-rw-r--r-- 1  14G Jan  4 10:05 2.bin

Haskell使用基於ByteString的惰性 IO,使用“二進制”解析器應該與執行相同作業的C代碼在相同的數據類型上具有相同的性能。

要注意的關鍵包:

考慮到這篇文章需要:

  • 哈斯克爾
  • 代碼優化
  • 績效基准

......可以肯定地說我已經超越了我的頭腦。 然而,當我進入我的腦海時,我總是學到一些東西,所以這里就是這樣。

我通過Hoogle圍繞Data.ByteString.Lazy.* Haskell模塊進行了探索,並找到了用於測量惰性ByteString長度的長度函數。 因此實施:

length :: ByteString -> Int64
length cs = foldlChunks (\n c -> n + fromIntegral (S.length c)) 0 cs

嗯。 Jon確實說過“......在F#中折疊文件是其快速的主要原因......”(我的重點)。 並且這個length函數似乎也使用粗大的折疊來實現。 因此,看起來這個函數更像是與Jon的F#代碼進行“蘋果對蘋果”的比較。

它在實踐中有所作為嗎? 我將Jon的例子與以下內容進行了比較:

import System
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.length

Jon的Haskell示例在我的機器上為1.2 GB文件: 10.5s

'矮胖'版本: 1.1s

Haskell代碼的“矮胖”版本快了近十倍 這表明它可能比Jon的優化F#代碼快幾倍。

編輯

雖然我不一定完全贊同Jon對我的例子的批評,但我想盡可能地使它成為可能的。 因此,我已經描述了以下代碼:

import System
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.count 0

此代碼將目標文件的內容加載到ByteString中,然后“計數”每個0值字節的出現。 除非我遺漏了某些東西,否則該程序必須加載並評估目標文件的每個字節。

上述程序的運行速度始終比Jon提交的最快的Haskell程序快4倍,復制在此作為參考(如果已更新):

import System
import Data.Int
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.foldl (\n c -> n + 1) (0 :: Data.Int.Int64)

我在這里寫博客。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM