【问题标题】:Android InputStream.read() horribly slowAndroid InputStream.read() 非常慢
【发布时间】:2013-04-05 09:32:04
【问题描述】:

我正在开发一个需要与服务器(在我的 PC 上运行)通信的 Android 应用程序,该应用程序也是由我编写的。 问题是 InputStream.read() 需要很长时间,处理 200kb 需要大约 30 秒。也许以某种方式涉及垃圾收集,在我的循环中它会不时被调用,但列出的延迟只有 2 或 3 毫秒,总共可能是 20 毫秒,所以我认为这不是问题。

我的代码:

client = new Socket("192.168.1.1", 1235);
client.setTcpNoDelay(true);
client.setReceiveBufferSize(1048576);
InputStream is = client.getInputStream();

byte[] buffer = new byte[1048576];
int i = 0;
int length = -1;

while (true)
{
    int b = is.read();
    if (b == -1)
    {
        success = false;
        break;
    }
    buffer[i] = (byte) b;

    if (i == length)
        break;

    if (i == 3)
    {
        length = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;
    }

    i++;
}

我在 Java 方面并没有真正的经验,并且在 Android 编程方面完全是初学者,所以我不知道为什么它这么慢。

【问题讨论】:

  • 建议:如果你想在Android中做一个服务器-客户端应用程序,我强烈建议你检查一些middleware,它会为你做通信,例如。 Apache Thrift.

标签: java android networking client inputstream


【解决方案1】:

您一次读取 1 个字节。这是令人难以置信的低效。您想一次读取大量字节 - 尽可能多。这就是您的应用运行缓慢的原因。

【讨论】:

    【解决方案2】:

    为什么要单独读取每个字节?看起来您确实想读取前 3 个字节并计算出您的长度,然后读取该块。

    IE:

    final byte[] lengthBuffer = new byte[3];
    
    int b = is.read(lengthBuffer);
    
    // make sure b was 3 and do your length calculation
    
    final byte buffer = new byte[length];
    
    b = is.read(buffer);
    
    // check b and then you have your bytes
    

    然后,您至少可以获得 Inputstream 可以提供的用于读取数据块而不是一次读取一个字节的优化。而且您不会像现在那样分配那个巨型阵列。

    【讨论】:

    • 好的,更快,更快,甚至太快:/ 现在它在所有数据都存在之前就完成了......顺便说一句:我知道进行 200k 次迭代不如优化的快,但是 30 秒很有趣,这应该仍然只需要几毫秒,.read() 必须非常低效地实现
    • 好的,我只是循环读取直到达到长度,仍然比读取每个字节快一千倍
    • @Hidden Read 的写入效率并不低——它的访问硬件。通过对流进行大量小读取,您可以从硬件缓冲区进行大量小读取。这需要时间——你不再以时钟速度运行,你受到总线时序和延迟的限制。在对网络、存储等进行任何操作时,您必须意识到最终您会遇到物理组件并且需要编写它们的工作方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    相关资源
    最近更新 更多