2013-11-21 42 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,这可能有助于减少磁盘访问和内存消耗,如果这确实是问题。