首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字节数组输出流

字节数组输出流
EN

Stack Overflow用户
提问于 2020-11-24 18:45:31
回答 1查看 41关注 0票数 0

这个问题可能很愚蠢,但是通过outputstream发送的字节数组的理想长度是多少?我在网上找不到任何关于这个的东西。

我发现了很多将数组大小设置为2^X或类似值的示例。但这样做的目的是什么?

EN

回答 1

Stack Overflow用户

发布于 2020-11-24 19:09:01

没有最佳大小。OutputStream是一个抽象的概念;它有一百万个实现。(不仅仅是“FileOutputStream是一种实现”,还有“FileOutputStream,在OpenJDK11上,在Windows10上,在这种情况下,有这个服务包,有这个中央处理器和这么多的系统内存”)。

您看到的原因是为了提高缓冲区效率。发送1个字节的问题通常不会有什么问题,但有时发送1(或很少)个字节会导致这种糟糕的情况:

  1. 你发送一个字节。
  2. 底层输出流不是用来缓冲这个字节的,它没有足够的存储空间,所以它唯一能做的就是把它转发给实际的底层资源。假设OutputStream表示filesystem.
  3. The内核驱动上的一个文件,其工作原理与此类似。(大多数OSes都在内部缓冲,但当您打开file).
  4. Therefore,时,您可以要求操作系统不要这样做,因为现在需要将一个字节写入磁盘。但是,它是SSD,您不能对SSD执行此操作,您一次只能写入整个单元*。这就是SSD的工作方式:您只能写出整个块的值。它们不是大盘子上按顺序排列的位。
  5. 因此,内核读取整个单元,更新您正在写入的一个字节,然后将整个单元写回固态硬盘。
  6. 您的实际循环确实写入了大约50,000个字节,所以本应进行一次固态硬盘读写的操作现在需要50,000次读取和50,000次写入,从而耗费了固态硬盘存储单元的寿命,耗费的时间是所需时间的50,000倍。

类似的问题也出现在网络上(最终发送一个包含在HTTP头中的单个字节,再包含在两个TCP/IP数据包中,导致通过网络为您.write(singleValue)和许多其他类似系统的每个字节发送大约1000字节。

那么为什么这些流没有缓冲呢?

因为在某些情况下,您实际上并不希望它们这样做;有很多理由让它们在编写I/O时考虑到特定的效率。

就不能让我做点什么吗?

啊,你很幸运,有!BufferedWriter和朋友(BufferedOutputStream也存在)为你包装了一个底层的流和缓冲区:

代码语言:javascript
复制
var file = new FileOutputStream("/some/path");
var wrapped = new BufferedOutputStream(file);
file.write(1); // this is a bad idea
wrapped.write(1); // this is fine

在这里,包装的写入不会导致任何事情发生,除了一些内存被推来推去。不会将字节写入磁盘(缺点是,如果有人被powercable绊倒,它就会丢失)。只有在您关闭wrapped,或者在wrapped上调用flush(),或者将足够的字节写入wrapped之后,wrapped才会真正地向底层流发送一大堆字节。如果创建一个字节数组是一个笨重的,这是你应该使用的。为什么要重新发明轮子呢?

但是我想写入底层的原始流。

好吧,如果字节数小于单个TCP/IP数据包可以容纳的字节数,或者是一个不幸的大小,那么您使用的字节就太少了(假设TCP/IP数据包正好可以容纳1000个字节,而您发送1001个字节)。这是一个完整的数据包,然后是第二个只有1个字节的数据包,效率只有50%。50%的效率仍然好于0.1%的效率,在这个假设中,每次一个字节的效率会让你得到更好的效率)。但是,如果你发送,比如说5001字节,那就是5个完整的包和一个令人遗憾的1字节的包,效率为83.35%。不幸的是,它没有接近100,但也没有那么糟糕。同样的情况也适用于磁盘(如果一个SSD单元有2048字节,而你发送了65537字节,它仍然有大约96/7%的效率)。

如果对您自己的java进程的影响是有问题的,那么您使用了太多的字节:它导致了过多的垃圾收集,或者更糟糕的是,内存不足错误。

那么“甜蜜点”在哪里呢?这取决于一点,但65536很常见,不太可能“太低”。除非同时运行数千个线程,否则也不会太高。

它通常是2的幂,这主要是因为迷信,但其中也有一些意义:底层的缓冲区通常是2的幂(毕竟计算机是二进制的)。因此,如果信元大小恰好是2048年,那么如果您发送65536个字节(这恰好相当于32个信元的数据),那么您的效率是100%的。

但是,您真正想要避免的唯一一件事是,如果您一次向打包(SSD、网络等)底层流写入一个字节,就会出现0.1%的效率。因此,这并不重要,只要超过2048,你就应该已经避免了厄运的发生。

*)我过于简单化了;重点是单个字节的读或写可能会花费整个字节的时间,并给出一些提示,为什么不在SSD技术上做一个完整的深入研究。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64984809

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档