Из двух фрагментов вы вывешенные, я не хотел бы сказать. Я бы согласился с Виллом, что это почти не имеет никакого отношения к общей производительности вашего кода - и если это не так, вы можете просто внести изменения и определить для себя, что наиболее быстро для ваших данных с вашей JVM на вашем оборудовании.
Сказанное, вероятно, что второй фрагмент будет лучше, если сначала преобразовать строку в массив символов, а затем выполнить итерации по массиву. Выполнение этого способа будет выполнять служебные данные String только один раз (преобразование в массив) вместо каждого вызова. Кроме того, вы можете передать массив непосредственно в конструктор String с некоторыми индексами, который более эффективен, чем принимать char из массива для передачи его отдельно (который затем преобразуется в массив символов):
String s = "abcdefg";
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++) {
newFunction(String.valueOf(chars, i, 1));
}
Но, чтобы укрепить мой первый момент, когда вы смотрите на то, чего фактически избегаете при каждом вызове String.charAt()
- это две проверки границ, (ленивое) логическое ИЛИ и добавление. Это не приведет к заметным различиям. Также нет различий в конструкторах String.
По сути, обе идиомы в порядке с точки зрения производительности (ни одна из них не сразу явно неэффективна), поэтому вы не должны тратить больше времени на их работу, если профилировщик не показывает, что это занимает большую часть времени выполнения вашего приложения.И даже тогда вы почти наверняка получите больше выигрышей в производительности за счет реструктуризации вашего поддерживающего кода в этой области (например, newFunction
возьмите всю строку); java.lang.String довольно хорошо оптимизирована к этому моменту.
Как только вам передадут строку, вам нужно немного изменить свое тестирование в первом тесте. {char [] s = "abcdefg" .toCharArray();} должен быть внутри цикла или даже лучше (чтобы избежать умной оптимизации JVM, поместите весь цикл и .toCharArray() внутри отдельной функции). Важно измерить все начальные накладные расходы, а также затраты на цикл. Тем более, что производительность может реалистично переходить от одного к другому на основе длины строки. Таким образом, тестирование различных длин укусов также важно. – MatBailie
+1 для ответа на вопрос. – gustafc
Переместил «s» внутри цикла и добавил assert(), чтобы предотвратить оптимизацию JVM newFunction(). Конечно, сейчас он медленнее, но относительные измерения все те же. Моя точка зрения состоит лишь в том, что есть возможности для оптимизации, если проблема точно известна. Дело не в том, чтобы изменить какую функцию использовать для определенной операции, а чтобы увидеть операцию на более высоком уровне для улучшения, например. путем кэширования – mhaller