我有一個Web應用程序,用戶上傳圖片。我們通過ImageIO.read()驗證圖像數據,並在將其保存到磁盤之前對生成的BufferedImage執行一些簡單的轉換。ImageIO是同步的
在執行負載測試中,我們意識到,當許多要求在同一時間進來,他們被擋在ImageIO.read()調用。深入挖掘,我們注意到JPEGImageReader已同步,並且一次只創建一個BufferedImage。
有沒有人遇到過這個?我一直在使用谷歌搜索幾天,並沒有遇到過這個問題的另一個人,所以也許我做錯了什麼。我不能拿出任何合乎邏輯的理由。這似乎與不能爲每個圖像創建單獨的讀者和作者有關內存泄漏問題,但這種解釋似乎相當薄。
編輯:Here是一個性能工具,它打破了這麼久什麼是服用。我相信這是由於所有的線程都在等待同步鎖,JPEGImageReader源。
編輯:JAI庫會工作,除了OpenJDK的已刪除了它的關鍵部件,明確JPEG編解碼器的支持。
解決方案:給定的時間我花了試圖找到一個替代的解決方案,並沒有做這樣的量,我最好的解決辦法是異步處理的圖像,相對於該請求。因此,當請求進入時,原始圖像數據被存儲爲假定有效的圖像;那麼請求線程之外的異步進程將一次處理一個圖像。 由於ImageIO庫的同步性,嘗試一次執行多個操作沒有任何好處。考慮到庫不同步,圖像可以並行處理,效率很低。
一邊做處理異步地增加了複雜的程度,它可能是一個好主意,關於修改圖像。不起作用的是,我們無法在每個請求中處理原始圖像,這意味着我們的系統必須假設每個圖像都是有效的圖像數據。當異步處理器開始處理圖像時,如果數據不好,系統中可能會出現不一致。
您在運行多線程?你是說多個'JPEGImageReader'實例在類上序列化(即單線程)?你怎麼確定這是事實?如果是這樣,他們都在鎖定/等待的顯示器在哪裏? –
它絕對是多線程的,因爲它們是Tomcat中的單個請求。我開始相信ImageIO只是在底層創建一個底層的JPEGImageReader。請參閱:[JPEGImageReader](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/com/sun/imageio/plugins/jpeg/JPEGImageReader.java)。我們99%確定這是發生了什麼事情,因爲當我們註釋掉創建BufferedImage並執行轉換並將InputStream內容保存到磁盤的部分時,CPU實際上正在徵稅。否則,他們在負載時的使用率約爲5%。 – user1236874
聽起來你需要在ImageIO中下一層,並使用創建讀者的方法,而不是方便的方法。 – EJP