سؤال

I tried the following code:

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

The output to the console is:

loop one use time = 216,z = 18
loop two use time = 70,z = 18.

It seems that the second loop took less time, than the first one! I don't understand why this happens. Thanks for you help.


Update: I exchanged the two loops, now loop one takes less time!!

loop two use time = 219,z = 18
loop one use time = 69,z = 18
هل كانت مفيدة؟

المحلول

Writing a correct micro-benchmark is very time consuming and error prone. I would suggest doing micro-benchmarks only with an already available library like e.g. Caliper, that is specially designed for doing just that.

Your micro-benchmark has quite a lot of flaws, that will lead to unpredictable results:

  1. You are doing no warmups.
  2. You are benchmarking both approaches inside your main method, thereby giving the JIT compiler a harder time to optimize the code.
  3. The code "z = x + y;" comes actually down to "z = 9 + 9;" and does not ever change during the loop, so the loop may be completely optimized away to the simple expression "z = 18".

Anyway, here is the code for a corresponding benchmark done with Caliper:

@VmOptions("-server")
public class Test {

    @Benchmark
    public int timeSum1(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = x + y;
        }
        return dummy;
    }

    @Benchmark
    public int timeSum2(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = sum(x, y);
        }
        return dummy;
    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

You can have a look at the results for this benchmark here:

The results are as expected: both approaches take about the same time because they can be inlined by the JIT compiler. Running with -server both approaches still take about the same time but are optimized a little better.

نصائح أخرى

from the reading comments I got this idea, try below code

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
                // z = sum(x, y);
            }
        }
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

what result will show that both the loops have same time, cause JVM has warmed up its internal functions and ready to serve on his toes. :)

This also means you can't directly relate time used by certain code is directly related to it's algorithm, well you need to control the same environment and parameters governing the time consumption of code.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top