Сохраняет ли значение str.length() в переменной перед тем, как использовать его в цикле for, какие-либо улучшения производительности в Java?
Короче говоря, JVM внутренне оптимизирует следующий код
public void test(String str)
{
int a = 0;
for( int i = 0; i < 10; i++)
{
a = a + str.length();
}
}
вести себя так же эффективно, как ниже:
public void test(String str)
{
int len = str.length();
int a = 0;
for( int i = 0; i < 10; i++)
{
a = a + len;
}
}
Если он оптимизирует, делает ли это это путем кэширования значения str.length() внутри?
Ответы
Ответ 1
хороший ответ Эллиот Ф.
Я сделал гораздо более простой тест и использовал два метода с очень большим количеством повторений и каждый раз.
Первый метод (когда длина вычисляется только один раз) был последовательно быстрее второго.
Здесь весь тестовый класс, который я создал,
package _testing;
import java.util.Date;
public class Speed {
long count = 5000000;
public static void main(String[] args) {
long start, finish;
Speed sp = new Speed();
start = new Date().getTime();
sp.test("test");
finish = new Date().getTime();
System.out.println("test 1:"+(finish - start));
start = new Date().getTime();
sp.test2("test");
finish = new Date().getTime();
System.out.println("test 2:"+(finish - start));
}
public void test(String str) {
int len = str.length();
int a = 0;
for (int i = 0; i < count; i++) {
a = a + len;
}
}
public void test2(String str) {
int a = 0;
for (int i = 0; i < count; i++) {
a = a + str.length();
}
}
}
Результат выглядит следующим образом:
test 1:7
test 2:22
Ответ 2
Я создал следующие два метода:
public void test(String str) {
int len = str.length();
int a = 0;
for (int i = 0; i < 10; i++) {
a = a + len;
}
}
public void test2(String str) {
int a = 0;
for (int i = 0; i < 10; i++) {
a = a + str.length();
}
}
Затем я использовал javap -v
для генерации для первого метода test
public void test(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=5, args_size=2
0: aload_1
1: invokevirtual #16 // Method java/lang/String.length:()I
4: istore_2
5: iconst_0
6: istore_3
7: iconst_0
8: istore 4
10: goto 20
13: iload_3
14: iload_2
15: iadd
16: istore_3
17: iinc 4, 1
20: iload 4
22: bipush 10
24: if_icmplt 13
27: return
и для test2
public void test2(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: iconst_0
1: istore_2
2: iconst_0
3: istore_3
4: goto 17
7: iload_2
8: aload_1
9: invokevirtual #16 // Method java/lang/String.length:()I
12: iadd
13: istore_2
14: iinc 3, 1
17: iload_3
18: bipush 10
20: if_icmplt 7
23: return
Таким образом, ответ, похоже, будет некоторым преимуществом для хранения длины один раз (он создает более короткий байт-код, эквивалентный 23 против 27 строк), что, кажется, предполагает, что он может работать лучше, но я сомневаюсь, что это действительно может быть измеряется. Особенно после того, как код был скомпилирован JIT).
Наконец, вы можете рассмотреть
public void test(String str)
{
int a = 0;
for( int i = 0, len = str.length(); i < 10; i++) {
a = a + len;
}
}
или просто
int a = 10 * str.length();