2010-12-14 14 views
5

我正在分析加載二進制文件的代碼。加載時間約爲15秒左右。在Java中尋找BufferedInputStream的最佳大小

我的加載時間大部分來自加載二進制數據的方法。

我有下面的代碼創建我的DataInputStream類:

is = new DataInputStream(
    new GZIPInputStream(
    new FileInputStream("file.bin"))); 

而且我改成了這樣:

is = new DataInputStream(
    new BufferedInputStream(
    new GZIPInputStream(
    new FileInputStream("file.bin")))); 

所以我做了這個小修改的代碼加載從15秒跑到後4.

但後來我發現BufferedInputStream有兩個構造函數。另一個構造函數允許您明確定義緩衝區大小。

我有兩個問題:

  1. 選擇什麼大小的BufferedInputStream,是理想?如果沒有,我怎麼才能找到緩衝區的最佳尺寸?我應該寫一小段代碼來進行二分查找嗎?
  2. 這是我可以使用BufferedInputStream的最佳方式嗎?我原本在GZIPInputStream中使用它,但是可以忽略的好處。我假設代碼現在正在做的是每次需要填充文件緩衝區時,GZIP輸入流會通過並解碼x個字節(其中x是緩衝區的大小)。完全忽略GZIPInputStream是否值得?這絕對不是必需的,但是當使用它時,我的文件大小會大大減少。

回答

8

GZIPInputStream和BufferedInputStream都使用內部緩衝區。這就是爲什麼在GZIPInputStream中使用BufferedInputStream不提供任何好處。 GZIPInputStream的問題在於它不會緩衝它生成的輸出,因此您的當前版本要快得多。

BufferedInputStream的默認緩衝區大小爲8kb,因此您可以嘗試增加或減少該值以查看是否有幫助。我懷疑確切的數字很重要,所以你可以簡單地乘以或除以二。

如果文件很小,您也可以嘗試完全緩衝它。這應該在理論上給你最好的表現。您也可以嘗試增加GZIPInputStream的緩衝區大小(默認512字節),因爲這可能會加速從磁盤讀取數據。

+0

我建議你在從磁盤讀取數據時爲GZIPInputStream嘗試一個64K的緩衝區。我使用1 MB,這可能超過需要。 ;) – 2010-12-14 10:47:34

4
  1. 不要用編碼的二進制搜索打擾。只需手動嘗試一些值並比較時間(如果喜歡,可以手動進行二進制搜索)。您很可能會發現,各種緩衝區大小會給您提供接近最佳的性能,所以請選擇最小的方法。

  2. 你有什麼是正確的順序:(但不是輸出)

    is = new DataInputStream(
        new BufferedInputStream(
        new GZIPInputStream(
        new FileInputStream("file.bin")))); 
    

    有在把一個BufferedInputStreamGZIPInputStream內的小點,因爲後者已經緩衝了輸入

    刪除GZIPInputStream可能是一個勝利,但如果數據必須從磁盤讀取並且不駐留在文件系統緩存中,則很可能會對性能造成不利影響。原因是從磁盤讀取速度很慢,並且解壓縮速度非常快。因此,從磁盤讀取較少數據並將其解壓縮到內存中比從磁盤讀取更多數據要便宜。

+0

感謝您的洞察。 – Brad 2010-12-14 10:32:00

+0

不客氣。我用更多的信息編輯了答案。 – NPE 2010-12-14 10:35:23