Java short, integer, long performance

Я читал, что JVM хранит внутренне короткие, целые и длинные как 4 байта. Я прочитал его из статьи с 2000 года, поэтому я не знаю, насколько это верно сейчас.

Для новых JVMs есть ли увеличение производительности при использовании short over integer/long? И изменилась ли эта часть реализации с 2000 года?

Спасибо

Ответы

Ответ 1

long  64 –9,223,372,036,854,775,808 to 9 ,223,372,036,854,775,807 
int   32 –2,147,483,648 to 2,147,483,647 
short 16 –32,768 to 32,767 
byte   8 –128 to 127 

Используйте то, что вам нужно, я бы подумал, что короткие шорты редко используются из-за небольшого диапазона, и он находится в формате big-endian.

Любое увеличение производительности будет минимальным, но, как я уже сказал, если вашему приложению требуется диапазон больше, чем короткий, с int. Длинный тип может быть слишком большим для вас; но все зависит от вашего приложения.

Вы должны использовать только короткие, если у вас есть проблема с пространством (память), в противном случае используйте int (в большинстве случаев). Если вы создаете массивы и пытаетесь это сделать, объявляя массивы типа int и short. Короткие будут использовать 1/2 пространства, а не int. Но если вы запустите тесты, основанные на скорости/производительности, вы увидите мало различий (если вы имеете дело с массивами), кроме того, единственное, что вы сохраняете, - это пространство.

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

Ответ 2

Целочисленные типы хранятся во многих байтах, в зависимости от точного типа:

  • байт на 8 бит
  • short на 16 бит, подписанный
  • int на 32 бита, подписан
  • длиной 64 бит, подписанный

См. здесь .

Что касается производительности, это зависит от того, что вы делаете с ними. Например, если вы присваиваете буквальное значение байту или краткому, они будут масштабироваться до int, поскольку значения по умолчанию считаются ints по умолчанию.

byte b = 10;  // upscaled to int, because "10" is an int

Что вы не можете сделать:

byte b = 10;
b = b + 1;  // Error, right member converted to int, cannot be reassigned to byte without a cast.

Итак, если вы планируете использовать байты или шорты для выполнения некоторых циклов, вы ничего не выиграете.

for (byte b=0; b<10; b++) 
{ ... } 

С другой стороны, если вы используете массивы байтов или шорт для хранения некоторых данных, вы, очевидно, выиграете от их уменьшенного размера.

byte[] bytes = new byte[1000];
int[] ints = new int[1000];  // 4X the size

Итак, мой ответ: это зависит:)

Ответ 3

Это деталь реализации, но по-прежнему верно, что по соображениям производительности большинство JVM будут использовать полное слово (или больше) для каждой переменной, так как ЦП получают доступ к памяти в словарных единицах. Если JVM сохранил переменные в блоках и позициях подслова, это будет на самом деле медленнее.

Это означает, что 32-битная JVM будет использовать 4 байта для коротких (и даже булевых), в то время как 64-битная JVM будет использовать 8 байтов. Однако для элементов массива это не так.

Ответ 4

Я согласен с user2391480, расчеты с шортами кажутся дороже. Вот пример, где на моей машине (Java7 64 бит, Intel i7-3770, Windows 7) операции с шортами примерно в 50 раз медленнее, чем целые и длинные.

public class ShortTest {

public static void main(String[] args){
    calculate();
    calculate();
}

public static void calculate(){
    int N = 100000000;

    long time1=System.currentTimeMillis();
    short s=0;
    for(int i = 0; i<N;i++) {
        s+=1;
        s-=1;
    }
    long time2=System.currentTimeMillis();
    System.out.println("Time elapsed for shorts: "+(time2-time1));


    long time3=System.currentTimeMillis();
    int in=0;
    for(int i = 0; i<N;i++) {
        in+=1;
        in-=1;
    }
    long time4=System.currentTimeMillis();
    System.out.println("Time elapsed for ints: "+(time4-time3));


    long time5=System.currentTimeMillis();
    long l=0;
    for(int i = 0; i<N;i++) {
        l+=1;
        l-=1;
    }
    long time6=System.currentTimeMillis();
    System.out.println("Time elapsed for longs: "+(time6-time5));


    System.out.println(s+in+l);
}

}

Вывод:

Time elapsed for shorts: 113
Time elapsed for ints: 2
Time elapsed for longs: 2
0
Time elapsed for shorts: 119
Time elapsed for ints: 2
Time elapsed for longs: 2
0

Примечание: указание "1" должно быть коротким (во избежание кастинга каждый раз, как это предлагает пользователь Robotnik в качестве источника задержки), похоже, не помогает, например.

    short s=0;
    short one = (short)1;
    for(int i = 0; i<N;i++) {
      s+=one;
      s-=one;
    }

EDIT: изменено в соответствии с запросом пользователя Hot Licks в комментарии, чтобы вызывать метод calculate() более одного раза за пределами основного метода.

Ответ 5

Там в принципе нет разницы. Нужно "немного запутать" JITC, чтобы он не признавал, что операции приращения/декремента самоотменяются и что результаты не используются. Сделайте это, и три случая выйдут примерно одинаково. (На самом деле, short кажется немного меньшим.)

public class ShortTest {

    public static void main(String[] args){
        // Do the inner method 5 times to see how it changes as the JITC attempts to
        // do further optimizations.
        for (int i = 0; i < 5; i++) {
            calculate(i);
        }
    }

    public static void calculate(int passNum){

        System.out.println("Pass " + passNum);
        // Broke into two (nested) loop counters so the total number of iterations could
        // be large enough to be seen on the clock.  (Though this isn't as important when
        // the JITC over-optimizations are prevented.)
        int M = 100000;
        int N = 100000;
        java.util.Random r = new java.util.Random();
        short x = (short) r.nextInt(1);
        short y1 = (short) (x + 1);
        int y2 = x + 1;
        long y3 = x + 1;

        long time1=System.currentTimeMillis();
        short s=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                s+=y1;
                s-=1;
                if (s > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time2=System.currentTimeMillis();
        System.out.println("Time elapsed for shorts: "+(time2-time1) + " (" + time1 + "," + time2 + ")");


        long time3=System.currentTimeMillis();
        int in=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                in+=y2;
                in-=1;
                if (in > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time4=System.currentTimeMillis();
        System.out.println("Time elapsed for ints: "+(time4-time3) + " (" + time3 + "," + time4 + ")");


        long time5=System.currentTimeMillis();
        long l=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                l+=y3;
                l-=1;
                if (l > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time6=System.currentTimeMillis();
        System.out.println("Time elapsed for longs: "+(time6-time5) + " (" + time5 + "," + time6 + ")");


        System.out.println(s+in+l);
    }
}

Результаты:

C:\JavaTools>java ShortTest
Pass 0
Time elapsed for shorts: 59119 (1422405830404,1422405889523)
Time elapsed for ints: 45810 (1422405889524,1422405935334)
Time elapsed for longs: 47840 (1422405935335,1422405983175)
0
Pass 1
Time elapsed for shorts: 58258 (1422405983176,1422406041434)
Time elapsed for ints: 45607 (1422406041435,1422406087042)
Time elapsed for longs: 46635 (1422406087043,1422406133678)
0
Pass 2
Time elapsed for shorts: 31822 (1422406133679,1422406165501)
Time elapsed for ints: 39663 (1422406165502,1422406205165)
Time elapsed for longs: 37232 (1422406205165,1422406242397)
0
Pass 3
Time elapsed for shorts: 30392 (1422406242398,1422406272790)
Time elapsed for ints: 37949 (1422406272791,1422406310740)
Time elapsed for longs: 37634 (1422406310741,1422406348375)
0
Pass 4
Time elapsed for shorts: 31303 (1422406348376,1422406379679)
Time elapsed for ints: 36583 (1422406379680,1422406416263)
Time elapsed for longs: 38730 (1422406416264,1422406454994)
0

C:\JavaTools>java -version
java version "1.7.0_65"
Java(TM) SE Runtime Environment (build 1.7.0_65-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

Ответ 6

Расчеты с коротким типом чрезвычайно дороги.

Возьмите следующий бесполезный цикл, например:

short t=0;
//int t=0;
//long t=0;
for(many many times...)
{
  t+=1;
  t-=1;
}

Если он короткий, он будет буквально в 1000 раз дольше, чем если бы он был int или длинным.

Проверено на 64-битных версиях JVM версии 6/7 на Linux