2014-11-23 87 views
5

我正在運行Delphi RAD Studio XE2。最近我一直在玩文件流,發現一些有趣的結果,導致我這個問題。Delphi中的文件流 - 最佳緩衝區大小

Delphi中TStreamReader的最佳緩衝區大小是多少?例如,我正在以doubleTABdoubleTABdouble的形式加載一個200萬行的1GB文件。如果使用下面的代碼將它加載到TStringList中,對於不同的緩衝區大小,我會得到顯着不同的結果。結果我的意思是處理速度和內存使用量。

reader := TStreamReader.Create(fileLocation, TEncoding.UTF8, True, NumBytes); 
try 
    stringList.BeginUpdate; 
    try 
    stringList.Clear; 
    while not reader.EndOfStream do 
     stringList.Add(reader.ReadLine); 
    finally 
     stringList.EndUpdate; 
    end; 
    finally 
    reader.Free; 
    end; 
end; 

最佳緩存大小似乎是1024和4096之間。如果將它設置低於1024似乎線性放慢腳步,似乎使用更多的內存。如果它設置在4096以上,它似乎會呈指數級下降。

爲什麼我會看到這些行爲,以及如何確定任務的最佳緩衝區大小?另外,最大緩衝區大小是多少?

編輯

我跑下面的代碼使用上述文件大小來提取運行時間:

startTime := Now(); 
myStreamReader := TStreamReader.Create(fileLocation, TEncoding.UTF8, True, numBytes); 
myStringList := TStringList.Create; 
try 
    myStringList.BeginUpdate; 
    try 
    myStringList.Clear; 
    while not myStreamReader.EndOfStream do 
     myStringList.Add(myStreamReader.ReadLine); 
    finally 
     myStringList.EndUpdate; 
    end; 
    finally 
    myStreamReader.Free; 
    end; 
processTime := Now() - startTime; 
myStringList.Free; 

實施例的運行時間被提取爲:

Buffer Size 32. Done in 69s 
Buffer Size 64. Done in 69s 
Buffer Size 96. Done in 69s 
Buffer Size 128. Done in 70s 
Buffer Size 160. Done in 60s 
Buffer Size 192. Done in 57s 
Buffer Size 224. Done in 52s 
Buffer Size 256. Done in 50s 
Buffer Size 512. Done in 44s 
Buffer Size 768. Done in 40s 
Buffer Size 1024. Done in 39s 
Buffer Size 1280. Done in 41s 
Buffer Size 1536. Done in 44s 
Buffer Size 1792. Done in 40s 
Buffer Size 2048. Done in 39s 
Buffer Size 2304. Done in 41s 
Buffer Size 2560. Done in 41s 
Buffer Size 2816. Done in 42s 
Buffer Size 3072. Done in 43s 
Buffer Size 3328. Done in 43s 
Buffer Size 3584. Done in 45s 
Buffer Size 3840. Done in 44s 
Buffer Size 4096. Done in 45s 
Buffer Size 4352. Done in 47s 
Buffer Size 4608. Done in 46s 
Buffer Size 4864. Done in 46s 
Buffer Size 5120. Done in 48s 
Buffer Size 5376. Done in 49s 
Buffer Size 5632. Done in 51s 
Buffer Size 5888. Done in 51s 
Buffer Size 6144. Done in 52s 
Buffer Size 6400. Done in 54s 
Buffer Size 6656. Done in 53s 
Buffer Size 6912. Done in 55s 
Buffer Size 7168. Done in 55s 
Buffer Size 7424. Done in 56s 
Buffer Size 7680. Done in 57s 
Buffer Size 7936. Done in 65s 
Buffer Size 8192. Done in 62s 
Buffer Size 8448. Done in 63s 
Buffer Size 8704. Done in 64s 
Buffer Size 8960. Done in 64s 
Buffer Size 9216. Done in 66s 
Buffer Size 9472. Done in 66s 
Buffer Size 9728. Done in 68s 
Buffer Size 9984. Done in 68s 
Buffer Size 10240. Done in 69s 

至於RAM使用率,256以下的緩衝區大小導致總共使用5GB RAM和大於1024的緩衝區,總共使用大約3.5GB。例如使用2kb,4kb和8kb緩衝區的RAM使用情況;請參考:

this image

+1

請參閱[TStreamReader - 性能不佳](http://qc.embarcadero.com/wc/qcmain.aspx?d=114824)。 – 2014-11-23 07:56:26

+0

如果較大的緩衝區較慢,則會出錯。這很奇怪。你真的需要加載到一個字符串列表嗎?如果你能避免這種情況,你仍然會更快。 – 2014-11-23 08:01:43

+1

@DavidHeffernan,在XE7上進行了測試,可以確認TStreamReader的性能不佳。使用'stringList.LoadFromFile()'快5倍。 – 2014-11-23 21:03:56

回答

1

@Trojanian,你上面提到的代碼類似於雷米勒博在以前的帖子,TStringList.LoadFromFile - Exceptions with Large Text Files答案。我也在擺弄雷米的例子,它可能會載入更大的文件,但小文件的性能大約是TStrings.LoadFromFile的一半。我自己試圖切換緩衝區大小並不能提升性能。

然後我發現下面的代碼示例,Alternative to TStrings.LoadFromFile or TStringList.LoadFromFile,它採用了128KB緩衝區,減少了一半的我的大文件的加載時間相比TStrings.LoadFromFile,即X4比你更快的代碼上面,當我使用XE3。

+0

謝謝你 - 我會看看。 :-) – Trojanian 2014-11-23 23:33:51

+2

該代碼中有一些問題需要注意。其一,它在每個循環迭代中執行3個流的查找,這對於大文件流可能是昂貴的。在進入循環之前,最好將當前的'Position'和'Size'檢索到局部變量,然後在循環時使用它們。此外,循環使用'TStream.Read()',但不檢查失敗,並假定總是讀取「ReadSize」字節數。最好使用'TStream.ReadBuffer()'代替。 – 2014-11-23 23:56:58

+0

謝謝雷米的反饋! – Lars 2014-11-24 00:41:52