13

I read that JVM stores internally short, integer and long as 4 bytes. I read it from an article from the year 2000, so I don't know how true it is now.

For the newer JVMs, is there any performance gain in using short over integer/long? And did that part of the implementation has changed since 2000?

Thanks

Aminah Nuraini
  • 18,120
  • 8
  • 90
  • 108
bob
  • 563
  • 2
  • 7
  • 12
  • 11
    Um, there's no possible way to store longs in 4 bytes. – Michael Myers Mar 04 '10 at 16:06
  • do you have a link to this article? are you sure you are remembering it correctly? – Peter Recore Mar 04 '10 at 17:17
  • 1
    `short` willl be (microscopically) slower than `int`. How `long` and `int` compare depends a lot on the actual implementation. Generally `long` will be slower, but it could be microscopic or could be borderline significant. – Hot Licks Jan 27 '15 at 22:24

6 Answers6

15

Integer types are stored in many bytes, depending on the exact type :

  • byte on 8 bits
  • short on 16 bits, signed
  • int on 32 bits, signed
  • long on 64 bits, signed

See the spec here.

As for performance, it depends on what you're doing with them. For example, if you're assigning a literal value to a byte or short, they will be upscaled to int because literal values are considered as ints by default.

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

That's why you can't do :

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

So, if you plan to use bytes or shorts to perform some looping, you won't gain anything.

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

On the other hand, if you're using arrays of bytes or shorts to store some data, you will obviously benefit from their reduced size.

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

So, my answer is : it depends :)

Olivier Croisier
  • 6,139
  • 25
  • 34
13
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 

Use what you need, I would think shorts are rarely used due to the small range and it is in big-endian format.

Any performance gain would be minimal, but like I said if your application requires a range more then that of a short go with int. The long type may be too extremly large for you; but again it all depends on your application.

You should only use short if you have a concern over space (memory) otherwise use int (in most cases). If you are creating arrays and such try it out by declaring arrays of type int and short. Short will use 1/2 of the space as opposed to the int. But if you run the tests based on speed / performance you will see little to no difference (if you are dealing with Arrays), in addition, the only thing you save is space.

Also being that a commentor mentioned long because a long is 64 bits. You will not be able to store the size of a long in 4 bytes (notice the range of long).

Crozin
  • 43,890
  • 13
  • 88
  • 135
JonH
  • 32,732
  • 12
  • 87
  • 145
8

It's an implementation detail, but it's still true that for performance reasons, most JVMs will use a full word (or more) for each variable, since CPUs access memory in word units. If the JVM stored the variables in sub-word units and locations, it would actually be slower.

This means that a 32bit JVM will use 4 bytes for short (and even boolean) while a 64bit JVM will use 8 bytes. However, the same is not true for array elements.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • I assume you are essentially saying that you will save space but there will be no gain for perforamnce reasons (especially with arrays). – JonH Mar 04 '10 at 16:17
  • 2
    With regular variables, short saves neither space nor peformance over int (on a 32 or 64bit JVM). With arrays, it's hard to say since the extra CPU commands needed to convert the shorts to words and back can easily be offset by better cache behaviour due to smaller data size. – Michael Borgwardt Mar 04 '10 at 16:20
  • I agree with that, short vs int as regular variables will not matter, again it comes down to what are the needs in the application (the range of the type). But for arrays, the short will be a better space saver then an int / long. – JonH Mar 04 '10 at 16:25
  • Even as member variables nearly all JVMs store shorts in 16-bits, not as a full word, and 64-bit JVMs certainly don't use 64-bits to store `short` or `int`. So it's not just arrays, but essentially all data in the heap that benefits from using `short`. – BeeOnRope Jan 28 '15 at 01:01
1

There's basically no difference. One has to "confuse" the JITC a bit so that it doesn't recognize that the increment/decrement operations are self-cancelling and that the results aren't used. Do that and the three cases come out about equal. (Actually, short seems to be a tiny bit faster.)

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);
    }
}

Results:

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)
Hot Licks
  • 47,103
  • 17
  • 93
  • 151
0

I agree with user2391480, calculations with shorts seem to be way more expensive. Here is an example, where on my machine (Java7 64bit, Intel i7-3770, Windows 7) operations with shorts are around ~50 times slower than integers and longs.

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);
}

}

Output:

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

Note: specifying "1" to be a short (in order to avoid casting every time, as suggested by user Robotnik as a source of delay) does not seem to help, e.g.

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

EDIT: modified as per request of user Hot Licks in the comment, in order to invoke the calculate() method more than once outside the main method.

Federico Giorgi
  • 10,495
  • 9
  • 42
  • 56
  • 1
    To be fair: Move the "guts" to a separate method. Invoke it from `main` once, throw away the result, then invoke it again, keeping only the result from the last run. This will give the JITC a shot at optimizing the code. (Code in `main` is hardly ever optimized.) – Hot Licks Jan 27 '15 at 22:28
  • Will try at once. Yeah the difference remains. – Federico Giorgi Jan 27 '15 at 23:02
  • You've been punk'd by the JITC. For int and long it's recognizing that the +/-1 operations cancel out and also that the result is never used, so it's basically cancelling the entire loop. It doesn't put as much effort into optimizing for short. Rewrite to fix those and there's essentially no difference between the 3 data types. – Hot Licks Jan 28 '15 at 00:44
  • Thank you for the downvote, but please let me understand: I am printing the result in the end, so it is used. Also, can you be more specific about "JITC not putting much effort in optimiziing for short"? How should I rewrite the operation to _not_ cancel the loop in all three data types? – Federico Giorgi Jan 28 '15 at 16:12
  • 2
    See my answer. I started with your code & modified it. Not sure which features are definitely necessary, but certainly the cancelling +1/-1 operations must be "obfuscated" somehow, since even the dumbest of optimizers can figure that out. (I missed the fact that you were referencing the results at the end. That's probably sufficient for that issue.) – Hot Licks Jan 28 '15 at 16:49
-2

Calculations with a short type are extremely expensive.

Take the following useless loop for example:

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

If it is a short, it will take literally 1000s of times longer than if it's an int or a long.

Checked on 64-bit JVMs versions 6/7 on Linux

Aminah Nuraini
  • 18,120
  • 8
  • 90
  • 108
  • 2
    I thought this sounded wrong so I just tried it. Short and integer both gave essentially the same timing results in a quick test. Do you have any figures to back this up? – Tim B Jan 03 '14 at 10:11
  • 1
    I just tried this on my 64-bit machine with a loop of 1 billion iterations, run three times per test. I replaced the calculations with t+=a and t-=b, a and b both calculated to become 1 but to never be removed by the compiler, (a = (int)Math.ceil(Math.random()), same for b). Also printed result of loop, to ensure that loop runs. With 64-bit JRE 6: short: 1450ms, int: 70ms, long: 765ms – Daniel Johansson May 04 '14 at 11:23
  • @DanielJohansson - wouldn't converting to/from an int slow down the application when t is not an int? – Robotnik May 19 '14 at 14:11
  • -1 - The claimed result is unsubstantiated, and fails the "sniff test". – Stephen C Jun 19 '14 at 10:57
  • 1
    @Robotnik - It might do on some architectures. However, this Answer claims a 1000+ fold performance difference, and that is (IMO) implausible. So does the result claimed by Daniel Johnson, IMO. This sort of claim needs to be accompanied by the full source code of the benchmark so that other people can examine the methodology and attempt to reproduce the results. It is VERY easy to get micro-benchmarking wrong in Java. – Stephen C Jun 19 '14 at 11:01
  • @StephenC My comment claims that on my 64-bit machine, int performs around 10 times faster than long, not 1000 times faster. I'll go back and find the source code for you to verify. – Daniel Johansson Jul 24 '14 at 09:27
  • @StephenC, "sniff test"... meaning? – Pacerier Aug 18 '14 at 00:43
  • 1
    Here's the code for my quick benchmark. The compiler shouldn't be able to optimize any of the cases more than the others. http://pastebin.com/fvV1GPFH – Daniel Johansson Aug 28 '14 at 11:08
  • @DanielJohansson - My test shows them all about equal. Your test doesn't appear to make use of the results, and a compiler might figure that it can throw out the operations, since they can't cause exceptions. – Hot Licks Jan 28 '15 at 01:06
  • @DanielJohansson - I take it back -- your test does make use of the calculation result. I don''t know why your results and mine would differ so much. – Hot Licks Jan 28 '15 at 17:41
  • @DanielJohansson - Actually, your testcase may be suffering from the fact that each method is only called once. Depending on the style of the JITC this can inhibit part or all of the optimizations. – Hot Licks Jan 28 '15 at 17:44