Tip : Don’t use shorts for loop indexes !

After a post I read on a french forum, i asked myself of the performances using shorts as loop indexes for loop with few iterations (less than 32768).

At first view, it can be tempting because we save 2 octets, so why use an int instead a short ?

But, when we think of that, we see that the int is more adapted. Indeed, it’s more performant.

Why ?

In Java language, all the operations on integers are made in int. Thus, if we use a short as loop index, at each iterations, a typecasting will be made, that’s really heavier than a simple affectation to int.

Here were my first results :

Time for int : 1441 ms
Time for short : 3015 ms

The short version is two times slower !

But like Jean have said, my first test was not correct at all because it doesn’t consider some issues that could occurs with micro-benchmarks.

So I write a new test using a Java Benchmarking framework from Brent Boyer. Here is a little test with that framework :

package com.wicht;

import bb.util.Benchmark;

import java.util.concurrent.Callable;

public class ShortIndexesLoop {
    public static void main(String[] args) {
        Callable callableInt = new Callable(){
            public Long call() throws Exception {
                long result = 0;

                for (int f = 0; f < 32760; f++){
                      result += f;
                  }

                return result;
            }
        };

        Callable callableShort = new Callable(){
            public Long call() throws Exception {
                long result = 0;

                for (short f = 0; f < 32760; f++){
                      result += f;
                  }

                return result;
            }
        };

        try {
            System.out.println("Result with int " + new Benchmark(callableInt));
            System.out.println("Result with short " + new Benchmark(callableShort));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

And here are the results :

Result with int first = 695.181 us, mean = 43.233 us (CI deltas: -49.358 ns, +74.073 ns), sd = 42.938 us (CI deltas: -11.634 us, +16.426 us)
Result with short first = 733.224 us, mean = 45.679 us (CI deltas: -62.975 ns, +63.932 ns), sd = 45.567 us (CI deltas: -5.877 us, +8.020 us)

So the results are lower. This time, the short version is 5.657% slower than the int version. Note that this can vary a lot depending on your configuration.

I talk here of for loops, but the case is the same when you use while loops with indexes.

Here are also the results with long, double and float versions :

Result with long first = 816.555 us, mean = 104.771 us (CI deltas: -236.563 ns, +344.219 ns), sd = 143.295 us (CI deltas: -39.149 us, +63.700 us)
Result with float first = 1.018 ms, mean = 58.055 us (CI deltas: -87.036 ns, +113.537 ns), sd = 70.757 us (CI deltas: -14.269 us, +19.962 us)
Result with double first = 912.115 us, mean = 57.918 us (CI deltas: -66.644 ns, +91.312 ns), sd = 55.185 us (CI deltas: -12.617 us, +25.160 us)

We can see that the long version is the slowest one and that float and double are equivalent but slower than int and short.

To conclude, always use int as loop indexes add a very little improvements of performances, but not a great thing and do not use long for loops indexes.

 

  • Jean

    Could you please read something before you post such nonsense. Your “benchmark” probably measures anything but not what you think it measures. Have a look at these slides by someone who knows (The author was the architect of the Hotspot JIT.) http://www.azulsystems.com/events/javaone_2002/microbenchmarks.pdf

    Have a loot at the subtitle: Lies, Damn Lies, and Micro Benchmarks.

    If you are interested in doing a valid measurement try the framework explained in these two articles: http://www.ibm.com/developerworks/java/library/j-benchmark1.html and https://www.ibm.com/developerworks/java/library/j-benchmark2/

    I came to the following numbers, using the above mentioned framework:

    - for int

    time of the first run: 1.268ms
    arithmetic mean of all measured and valid runs: 1.259ns
    95% confidence interval deltas: -1.194ps +1.710ps

    Note the different time units, there is factor of 1000 between them.

    - for short

    time of the first run: 3.934s
    arithmetic mean of all measured and valid runs: 1.283ns
    95% confidence interval deltas: -6.975ps +10.045ps

    Again, have a look at the units. Not there is a factory of roughly 2 000 000 between the first execution and the mean of the measured times.
    You can see very clearly why your benchmark says nothing. You measured only one execution. But, after making sure, that the JIT has finished its job, both version run at nearly the same speed: 1.268ns 1.283ns

    Hope, this helps do improve the quality of your and your readers statements about performance.

    • Baptiste Wicht

      Hi.

      Thanks for these corrections.

      I’m sorry for the errors i made on my post but i’m happy to know these issuesn now. We learn from our errors, isn’t it ?

      I edited the post to use the framework you mentioned. I have to say that this framework is awesome. I only use the Benchmark constructor on my code.

      Do you think it’s enough to have good results ?

      Do you have any more stuff about this framework ? I like to make an overview of this framework in my blog to apologize for my readers.

      Thanks a lot.

  • Jean

    Could you please read something before you post such nonsense. Your “benchmark” probably measures anything but not what you think it measures. Have a look at these slides by someone who knows (The author was the architect of the Hotspot JIT.) http://www.azulsystems.com/events/javaone_2002/microbenchmarks.pdf

    Have a loot at the subtitle: Lies, Damn Lies, and Micro Benchmarks.

    If you are interested in doing a valid measurement try the framework explained in these two articles: http://www.ibm.com/developerworks/java/library/j-benchmark1.html and https://www.ibm.com/developerworks/java/library/j-benchmark2/

    I came to the following numbers, using the above mentioned framework:

    - for int

    time of the first run: 1.268ms
    arithmetic mean of all measured and valid runs: 1.259ns
    95% confidence interval deltas: -1.194ps +1.710ps

    Note the different time units, there is factor of 1000 between them.

    - for short

    time of the first run: 3.934s
    arithmetic mean of all measured and valid runs: 1.283ns
    95% confidence interval deltas: -6.975ps +10.045ps

    Again, have a look at the units. Not there is a factory of roughly 2 000 000 between the first execution and the mean of the measured times.
    You can see very clearly why your benchmark says nothing. You measured only one execution. But, after making sure, that the JIT has finished its job, both version run at nearly the same speed: 1.268ns 1.283ns

    Hope, this helps do improve the quality of your and your readers statements about performance.

    • Baptiste Wicht

      Hi.

      Thanks for these corrections.

      I’m sorry for the errors i made on my post but i’m happy to know these issuesn now. We learn from our errors, isn’t it ?

      I edited the post to use the framework you mentioned. I have to say that this framework is awesome. I only use the Benchmark constructor on my code.

      Do you think it’s enough to have good results ?

      Do you have any more stuff about this framework ? I like to make an overview of this framework in my blog to apologize for my readers.

      Thanks a lot.

  • Pingback: Write corrects benchmarks | @Blog("Baptiste Wicht")