ByteArrayOutputStream performance



我的要求是创建输入流的2个副本,一个用于Apache Tika文件MimeType Detect,另一个用于输出流。

private List<InputStream> copyInputStream(final InputStream pInputStream, final int numberOfCopies) throws UploadServiceException{
final int bytesSize = 8192;
List<InputStream> isList = null;        
try(PushbackInputStream pushIS = new PushbackInputStream(pInputStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();){  
byte[] buffer = new byte[bytesSize];
for (int length = 0; ((length = pushIS.read(buffer)) > 0);) {
baos.write(buffer, 0, length);
}
baos.flush();
isList = new ArrayList();
for(int i = 0; i < numberOfCopies ; i++){
isList.add(new ByteArrayInputStream(baos.toByteArray()));
}
} catch (IOException ex) {
throw new MyException(ErrorCodeEnum.IO_ERROR, ex);
} catch (Exception ex) {            
throw new MyException(ErrorCodeEnum.GENERIC_ERROR, ex);
}
return isList;
}

我看到一些性能问题

  1. 字节数组的大小是文件大小的两倍。我计划使用ByteArrayOutputStream(int size(,但在上传过程中我没有文件大小。
  2. 我看到垃圾收集不经常发生,如何处理这种情况。

更新

根据反馈

  • 删除了回推输入流
  • 添加了最后一个字节[] byteArrayIS = baos.toByteArray((;

    private List<InputStream> copyInputStream(final InputStream pInputStream, final int numberOfCopies) throws MyException{
    final int bytesSize = 8192;
    List<InputStream> isList = null;        
    try(ByteArrayOutputStream baos = new ByteArrayOutputStream();){  
    byte[] buffer = new byte[bytesSize];
    for (int length = 0; ((length = pInputStream.read(buffer)) > 0);) {
    baos.write(buffer, 0, length);
    }
    baos.flush();
    isList = new ArrayList();
    final byte[] byteArrayIS = baos.toByteArray();
    for(int i = 0; i < numberOfCopies ; i++){
    isList.add(new ByteArrayInputStream(byteArrayIS));
    }
    } catch (IOException ex) {
    throw new MyException(ErrorCodeEnum.IO_ERROR, ex);
    } catch (Exception ex) {
    if(ex instanceof MyException){
    throw ex;
    }
    throw new MyException(ErrorCodeEnum.GENERIC_ERROR, ex);
    }
    return isList;
    }
    

字节数组的大小是文件大小的两倍。我计划使用ByteArrayOutputStream(int size(,但在上传过程中我没有文件大小。

如果您必须使用ByteArrayOutputStream并且对大小没有很好的估计,那么您无能为力。 该ByteArrayOutputStream使用一种简单(且省时(的策略,即在字节数组填满时将字节数组大小加倍。

ByteArrayOutputStream的Apache Commons IO版本使用了一种减少复制的替代策略,但它仍然过度分配内存...显著。

我看到垃圾收集不经常发生,如何处理这种情况。

正确的方法是处理它。 让 GC 在 JVM 确定有必要时运行。 这是迄今为止在Java中进行存储管理的最有效方法。

  • 使用System.gc()显式运行 GC 可能会对性能造成灾难性影响。
  • 运行
  • GC(显式运行或让 JVM 执行此操作(不太可能将内存返回给操作系统。

事实上,GC 不经常运行可能是一件事。


然后。。。查看您的代码...我可以看到一些东西,这意味着您将使用比您需要的更多的数据副本。

每次调用toByteArray()时,都会创建ByteArrayOutputStream捕获的数据的新副本。 对于您正在做的事情,这是不必要的。 相反,您应该在创建单个byte[]后调用toByteArray()并将该单个byte[]包装在多个ByteArrayInputStream实例中。 您可以确定输入流不会修改byte[]中的字节。

在您的示例代码中使用PushbackInputStream似乎没有实现任何效果......这在其他方面是无法实现的。

首先,你为什么使用 PushbackInputStream?这完全无关紧要。您可能希望将输入流包装到 BufferedInputStream 中,如果尚未缓冲输入流。

其次,您是如何测量字节数组大小的?ByteArrayOutputStream 自动管理内部分配。如果 baos.toByteArray(( 给你双倍数据,首先看看你从 InputStream 中实际读取了多少数据(提示:for 循环中所有长度的总和(。

至于垃圾回收,它是自动的和非确定性的,所以如果你对它了解不多,那就别管它了。通常,较少的GC活动意味着有足够的可用内存和/或程序不会产生太多垃圾。这是好事!但是,一旦不再需要它们,您应该确保关闭所有流,否则会出现内存泄漏。特别是,查找 pInputStream 关闭的位置,以及结果列表中所有输入流关闭的位置。

相关内容

  • 没有找到相关文章

最新更新