简体   繁体   English

如何提高读取 InputStream 的性能?

[英]How can I increase performance on reading the InputStream?

This very well may just be a KISS moment, but I feel like I should ask anyway.这很可能只是一个 KISS 时刻,但我觉得无论如何我都应该问。

I have a thread and it's reading from a sockets InputStream.我有一个线程,它正在从 sockets InputStream 读取。 Since I am dealing in particularly small data sizes (as in the data that I can expect to recieve from is in the order of 100 - 200 bytes), I set the buffer array size to 256. As part of my read function I have a check that will ensure that when I read from the InputStream that I got all of the data.由于我正在处理特别小的数据大小(因为我可以期望接收的数据大约为 100 - 200 字节),我将缓冲区数组大小设置为 256。作为我读取 function 的一部分,我有一个检查这将确保当我从 InputStream 中读取所有数据时。 If I didn't then I will recursively call the read function again.如果我没有,那么我将再次递归调用读取 function。 For each recursive call I merge the two buffer arrays back together.对于每个递归调用,我将两个缓冲区 arrays 重新合并在一起。

My problem is, while I never anticipate using more than the buffer of 256, I want to be safe.我的问题是,虽然我从没想过会使用超过 256 的缓冲区,但我想保证安全。 But if sheep begin to fly and the buffer is significantly more the read the function (by estimation) will begin to take an exponential curve more time to complete.但是,如果羊开始飞行并且缓冲区明显更多,则读取 function(据估计)将开始需要更多时间才能完成指数曲线。

How can I increase the effiency of the read function and/or the buffer merging?如何提高读取 function 和/或缓冲区合并的效率?

Here is the read function as it stands.这是 function 的原样。

int BUFFER_AMOUNT = 256;

private int read(byte[] buffer) throws IOException {
   int bytes = mInStream.read(buffer); // Read the input stream

   if (bytes == -1) { // If bytes == -1 then we didn't get all of the data

        byte[] newBuffer = new byte[BUFFER_AMOUNT]; // Try to get the rest
        int newBytes;
        newBytes = read(newBuffer); // Recurse until we have all the data

        byte[] oldBuffer = new byte[bytes + newBytes]; // make the final array size

        // Merge buffer into the begining of old buffer.
        // We do this so that once the method finishes, we can just add the 
        // modified buffer to a queue later in the class for processing.
        for (int i = 0; i < bytes; i++) 
            oldBuffer[i] = buffer[i];

        for (int i = bytes; i < bytes + newBytes; i++) // Merge newBuffer into the latter half of old Buffer
            oldBuffer[i] = newBuffer[i];
        // Used for the recursion

        buffer = oldBuffer; // And now we set buffer to the new buffer full of all the data.
        return bytes + newBytes;
    }
    return bytes;
}

EDIT: Am I being paranoid (unjustifiedly) and should just set the buffer to 2048 and call it done?编辑:我是偏执狂(不合理),应该将缓冲区设置为 2048 并称之为完成吗?

BufferedInputStream , as noted by Roland, and DataInputStream.readFully() , which replaces all the looping code. Roland 指出的BufferedInputStreamDataInputStream.readFully() ,它替换了所有循环代码。

int BUFFER_AMOUNT = 256;

Should be final if you don't want it changing at runtime.如果您不希望它在运行时更改,则应该是最终的。

if (bytes == -1) {

Should be !=应该是!=

Also, I'm not entirely clear on what you're trying to accomplish with this code.此外,我并不完全清楚您要使用此代码完成什么。 Do you mind shedding some light on that?你介意对此有所了解吗?

I have no idea what you mean by "small data sizes".我不知道您所说的“小数据量”是什么意思。 You should measure whether the time is spent in kernel mode (then you are issuing too many read s directly on the socket) or in user mode (then your algorithm is too complicated).您应该衡量时间是在 kernel 模式(那么您直接在套接字上发出太多read )还是在用户模式(那么您的算法太复杂)。

In the former case, just wrap the input with a BufferedInputStream with 4096 bytes of buffer and read from it.在前一种情况下,只需使用BufferedInputStream包装输入,其中包含 4096 字节的缓冲区并从中读取。

In the latter case, just use this code:在后一种情况下,只需使用以下代码:

/**
  * Reads as much as possible from the stream.
  * @return The number of bytes read into the buffer, or -1
  *         if nothing has been read because the end of file has been reached.
  */
static int readGreedily(InputStream is, byte[] buf, int start, int len) {
  int nread;
  int ptr = start; // index at which the data is put into the buffer
  int rest = len; // number of bytes that we still want to read

  while ((nread = is.read(buf, ptr, rest)) > 0) {
    ptr += nread;
    rest -= nread;
  }

  int totalRead = len - rest;
  return (nread == -1 && totalRead == 0) ? -1 : totalRead;
}

This code completely avoids creating new objects, calling unnecessary methods and furthermore --- it is straightforward.这段代码完全避免了创建新对象、调用不必要的方法等等——它很简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在不读取的情况下检查 InputStream 是否为空? - How can I check if an InputStream is empty without reading from it? 我如何gzip一个InputStream并返回一个InputStream? - How can I gzip an InputStream and return an InputStream? 提高阅读表现 - Increase the performance of reading 如何使用WebSocketServer提高Java Computer Vision的性能? - How can I increase performance of Java Computer Vision using WebSocketServer? 读完后如何锁定InputStream并释放 - How I can put a lock around InputStream and release when reading is done 如何使方法 isEmpty() 为真,以便我最终可以从 InputStream 读取数据? - How to make the method isEmpty() true so that I can end up reading data from InputStream? 如何有效地将未压缩的InputStream转换为gzip的InputStream? - How can I convert an uncompressed InputStream into a gzip'ed InputStream efficiently? 调整在java中读取大型InputStream的性能 - Tuning the performance of reading a large InputStream in java 你怎么能以编程方式取消从InputStream读取? - How can you programatically cancel reading from an InputStream? 在这种情况下,多线程如何帮助提高性能? - How can multithreading help increase performance in this situation?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM