2014-11-23 37 views
5

Delphi RAD Studio XE2 çalıştırıyorum. Son zamanlarda dosya akışlarıyla uğraştım ve bu soruya beni yönlendiren bazı ilginç sonuçlar buldum.Delphi'de Dosya Akışı - Optimum Tampon Boyutu

Delphi'de TStreamReader için en uygun tampon boyutu nedir? Örneğin, doubleTABdoubleTABdouble formunda 2 milyon satırlık bir 1GB dosya yüklüyorum. Aşağıdaki kodu kullanarak bir TStringList'a yüklerseniz, farklı arabellek boyutları için önemli ölçüde değişken sonuçlar elde ederim. Sonuçlara göre işlem hızlarını ve RAM kullanımını kastediyorum.

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; 

uygun tampon boyutu ayarlanmış ise az 1024 den doğrusal yavaşlaması gibi görünüyor ve daha fazla RAM kullanmak gibi between 1024 ve 4096 gibi görünüyor. 4096'nın üzerinde ayarlanırsa, üstel olarak yavaşlıyor gibi görünüyor.

Neden bu davranışları görüyorum ve görev için en uygun arabellek boyutunu nasıl belirleyebilirim? Ek olarak, maksimum arabellek boyutu nedir? gelince

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 

:

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; 

Örnek çalıştırmak katı ekstre edilmiştir: Düzenleme

Anılan dosya boyutu kullanılarak çalışma sürelerini elde etmek için aşağıdaki kodu ran RAM kullanımı, 256'nın altındaki arabellek boyutları toplamda yaklaşık 3,5GB'lık bir kullanımla, 540 RAM'lik toplam bellek kullanımı ve 1024'ün üzerinde bir arabellek boyutuyla sonuçlandı. Örneğin, 2kb, 4kb ve 8kb tamponu ile RAM kullanımı; bakınız:

this image

+1

Bkz. [TStreamReader - kötü performans] (http://qc.embarcadero.com/wc/qcmain.aspx?d=114824). –

+0

Büyük tamponlar daha yavaşsa, bir şeyler yanlıştır. Bu tuhaf. Gerçekten bir dize listesine yüklemeniz gerekiyor mu? Bundan kaçınabilseydin daha hızlı ilerleyecektin. –

+1

@DavidHeffernan, bunu XE7 üzerinde test etti ve TStreamReader'ın kötü performansını onaylayabilir. Sadece 'stringList.LoadFromFile()' kullanarak> 5 kat daha hızlıdır. –

cevap

1

@Trojanian, yukarıdaki söz kod önceki yazı, TStringList.LoadFromFile - Exceptions with Large Text Files yılında Remy LeBeau cevabı benzer. Ben de Remy'nin daha büyük dosyaları yükleyebilecek örneğiyle uğraştım ama daha küçük dosyalar için performans TStrings.LoadFromFile'un yarısıydı. Arabellek boyutunu değiştirmeye yönelik kendi girişimlerim performansı artırmadı.

Sonra, Alternative to TStrings.LoadFromFile or TStringList.LoadFromFile Aşağıdaki kod örneği bulundu, bu yani x4 daha hızlı kod daha ben Xe3 kullandığınızda da yukarıda, bir 128kb tampon kullanır ve TStrings.LoadFromFile kıyasla benim büyük dosyaların yüklenme zamanı yarıya.

+0

Bunun için teşekkürler - Bir göz atacağım. :-) – Trojanian

+2

Bu kodda dikkat edilmesi gereken bazı sorunlar var. Bir, her döngü yinelemede akımın 3 aşamasını gerçekleştirir, bu da büyük dosya akışları için maliyetli olabilir. Döngü girmeden önce mevcut 'Position' ve' Size' yerel değişkenlere geri almak için daha iyi, daha sonra bunları loop yaparken kullanın.Ayrıca, döngü 'TStream.Read()' kullanıyor, ancak başarısızlık için denetleme yapmıyor ve 'ReadSize' bayt sayısı her zaman okunduğunu varsayar. Bunun yerine TStream.ReadBuffer() 'yi kullanmak daha iyidir. –

+0

Teşekkürler Geri bildirim için Remy! – Lars