LINUX.ORG.RU

Многочисленные проверки индекса массива в Java оптимизируются JIT'ом?

 ,


0

8

Скажем есть такой код:

for (int i = 0; i < value.length(); i++) {
    char currChar = value.charAt(i);
    ... // i ниже не изменяется
}

...
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }
Логично выбросить проверку из charAt, зачем она нужна? Делают ли это современные JIT'ы для подобных ситуаций? Более того, подгружаясь в код стандартных классов подобных проверок +100500... И я как понимаю, под капотом, к этим проверкам добавляется проверка на выход индекса за границы массива. Т.е. в данном месте:
return value[index];
Докидывается еще одна невидимая проверка с выбросом ArrayIndexOutOfBoundsException. Это безобразие и правда попадает в рантайм? Или современные JIT'ы выкидывают большую часть подобных перепроверок для стандартных классов типа String, ArrayList и т.д.?

★★★★★

public

Как одна из возможных причин.

orm-i-auga ★★★★★
()

Логично выбросить проверку из charAt, зачем она нужна? Делают ли это современные JIT'ы для подобных ситуаций?

Да. После инлайна будут очевидные инварианты. В более сложных случаях может и не убрать. Стандартные классы тут не при чём, JIT про них ничего не знает и не может знать, т.к. тебе ничего не мешает подсунуть модифицированную стандартную библиотеку.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

Чего изгаляться-то? Исходные тексты должны быть читаемы и поддерживаемыми человеком

Что мешает пробовать различные варианты и натравливать профилировщик на результирующий код?

iZEN ★★★★★
()

Логично выбросить проверку из charAt, зачем она нужна?

Барьер абстракций (SICP): завтра сделают, что value внутри String'а будет хранить Unicode code point'ы (int), а не char'ы и реализация charAt станет какой-то такой (очень упрощённо):

public final class Utf32String implements CharSequence {

    private final int[] codePoints;
    private final int charCount;

    public Utf32String(String oldString) {
        codePoints = oldString.codePoints().toArray();
        charCount = str(codePoints).length();
    }

    @Override
    public char charAt(int index) {
        if (index < 0 || index >= charCount) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return str(codePoints).charAt(index);
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        // some implementation
        return null;
    }

    @Override
    public int length() {
        return charCount;
    }

    @Override
    public String toString() {
        return str(codePoints);
    }

    private static String str(int[] codePoints) {
        // just for proof of concept
        return new String(codePoints, 0, codePoints.length);
    }
}

В итоге, нормальный код продолжит работать как раньше:

import java.io.PrintStream;

public final class NewStringDemo {

    private static final String USER = "foror";

    public static void main(String[] args) {
        test(USER);
        test(new Utf32String(USER));
    }

    private static void test(CharSequence cs) {
        final PrintStream ps = System.out;
        ps.println("Testing " + cs.getClass().getSimpleName() + ": " + cs);
        final int charCount = cs.length() + 1;
        for (int i = -1; i < charCount; i++) {
            try {
                ps.print(cs.charAt(i));
            } catch (StringIndexOutOfBoundsException e) {
                if (i >= charCount - 1) {
                    ps.println();
                }
                ps.println("\t// " + e.getMessage());
            }
        }
        ps.println();
    }
}

=>

Testing String: foror
	// String index out of range: -1
foror
	// String index out of range: 5

Testing Utf32String: foror
	// String index out of range: -1
foror
	// String index out of range: 5

Хотя по идее это должен быть какой-нибудь CharSequenceIndexOutOfBoundsException, ну да ладно.

В общем, StringIndexOutOfBoundsException — это API класса String, и если он выбросился, значит проблема в твоём коде (т.е. в коде, использующем класс String), а ArrayIndexOutOfBoundsException сигнализирует об ошибке в реализации класса String.

korvin_ ★★★★★
()
Ответ на: комментарий от Deleted

Weres же уже ответил выше.

И при чём тут «обычно»? Вы с mcgeek'ом что, документацию вообще не читаете? Или String'ом не пользуетесь?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Хорошо. Так и есть. Мы скорее русским языком коряво пользуемся. :D

Deleted
()
Ответ на: комментарий от Weres

Действительно. Перепутал с String из Kotlin, в котором это поле. Коллизии возникают, когда в проекте одновременно Kotlin и Java, а IDE делает автодополнение. Извините.

mcgeek
()
Последнее исправление: mcgeek (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.