2013-11-21 41 views
6

我有一個簡單的服務器端代碼,接收一個字節數組表示一個JPEG格式的圖像,並返回圖像的尺寸。字節數組緩存圖像轉換慢

public String processImage(byte[] data) { 
    long startTime = System.currentTimeMillis(); 
    ByteArrayInputStream stream = new ByteArrayInputStream(data); 
    BufferedImage bufferedImage; 
    bufferedImage = ImageIO.read(stream); 

    int height = bufferedImage.getHeight(); 
    int width = bufferedImage.getWidth(); 

    long endTime = System.currentTimeMillis(); 

    return "height="+height+" | width="+width+" | elapsed="+(endTime-startTime); 
} 

它的工作原理,但問題是它是無法接受的緩慢。對於100KB的圖片,需要6秒。對於900KB的圖像,需要30秒。這是預期的嗎?有沒有辦法使字節數組bufferedImage轉換更快?

僅供參考,抓高度/寬度並不是我打算做的唯一事情。我最終想要處理bufferedImage。所以獲得高度/寬度只是一個示例代碼。

回答

0

嘗試使用以下命令行選項運行Java程序,看看它是否加快東西都:

-Djava.awt.headless=true 
+1

謝謝,我還沒有嘗試過,但我試圖在一個孤立的環境中運行相同的代碼,它只花了20毫秒200KB。所以這個問題看起來不像是代碼。上述設置是做什麼的? – baekacaek

+1

@baekacaek:它將圖形卡排除在等式之外。如果您從未計劃在顯示器上顯示BufferedImage,則無需浪費時間將其加載到顯卡的RAM中。我在本地嘗試了你的代碼片段,上面的命令行選項將測試圖像上的運行時間從大約250ms降低到大約140ms。因人而異。 – Asaph

2

從你在哪裏讀的形象呢?從哪裏來的字節[]?如果您正在從硬盤讀取圖像,可能會幫助您使用BufferedInputStream來讀取圖像。

這可以加快裝載速度。但是這隻有在你從例如FileInputStream讀取時纔有幫助。當從ByteArrayInputStream讀取它將無濟於事。

編輯:有沒有更多的信息可以給我們?字節數組來自哪裏?

+0

字節數組來自HTTP正文,由apache tomcat服務器處理以調用此函數。 – baekacaek

5

我認爲這個問題可能與ImageIO默認使用磁盤緩存(臨時文件)有關,即使您的源是ByteArrayInputStream。所以如果你的文件系統很慢,無論輸入源如何,讀取速度也會很慢。

您可以使用ImageIO.setUseCache(false)禁用磁盤緩存(以使用更多內存爲代價)。這仍然會緩存你的流(以允許向後搜索),但只能在內存中。

如果您有更快的磁盤/ ramdisk或類似的存儲臨時文件,也可以使用ImageIO.setCacheDirectory(cacheDirectory)將緩存目錄設置爲特定路徑。

也就是說,即使對於磁盤緩存讀取,您報告的讀取時間似乎也不合理地偏高。如果問題依然存在,我建議使用一個分析器來查明時間花在哪裏,並查看可能的優化。我也有一個自定義ByteArrayImageInputStream,這可能有助於減少磁盤訪問和內存消耗,如果這確實是問題。