Возможное улучшение производительности для AbstractStringBuilder

Я проводил тесты с Java StringBuilder, особенно с функцией replace(int, int, String), которая реализована в классе AbstractStringBuilder следующим образом:

public AbstractStringBuilder replace(int start, int end, String str) {
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (start > count)
        throw new StringIndexOutOfBoundsException("start > length()");
    if (start > end)
        throw new StringIndexOutOfBoundsException("start > end");

    if (end > count)
       end = count;
    int len = str.length();
    int newCount = count + len - (end - start);
    if (newCount > value.length)
       expandCapacity(newCount);

    System.arraycopy(value, end, value, start + len, count - end);
    str.getChars(value, start);
    count = newCount;
    return this;
}

Вызов функции Arraycopy «перемещает» части содержимого массива символов значения, чтобы освободить место для введенного позже содержимого str (str.getChars(value, start)). С моей точки зрения, эту копию массива следует делать только в том случае, если длина строки в любом случае не соответствует пространству, которое должно быть перезаписано в массиве символов.

Ясно, что кто-то очень отчаянно пытается рассматривать это как проблему с производительностью, хотя выполнение тестов с большими массивами символов (>500 тыс. символов) и копированием массива в замещающем классе StringBuilder привело к заметному улучшению производительности.

Протестировано с java 6 на 32-битной платформе Windows с тем же экземпляром StringBuilder для нескольких миллионов вызовов замены.

Считаете ли вы это неважным, ошибкой или я что-то полностью упускаю?


person Big Bad Baerni    schedule 08.03.2012    source источник
comment
неважно, однозначно.   -  person vulkanino    schedule 08.03.2012
comment
Отправьте запрос в Oracle/Sun и посмотрите, что они скажут. Я не думаю, что это ошибка, потому что код работает. Назовите это возможным улучшением, и вы можете получить больше. Я бы также подумал, что вы можете что-то полностью упустить. Возможно, вы думаете об одном крайнем случае, который не является общепринятым. У меня сейчас нет времени проверять ход ваших мыслей.   -  person duffymo    schedule 08.03.2012
comment
Я подозреваю, что arraycopy в любом случае достаточно умен, чтобы избежать ненужной работы; единственное улучшение производительности будет происходить за счет исключения проверки, необходимой для определения того, что работа не нужна. Я думаю, что вы правы, на самом деле.   -  person Ernest Friedman-Hill    schedule 08.03.2012
comment
Я проводил тесты с помощью arraycopy. Замена меньших массивов собой была быстрее, чем с большими массивами. По крайней мере, размер массива имеет значение, независимо от arraycopy для обнаружения ненужных копий.   -  person Big Bad Baerni    schedule 08.03.2012
comment
Не уверен, что это оптимизация. Я подозреваю, что дополнительные затраты на гораздо более распространенный случай, когда вы не копируете в одно и то же место, не стоят повышения производительности в этом редком случае.   -  person Louis Wasserman    schedule 08.03.2012


Ответы (1)


Я бы передал это как запрос на улучшение.

Что-то типа

if (end != start + len)
    System.arraycopy(value, end, value, start + len, count - end);

Дальнейшим улучшением будет изменение копии массива.

public static void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length) {
    if (srcPos != destPos && length != 0)
       arraycopy0(src, srcPos, dest, destPos, length);

}

private static native void arraycopy0(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);
person Peter Lawrey    schedule 08.03.2012