【问题标题】:Poor performance by overriding Java class?重写 Java 类导致性能不佳?
【发布时间】:2009-07-09 15:33:06
【问题描述】:

我有以下 FilterInputStream 的子类,只覆盖了一个方法。然而,这门课的表现太差了。它的运行速度是其超类的 1/10。我什至从 javasrc 的 InputStream 中获取了相同的源代码,并在我的子类中使用了它。同样的表现受到打击。覆盖类有什么问题吗?

public class NewLineStream extends FilterInputStream    {


public NewLineStream(InputStream in) {
    super(in);
}



public int read(byte[] b, int off, int len) throws IOException  {       
    if (b == null) {
        throw new NullPointerException ();
    } else if ((off < 0) || (off > b.length) || (len < 0) ||
            ((off + len) > b.length) || ((off + len) < 0)) {
        throw new IndexOutOfBoundsException ();
    } else if (len == 0) {
        return 0;
    }

    int c = read();
    if (c == -1) {
        return -1;
    }
    b[off] = (byte)c;

    int i = 1;
    try {
        for (; i < len ; i++) {
            c = read();
            if (c == -1) {
                break;
            }
            if (b != null) {
                b[off + i] = (byte)c;
            }
        }
    } catch (IOException  ee) {
    }
    return i;
}

}

【问题讨论】:

  • 是的,你一个一个地读取(),如果没有底层缓冲,它会很慢。
  • java.io.InputStream就是这样实现的,为什么那么快?
  • 它是一个基类,每个实现都会覆盖它的方法。默认只是一个占位符。
  • 你能展示一下你如何使用你的类的代码吗?

标签: java file-io performance


【解决方案1】:

这种方法是逐字节读取的,我想这就是它性能如此糟糕的原因。 FilterInputStreams 通常只是包装其他输入流,所以如果您不打算进行任何过滤,只需在包装后的流上调用 read(byte[], int, int)。

【讨论】:

  • 除非你真的需要,否则不要重新发明轮子。可能有一个流类可以满足您的需求。
  • 我什么都没做,因为我正在尝试测试性能。显然什么都不做会使性能下降到 1/10
  • @erotsppa - 您从 InputStream 类中复制了通用(基本上从未使用过)代码,效率极低。
  • 我在哪里可以得到实际的实现?我需要重写 read(),但是没有 read(byte[]) 的源代码,我做不到。
  • 你过滤的是什么 InputStream? FileInputStream 和 ByteArrayInputStream 实现了“int read(byte b[], int off, int len)” 方法以及“read()” 来优化一次读取多个字节。您的过滤器强制所有调用改为使用单字节读取,这可能会更慢(尤其是来自文件)。如果您不想更改您的实现,您可以使用 BufferedInputStream 包装源 InputStream,这应该会在一定程度上提高性能。还要注意 LineNumberInputStream 的源看起来像你的,所以也许 BufferedInputStream 是可以接受的。
【解决方案2】:

是的,你一个一个地读取(),如果没有底层缓冲,它会很慢。传入一个 BufferedInputStream,它应该会加快速度。

【讨论】:

  • 这没什么意义,FilterInputStream的实现是return in.read(b, off, len);其中in是一个InputStream,InputStream的读取实现和我的一样。 (我复制了源代码)
  • InputStream 是一个基类,具有一些默认值,在某些情况下实现效率低下。之所以使用它是因为“使用超类/超接口”习语:InputStream in = new BufferedInputStream(new FileInputStream("a"));
【解决方案3】:

对于几乎所有目的,重写类的性能命中应该可以忽略不计。

也许问题出在您正在装饰的InputStream 上。

【讨论】:

    【解决方案4】:

    重写类有什么问题吗?

    不,它没有。

    但是,FilterInputStream 只是您使用构造函数传递的 InputStream 周围的装饰器。我会将我的输入流包裹在一个缓冲的流中,比如BufferedInputStream:

    NewLineStream nws = new NewLineStream(new BufferedInputStream(in));
    

    【讨论】:

      【解决方案5】:

      大多数时候,当开发人员觉得他们发现了 JDK 中的错误或 Java 的工作原理时,这通常只是开发人员的误解。 Java 已经十多年了,最常见的 bug 已经解决了。

      现在可能很难解决的糟糕设计决策有很多,但我想不出有什么影响性能或没有已知的解决方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-18
        • 1970-01-01
        • 1970-01-01
        • 2014-12-16
        • 1970-01-01
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多