Java короткое, целое, длинное представление - PullRequest
13 голосов
/ 04 марта 2010

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

Для более новых JVM, есть ли какой-либо выигрыш в производительности при использовании short по сравнению с integer / long? И изменилась ли эта часть реализации с 2000 года?

Спасибо

Ответы [ 6 ]

15 голосов
/ 04 марта 2010

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

  • байт на 8 бит
  • короткий 16 бит, подписанный
  • int на 32 бита, со знаком
  • длиной 64 бит, со знаком

См. спецификацию здесь .

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

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

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

12 голосов
/ 04 марта 2010
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 

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

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

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

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

8 голосов
/ 04 марта 2010

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

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

0 голосов
/ 28 января 2015

В принципе нет разницы. Нужно немного «запутать» 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)
0 голосов
/ 28 января 2015

Я согласен с user2391480, расчеты с шортами кажутся намного дороже . Вот пример, где на моей машине (Java7 64bit, 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;
    }

РЕДАКТИРОВАТЬ : изменено в соответствии с запросом пользователя Hot Licks в комментарии, чтобы вызывать метод Calculate () более одного раза за пределами метода main.

0 голосов
/ 05 ноября 2013

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

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

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

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

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

...