5 дек. 2008 г.

Java: FastException

Не помню точно источник, поэтому попытаюсь описать своими словами.

Бросание исключения в java является «накладной» операцией, однако это не повод не пользоваться ими.

В чём же основные накладные расходы на бросание исключения и как можно их уменьшить ?
Брошенное исключение это не только экземпляр некоторого класса, возможно с сообщением ошибки, но ещё и со стеком, откуда именно он был брошен.

За заполнение стека исключения отвечает метод fillInStackTrace в классе Throwable:
    /**
* Fills in the execution stack trace. This method records within this
* Throwable object information about the current state of
* the stack frames for the current thread.
*
* @return a reference to this Throwable instance.
* @see java.lang.Throwable#printStackTrace()
*/
public synchronized native Throwable fillInStackTrace();

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

Сравним SimpleException1 (обычное исключение):
public class SimpleException1 extends Exception {

}
и SimpleException2 («быстрое» исключение):
public class SimpleException2 extends Exception {
@Override
public Throwable fillInStackTrace() {
return this;
}
}

Тест:
public class TestSimpleExceptions {

@Test
public void test(){
int count = 100000;

long time1 = 0;
for(int i = 0; i < count; i++){
time1 -= System.currentTimeMillis();
try{
throw new SimpleException1();
}catch(SimpleException1 e){
// nothing
}
time1 += System.currentTimeMillis();
}

long time2 = 0;
for(int i = 0; i < count; i++){
time2 -= System.currentTimeMillis();
try{
throw new SimpleException2();
}catch(SimpleException2 e){
// nothing
}
time2 += System.currentTimeMillis();
}

System.out.println("time1:" + time1 + "ms, average:" + ((double)time1 / count) + "ms");
System.out.println("time2:" + time2 + "ms, average:" + ((double)time2 / count) + "ms");
}
}
Результаты на моей машине:
time1:612ms, average:0.00612ms
time2:162ms, average:0.00162ms

т.е «быстрое» исключение оказалось в ~4 раза быстрее обычного исключения.

Хотя абсолютные числа говорят о том, что игра не стоила свеч.

Комментариев нет: