Ica*_*ndu 1 java io optimization buffer
缓冲区实际上如何优化读/写过程?
每次我们读取一个字节时,我们都会访问该文件。我读到缓冲区减少了访问文件的次数。问题是如何?。在图片的缓冲部分,当我们从文件加载字节到缓冲区时,我们就像在图片的未缓冲部分一样访问文件,那么优化在哪里?
我的意思是......每次读取一个字节时,缓冲区都必须访问文件,所以即使缓冲区中的数据读取速度更快,这也不会提高读取过程中的性能。我错过了什么?
基本的误解是假设文件是逐字节读取的。大多数存储设备,包括硬盘驱动器和固态磁盘,都以块的形式组织数据。同样,网络协议以数据包而不是单个字节的形式传输数据。
这会影响控制器硬件和低级软件(驱动程序和操作系统)的工作方式。通常,甚至不可能在此级别上传输单个字节。因此,请求读取单个字节最终会读取一个块并忽略除一个字节之外的所有内容。更糟糕的是,写入单个字节可能意味着读取整个块,更改其中的一个字节,然后将该块写回设备。对于网络传输,发送负载仅为 1 个字节的数据包意味着将 99% 的带宽用于元数据而不是实际负载。
请注意,有时需要立即响应或需要在某个时刻明确完成写入,例如出于安全考虑。这就是无缓冲 I/O 存在的原因。但是对于大多数普通用例,您无论如何都希望传输字节序列,并且应该以适合底层硬件的大小的块传输。
请注意,即使底层系统自行注入缓冲,或者当硬件真正传输单个字节时,执行 100 个操作系统调用来传输单个字节仍然比执行单个操作系统调用告诉它传输 100 个字节要慢得多。字节一次。
但是您不应该将缓冲区视为文件和程序之间的内容,如图片所示。您应该将缓冲区视为程序的一部分。就像您不会将String对象视为介于您的程序和字符源之间的某种东西,而是一种处理此类项目的自然方式。例如,当您对InputStreamFileInputStream足够大的目标数组使用(例如 a )的批量读取方法时,无需将输入流包装在 a 中BufferedInputStream;它不会提高性能。您应该尽可能远离单字节读取方法。
作为另一个实际示例,当您使用 an 时InputStreamReader,它已经将字节读入缓冲区(因此不需要额外的BufferedInputStream内容)并且内部使用的CharsetDecoder将对该缓冲区进行操作,将结果字符写入目标字符缓冲区。例如Scanner,当您使用时,模式匹配操作将在字符集解码操作的目标字符缓冲区上工作(当源是InputStream或 时ByteChannel)。然后,当将匹配结果作为字符串传递时,它们将通过另一个批量复制操作从字符缓冲区创建。所以分块处理数据已经是常态,而不是例外。
这已被纳入 NIO 设计中。因此,不像API 那样支持单字节读取方法并通过提供缓冲装饰器来修复它InputStream,NIO 的ByteChannel子类型仅提供使用应用程序管理的缓冲区的方法。
所以我们可以说,缓冲并没有提高性能,它是传输和处理数据的自然方式。相反,由于需要从自然批量数据操作转换为单项操作,不缓冲会降低性能。
| 归档时间: |
|
| 查看次数: |
513 次 |
| 最近记录: |