编码时the solution解决downloading a huge dynamic zip with low RAM impact的问题,一个想法开始围攻我,并引发了这个问题,要求纯粹的好奇心/对知识的渴望:
如果我不是一次加载一个InputStream
(对数据库进行单独查询),而是加载所有InputStream
,我会遇到什么样的缺点? code> 在单个查询中,返回一个列表(n,可能数千个,“打开”)InputStreams
?
当前(安全)版本:n 个查询,一个 一次实例化 inputStream
for (long id : ids){
InputStream in = getMyService().loadStreamById(id);
IOUtils.copyStream(in, out);
in.close();
}
假设版本:一个查询,n 实例化 inputStreams
List<InputStream> streams = getMyService().loadAllStreams();
for (InputStream in : streams){
IOUtils.copyStream(in, out);
in.close();
in = null;
}
第二种方法的优点和缺点是什么,不包括用于保持多个 java InputStream 实例化的(我想很少)内存量?
超过多个查询是否会导致某种网络卡住或数据库压力(或锁定,或其他人读/写流指向的相同 BLOB 字段等问题)?
或者它们是否足够聪明,在请求数据之前几乎不可见,然后 1 个查询 + 1000 个 Activity 流
可能比 1000 个查询 + 1 个 Activity 流
更好?
最佳答案
简单的回答是,您可能会遇到操作系统和/或 DBMS 的限制。
较长的答案取决于具体的操作系统和 DBMS,但这里有一些需要考虑的事情:
- 在 Linux 上,任何进程可以保存的打开文件描述符的最大数量是有限制的。默认值为 1024,但增加它相对容易。在我看来,这个限制的目的是杀死一个写得不好的进程,因为每个文件/套接字所需的内存量是最小的(在现代机器上)。
- 如果打开的流代表与数据库的单个套接字连接,则单个计算机可以向单个服务器地址/端口打开的客户端套接字总数存在硬性限制。这是由客户端的动态端口地址范围驱动的,它是 16 或 32k(但可以修改)。此限制适用于计算机上的所有进程,因此一个进程的过度消耗可能会使尝试访问同一服务器的其他进程挨饿。
- 根据 DBMS 如何管理用于检索 BLOB 的连接,您可能会遇到 DBMS 强制执行的小得多的限制。例如,Oracle 默认每个用户连接总共有 50 个“游标”( Activity 检索操作)。
除了这些限制之外,您不会从编写的代码中获得任何好处,因为它是按顺序运行连接的。如果您要使用多个线程来读取,您可能会发现拥有多个并发连接有一些好处。但是,我仍然会根据需要打开这些连接。为了避免您考虑为每个连接生成一个线程(并遇到线程数量的物理限制),您可能会在达到任何物理限制之前达到实际的吞吐量限制。
关于java - 打开多个InputStream的优点和缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16739163/