Почему андроид String.format собака медленная? - PullRequest
6 голосов
/ 11 июня 2011

Я выполнял действие ListView с пользовательскими нарисованными представлениями и имел следующий код:

@Override
public void onDraw(Canvas canvas)
{
    super.onDraw(canvas);
    ....
    canvas.drawText(String.format("%02d: %dx%d", position, w, h),
        10, 15, cached_paint);
}

Практически ничего другого в методе onDraw, так что это сводило меня с ума относительно того, почему прокрутка была такойбедные.Случайно я изменил параметр drawText, чтобы не использовать String.format, и внезапно прокрутка снова превратилась в шелк.На самом деле следующее практически то же самое, но хорошо работает:

canvas.drawText("" + position + ": " + w + "x" + h,
    10, 15, cached_paint);

Я ошеломлен.Почему последний работает быстрее, чем вызов String.format?Я ожидаю, что конкатенация объектов создаст больше промежуточных объектов и в целом производительность мусора, но я обнаружил, что все наоборот.На самом деле, при работе с String.format я получал много сообщений о выделении / освобождении от виртуальной машины.

Так почему String.format такой медленный, когда он, очевидно, может быть быстрее (по крайней мере, если исходить из других программязыки, на которых создание объекта стоит дорого)?

Ответы [ 3 ]

6 голосов
/ 11 июня 2011

Конкатенация строк с + не генерирует много промежуточных объектов; в основном это StringBuffer и его внутренний массив символов (который может быть перераспределен, если у него не хватит емкости). Да, и строка, когда она через конкатенацию.

Кроме того, с + большая часть работы по анализу типов данных объектов, входящих в строку, выполняется во время компиляции. С помощью String.format это делается во время выполнения. В довершение всего, каждый тип примитива, который вы передаете в String.format, должен быть автоматически упакован, что генерирует намного больше объектов.

4 голосов
/ 11 июня 2011

Я ошеломлен.

Почему?

Почему последний быстрее, чем вызывает String.format?

Потому что написано на Java.%02d: %dx%d это не Java.Это должно быть проанализировано каждый раз, и правила выполняются каждый раз.Эти правила выполняются в Java через java.util.Formatter.

Теперь String.format() можно оптимизировать, заменив его реализацией с собственным кодом (C / C ++), но я думаю, что varargsи JNI становятся беспорядочными.

Я ожидаю, что конкатенация объектов создаст больше промежуточных объектов и в целом производительность мусора, но я обнаружил, что все наоборот.Фактически, при работе с String.format я получал много сообщений о выделении / освобождении от виртуальной машины.

Это могло бы быть из-за того, что String.format() довольно сложен и реализован в Java.

1 голос
/ 01 сентября 2011

Чтобы добиться максимальной производительности, вы можете создать средство форматирования из пакета java.text и кэшировать его.

final static DecimalFormat myFormat = new DecimalFormat("###");
@Override
public void onDraw(Canvas canvas)
{
    super.onDraw(canvas);
    ....
    canvas.drawText(myFormat.format(w) + "x" + myFormat(h));
}

Для еще большей производительности вы можете использовать более быструю конкатенацию строк. Но это другой вид оптимизации и не по теме для этого вопроса.

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