Изчислява ли дължината на масива в java кеша в цикли

Да кажем, че имам масив, който бих искал да повторя:

int[] someArray = {1,2,3,4}

for (int i = 0; i < someArray.length; i++) {

    // do stuff
}

Тази дължина на масива ще бъде ли изчислена с всяка итерация или ще бъде оптимизирана да я изчисли само веднъж?

Трябва ли да итерирам масиви, като изчислявам дължината предварително и го предавам на цикъл?

for (int i = 0, length = someArray.length; i < length ; i++) {

    // do stuff
}

person John    schedule 10.06.2015    source източник
comment
stackoverflow.com/questions/9297899/   -  person Sagar Gandhi    schedule 10.06.2015
comment
@MonkeyDLuffy: Не виждам как това е свързано с производителността.   -  person Jon Skeet    schedule 10.06.2015
comment
Не трябва ли да е i<length във втория случай вместо i < someArray.length;?   -  person TheLostMind    schedule 10.06.2015


Отговори (3)


Както винаги за производителността: напишете най-простия код, който можете, и го тествайте, за да видите дали работи достатъчно добре.

Ако имате нужда само от елемента (а не от индекса), бих ви насърчил да използвате подобрения цикъл за:

for (int value : array) {
    ...
}

Съгласно JLS 14.14.2 това в общи линии е еквивалентно на първото ви парче код, но кодът говори само за това, което всъщност ви интересува.

Но ако имате нужда от индекса и ако приемем, че не променяте array никъде, вярвам, че JIT компилаторът ще оптимизира собствения код, за да извлече дължината само веднъж. Получаването на дължината е O(1) операция, тъй като в основата си това е просто поле в масива, но очевидно включва навлизане в паметта, така че е по-добре евентуалният код да направи това само веднъж. . но това не означава, че вашият код трябва да прави това. Имайте предвид, че не бих очаквал Java компилаторът (javac) да извърши тази оптимизация - бих очаквал JIT да го направи.

Всъщност вярвам, че един добър JIT действително ще види код като:

for (int i = 0; i < array.length; i++) {
    int value = array[i];
    ...
}

и да може да оптимизира проверките на границите на масива - може да разпознае, че ако има достъп до един и същ обект на масив през цялото време, това не може да се провали с грешка в границите на масива, така че може да избегне проверката. Той може да е в състояние да направи същото нещо за по-„умен“ код, който извлича дължината предварително, но оптимизациите на JIT често са насочени умишлено към много често срещани модели на код (за да се получи най-голямата „изгода за парите“ ) и горният начин за итерация върху масив е много често срещан.

person Jon Skeet    schedule 10.06.2015
comment
В case-1 arraylength байтова кодова инструкция се използва за всяка итерация. Във втория случай достъпът до локална променлива ще се случи за всяка итерация. Така че, гледайки байт-кода, case-2 изглежда има предимство. Но да, JIT най-вероятно ще оптимизира това - person TheLostMind; 10.06.2015
comment
@TheLostMind: Да, това е моята гледна точка: доверете се на JIT да се справи с това и напишете възможно най-чистия код. - person Jon Skeet; 10.06.2015

От JLS 7

10.7 Членове на масив

Всички членове на даден тип масив са следните: • Полето public final length, което съдържа броя на компонентите на масива. дължината може да бъде положителна или нула.

Връщайки се към въпроса ви, Java не преброява броя на елементите в масива на array.length. Връща стойността на public final int length, изчислена по време на създаването на масива.

person Sagar Gandhi    schedule 10.06.2015

Тъй като length е член на Array Така че вече е зададено, когато създавате масив, на всяка итерация имате достъп само до това свойство, нищо друго.

Така че или имате достъп до него като

    int myArrayLength=arr.length;
for(int i=0;i<myArrayLength;i++)

или като:

   for(int i=0;i<arr.length;i++)

Няма да има измерима промяна в ефективността.

person Neeraj Jain    schedule 10.06.2015
comment
Не е толкова лесно.. jvm използва отделна инструкция за байтов код, наречена arrayLength, за да определи дължината на масива - person TheLostMind; 10.06.2015