Необходимо подавить fillStackTrace () для всех исключений в данном потоке - PullRequest
0 голосов
/ 29 ноября 2018

У нас есть большое Java-приложение (100 миллионов миллионов сообщений), которое может столкнуться с исключениями времени выполнения в любой момент - логика создается пользователями, и невозможно предвидеть каждый тип ошибки.Простым примером является NPE Null Pointer Exception, которое может произойти только для 1M из 100M записей.

Проблема заключается в том, что всякий раз, когда Java выдает исключение, оно вызывает дорогостоящий метод fillStackTrace ().В зависимости от глубины стека (временные затраты кажутся пропорциональными, а у нас глубокие стеки) снижение производительности может быть в 40 с лишним раз медленнее, чем без исключений.

Я знаю, как создавать собственные исключения и подавлять fillStackTrace (), поэтомуэто помогает, когда я могу обнаружить проблему и выдать свое собственное исключение, но я не могу понять, как встать перед чем-то вроде NPE и избежать fillStackTrace ().Я попытался манипулировать байт-кодом (нарушение безопасности, чтобы попытаться настроить Throwable), перегрузил поток и создал стек [0] в getStackTrace () (внутренняя трассировка стека выполняется в собственном коде, поэтому это не вызывается).У меня нет выбора, и мне нужна помощь.

Примечание. Заставить пользователя писать более качественные выражения нереально, у нас есть сотни пользователей (и планируют иметь тысячи), пишущих эти выражения, обратите внимание, что ониВы находитесь в Groovy, но проблема стоимости исключений не зависит, так как они происходят ниже в части стека Java.

Вот простой тест, иллюстрирующий проблему:

public class TestExceptionPerformance {

    @Test
    public void testMissingFieldException() {
        exceptionTest(1f, 10_000_000, 100);
        exceptionTest(null, 10_000_000, 100);
    }

    private void exceptionTest(Float value, int iterations, int stackDepth) {

        long start = System.currentTimeMillis();
        int exceptionCount = 0;

        for (int i=0; i < iterations; i ++) {
            try {
                multiplyMe(value, i, stackDepth);
            } catch (Throwable e) {
                exceptionCount++;
            }
        }
        System.out.println("With " + iterations + " transactions and " + exceptionCount +
                " exceptions thrown at stack depth " + stackDepth + ": " +
                (System.currentTimeMillis() - start) + "ms");
    }

    // perform multiplication deep in stack
    static private float multiplyMe(Float value, int multiplier, int recurse) {
        if (recurse > 0) return multiplyMe(value, multiplier, --recurse);
        return value.floatValue() * multiplier;
    }

}

Результаты:

С 10 000 000 транзакций и 0 исключений на глубине стека 100: 1 431 мс

С 10 000 000 транзакций и 10 000 000 исключений на глубине стека 100: 43 912 мс

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