为什么InputStream.available()如此耗时?

时间:2013-03-06 14:09:14

标签: java io profiling pcap jvisualvm

我已经实现了自己的类来读取pcap个文件。 (二进制文件,即tcpdump,wireshark)

public class PcapReader implements Iterator<PcapPacket> {
    private InputStream is;

    public PcapReader (File file) throws FileNotFoundException, IOException {
        is = this(new DataInputStream(
             new BufferedInputStream(
                 new FileInputStream(file))));
    }

    @Override
    public boolean hasNext () {
        try {
            return (is.available() > 0);
        } catch (IOException e) {
            return false;
        }
    }

    //pseudo code!
    @Override
    public PcapPacket next () {
        is.read(header);
        is.read(body);

        return new PcapPacket(header, body);
    }

    //more code here
}

然后我像这样使用它:

PcapReader reader = new PcapReader(file);
while (reader.hasNext()) {
    PcapPacket pcapPacket = reader.next();
    //process packet
}

被测文件有190 Mb。我还使用JVisualVM进行配置。

  • hasNext()被称为170万次,时间 7.7

  • next()被调用的次数相同,时间 3.6

我的主要问题是为什么hasNext()绝对值非常耗时,而且比next大两倍?

3 个答案:

答案 0 :(得分:2)

当您致电is.available()时,在hasNext()方法中,它会逐步实施FileInputStream.available()。这是一种原生方法,可以从FileInputStream source code看到。

最后,这确实是一个耗时的操作,因为如果有更多数据可供读取,文件操作的操作系统实现必须提前检查。因此,它实际上会在不更新文件指针(或将其更新回原始位置)的情况下执行读取操作,只是为了检查是否存在“下一个”字节。

答案 1 :(得分:1)

我敢肯定,available()方法的内部(本机)实现类似于返回一些return availableSize;,但更复杂。流使用OS API计算可用数据;特别是,例如,对于日志文件,由Stream读取它们。

答案 2 :(得分:1)

  

我已经实现了自己的类来阅读pcap个文件。

因为您没有使用jNetPcap,或者 使用jNetPcap,但需要可以从File读取的内容?

如果是后者,你可能想要使用一个模式而不是一个具有“更多数据可用”方法的模式和一个单独的“如此读取数据”方法;读取数据的东西,或者返回“可用数据包”/“文件结束”/“错误”指示,或者为后面的一个或两个条件抛出异常(DataInputStream似乎会抛出I /的异常O错误和EOF,所以为你的班级做同样的事情可能是有道理的。)

是的,这意味着它不能是Iterator,但也许Iterator最初并不打算代表顺序文件中的记录(此外,如果你真的希望它是一个Iterator,您打算如何处理remove方法?)。

如果你可以避免需要从File读取,那么你可以使用jNetPcap自己的例程来读取捕获文件,在libpcap 1.1.0及更高版本中,它也可以读取一些pcap-ng文件。