2009-07-09 2 views
2

У меня есть следующий класс подкласса FilterInputStream с переопределением только одного метода. Однако производительность этого класса настолько бедна. Он выполняет на 1/10 скорости своего суперкласса. Я даже взял тот же исходный код из InputStream javasrc и использовал его в моем подклассе. Такая же производительность. Что-то не так с переопределяющими классами?Плохая производительность за счет переопределения класса Java?

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; 
} 

}

+1

Да, вы читаете() один за другим, если базовая буферизация отсутствует, она будет очень медленной. – akarnokd

+0

вот как реализуется java.io.InputStream, почему так быстро? – erotsppa

+0

Это базовый класс, каждая реализация переопределяет его методы. По умолчанию используется только местозаполнитель. – akarnokd

ответ

2

Этот метод читает байт по-байтам, я думаю, поэтому он так плохо работает. FilterInputStreams обычно просто обертывают другие входные потоки, поэтому, если вы не собираетесь делать какую-либо фильтрацию, просто вызовите read (byte [], int, int) на завернутый поток.

+2

Не изобретайте велосипед, если вам это действительно нужно. Вероятно, класс потока делает то, что вы хотите. – mcandre

+0

Я ничего не делаю, потому что я пытаюсь проверить производительность. Очевидно, что ничего не приносит производительность до 1/10 – erotsppa

+0

@erotsppa. Вы скопировали общий (по сути, никогда не использованный) код из класса InputStream, который крайне неэффективен. – jsight

0

Да, вы() один за другим, если нет основной буферизация происходит, то это будет очень медленно. Перейдите в BufferedInputStream, и он должен ускориться.

+0

Это не имеет никакого смысла, реализация FilterInputStream return in.read (b, off, len); где in - InputStream, а реализация чтения InputStream аналогична моей. (Я скопировал исходный код) – erotsppa

+0

InputStream - это базовый класс с некоторыми стандартными и для некоторых случаев неэффективной реализацией. Он используется из-за идиомы «использование суперкласса/суперинтерфейса»: InputStream in = new BufferedInputStream (новый FileInputStream («a»)); – akarnokd

0

Производительность для переопределения классов должна быть незначительной практически для всех целей.

Возможно, проблема в оформлении InputStream.

0

Есть ли что-то не так с переопределяющими классами?

нет, это не так.

Однако FilterInputStream - это просто декоратор вокруг InputStream, который вы передаете с помощью конструктора. Я бы обернуть входной поток вокруг буферном один, подобно BufferedInputStream:

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

+1 от меня. Я не могу объяснить это более подробно. – akarnokd

0

Большую часть времени, когда разработчики считают, что они нашли ошибку в JDK или как Java работает, его обычно просто неправильно со стороны разработчика. Java уже более десяти лет, и наиболее распространенные ошибки уже решены.

Существует более чем несколько неправильных проектных решений, вокруг которых, возможно, сейчас слишком сложно исправить, но я не могу думать о том, что влияет на производительность или не имеет известной работы.