Скорость Concat строки в Java - PullRequest
3 голосов
/ 09 июня 2011

Я быстро создавал прототип SQL-запроса, и вместо того, чтобы делать его правильно, я просто решил разбить его с помощью цепочки конкатов, все время думая, что это будет очень медленно, но это не такважно, потому что я просто тестировал запрос.К моему удивлению, Java говорит, что этот код занимает 0 мс для завершения?Разве это не займет больше времени, чтобы сделать это с +, а не StringBuilder или аналогичным?

long t = System.currentTimeMillis();
String load = "";
for (String s : loadFields)
    load += s + ", ";

String sql = "SELECT ";
sql += load + "sum(relevance) AS 'score' " +
        "FROM ( ";

for (int i = 0; i < searchFields.length; i++) {
    sql += "SELECT ";
    sql += load;
    sql += rels[i] + " AS relevance FROM articles WHERE " +
            searchFields[i];

    sql += " LIKE '%" + terms[0] + "%' ";
    for (int z = 1; z < terms.length; z++)
        sql += "AND " + searchFields[i] + " LIKE '%" + terms[z] + "%' ";

    if (i != searchFields.length - 1) sql += " UNION ALL ";
}

sql += ") results GROUP BY " + load.substring(0, load.length() - 2) + " ";
sql += "ORDER BY score desc, date desc";
System.out.println("Build Time: " + (System.currentTimeMillis() - t) + " ms");

Да, это очень уродливо, но дело не в том, чтобы интерпретировать SQL, а в том, чтобы сказать,мне, почему это так быстро.

Build Time: 0 ms

Редактировать: Я выполнил тест 10000 раз с 20 терминами, и это заняло около 10 секунд, так что около 1/ 10 миллисекунд.Теперь, когда я думаю об этом, совершенно очевидно, что это не так уж много для вычислений, если я не начну получать действительно длинные строки.

Ответы [ 4 ]

9 голосов
/ 09 июня 2011

Вы делаете только 29 конкатенаций - я надеюсь, что это займет менее миллисекунды.

Если вы хотите протестировать этот код с реализацией StringBuilder, вы должны повторить его примерно 10000 раз (и выполнить надлежащую разминку JVM).

Benchmark

Мне было любопытно посмотреть, в чем именно заключается разница в этом случае, поэтому я преобразовал ваш код для использования .concat() и StringBuilder и провел сравнительный анализ с 10 000 итераций (2 000 прогревов), с 5 полями и 20 терминами, все они случайным образом сгенерировали 32 строки символов.

Результаты (в миллисекундах):

   plus: 19656 (0.5/ms)
 concat: 5656  (1.77/ms)
builder: 578   (17.3/ms)
2 голосов
/ 09 июня 2011

Строки, которые вы объединяете, очень короткие. Попробуйте использовать строки длиной 100 000 или более (напишите некоторый код для генерации огромных строк), а затем сделайте это несколько сотен раз. С короткими строками и несколькими конкатами разница слишком мала, чтобы ее можно было измерить.

1 голос
/ 09 июня 2011

Насколько я понимаю, выполнение + означает, что java создает копию вашей исходной строки и каждый раз добавляет новую часть в копию. Я думаю, что это будет медленнее, но в любом случае это определенно займет больше памяти, чем StringBuilder. Кажется, было бы намного эффективнее иметь StringBuilder, к которому вы продолжали добавлять, и только .toString или String.valueOf(), когда вы закончите добавлять вещи.

1 голос
/ 09 июня 2011

Вы измеряете время, используя миллисекундные часы.

  • Абсолютный наименьший интервал, который вы можете измерить, составляет одну миллисекунду. Это, как правило, более одного миллиона циклов аппаратных часов. Процессор текущего поколения может выполнять много вычислений за это время.

  • Возможно, что фактическая гранулярность миллисекунды составляет несколько миллисекунд. (В отличие от операционной системы текущего поколения, но я помню дни, когда такт составлял 20 миллисекунд.)

В любом случае, неудивительно, что измеренное время обычно равно нулю.


Чтобы получить значимое измерение, вам нужно обвести этот код и запустить его сотни тысяч раз. И обведите еще одну петлю, чтобы повторно запустить тест ... пока не стабилизируется измеренное время.

Наконец, это будет интенсивное распределение, и вам нужно включить амортизированное время GC. (Оптимизированная версия, использующая StringBuilder, выиграет частично, НЕ занимая слишком много места.)

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