【问题标题】:Measure intermediate throughput when writing to OutputStream [or] Why is write() blocking, while read() is not?在写入 OutputStream 时测量中间吞吐量 [或] 为什么 write() 会阻塞,而 read() 不会?
【发布时间】:2012-04-28 01:56:51
【问题描述】:

我需要测量上传和下载大文件的中间吞吐量(通过 FTP 使用Apache Commons Net API)。

下载:(没问题)

一切都可以下载,使用如下代码:

InputStream is = ftp.retrieveFileStream(filePath);
byte[] buffer = new byte[256 * 1024];
int read;

while ((read = is.read(buffer, 0, buffer.length)) != -1) {
    Log.v(TAG, "Read = " + read);
}

这里,缓冲区大小为 256 KB,正在下载的文件的总大小为 1 MB。对is.read() 的每个单独调用仍然只返回大约 2 KB。在这种情况下,read() 不会阻塞,直到缓冲区已满。这使我能够测量中间下载吞吐量。到目前为止一切顺利。

上传:(有问题)

现在痛苦来了。当我分配一个类似大小的缓冲区来写入 OutputStream 时,对 write() 的调用会阻塞,直到整个 256 KB 都被写入。

为什么只有write() 会阻止,而read() 不会?

所以我尝试使用nio。与Outputstream 的 write() 不同,WritableByteChannel 的 write() 方法返回实际写入的字节数。所以它必须是非阻塞的,对吧?没有这样的运气。这个write() 也会阻塞,直到整个缓冲区都被写入。代码如下:

byte[] buffer = new byte[256 * 1024];
new Random.nextBytes(byteArray);

OutputStream os = ftp.storeFileStream(filePath);
WritableByteChannel channel = Channels.newChannel(os);
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
int written = channel.write(byteBuffer);

那么当上传阻塞时如何测量中间吞吐量呢?

一种方法是使用 Android 的TrafficStats API。但它也有自己的挫败感。根据文档,这些统计信息可能并非在所有平台上都可用。还需要处理整数计数器溢出(2GB 后)、counter reset bugson some platforms 在 3G 和 Wifi 之间切换等场景。

谁能告诉我一条出路?

【问题讨论】:

    标签: java android nio apache-commons java-io


    【解决方案1】:

    为什么只有 write() 会阻塞,而 read() 不会?

    因为这就是底层操作系统的行为方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      • 2018-05-05
      相关资源
      最近更新 更多