mardi 20 juin 2017

Comparing the performance of jump statements to != in loops

I was running an experiment to compare the performance of using break/continue vs without. There are two ways of looping through a sequence till a condition is met. I mean this:

Method (A)

function foo() {
    while(True) {
        if(! innerCondition ) {
            continue; 
        }

        // logic for innerCondition is true goes here 
        break;
    }
}

Method (B)

This can alternatively be written as:

function foo() {
    while(True) {
        if(innerCondition ) {
            // logic for innerCondition is true goes here
            break;
        }
    }
}

Obviously, this is a representative example. In a real case, the loops, as well as the inner and outer conditions could be anything.

I believed that Method (A) should be slower due to cache invalidation (assuming the business logic is a long wall of code). So, I wrote a Java program with dummy methods that do just this, and tried benchmarking my results.

public class Test {
    long foo(long x) {
        for(long i = 0; i < x; i ++) {
            if(i < x - 1) {
                continue;
            }

            return x;
        } 

        return -1;
    }

    long bar(long x) {
        for(long i = 0; i < x; i ++) {
            if(i == x - 1) {
                return x;
            }
        } 

        return -1;
    }

    public static void main(String args[]) {
        Test t = new Test();
        long startTime = System.nanoTime();
        t.foo(1000000000);
        long endTime = System.nanoTime();
        double duration = (((double)(endTime - startTime)) / 1000000.0D );
        System.out.println("Timing[foo]: " + duration + "ms");

        startTime = System.nanoTime();
        t.bar(1000000000);
        endTime = System.nanoTime();
        duration = (((double)(endTime - startTime)) / 1000000.0D );
        System.out.println("Timing[bar]: " + duration + "ms");
    }
}

I thought this was good enough to bring about some results that would help be solve this problem, but running this multiple tests gives me:

$ java Test
Timing[foo]: 644.357839ms
Timing[bar]: 661.337157ms

$ java Test
Timing[foo]: 647.931806ms
Timing[bar]: 641.273474ms

$ java Test
Timing[foo]: 645.645284ms
Timing[bar]: 657.748125ms

These results are inconclusive.

I'm convinced that my examples aren't good enough to invalidate the cache. I am also given to believe that nanoTime introduces some degree of inaccuracy.

Since I could not validate my hypothesis myself, I am posting this question on SO. My question is, is my hypothesis correct? In a normal situation, will Method (A) be slower? Or is it non-deterministic. Assume that the business logic inside both methods is identical, and there are no jump statements/function calls within.

Aucun commentaire:

Enregistrer un commentaire