Java Exceptions Loops and deprecated (or is this a URLEncoding thing?)

I just wrote a whole ad about how I got to this point, but decided it would be easier for you to post the code and leave it there :)

As far as I can tell, the performance of test3 () should be the same as that of test1 () - the only difference is that the exception is caught (inside the calling method for test1 (), inside the called method for test3 ())

Why does test3 () regularly take time somewhere between test1 () and test2 ()?

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class Test {

    public static void main(String[] args) {
        warmup(); 
        test1(2500000); // Exception caught inside the loop
        test2(2500000); // Exception caught outside the loop
        test3(2500000); // Exception caught "inside" the loop, but in the URLEncoder.encode() method
    }

    private static void warmup() {
        // Let URLEncoder do whatever startup it needs before we hit it
        String encoding = System.getProperty("file.encoding");
        try {
            URLEncoder.encode("ignore", encoding);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void test1(int count) {
        String encoding = System.getProperty("file.encoding");
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            try {
                URLEncoder.encode("test 1 " + i, encoding);
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings trying to catch each in " + (end - start) + "ms");
    }

    private static void test2(int count) {
        String encoding = System.getProperty("file.encoding");
        long start = System.currentTimeMillis();
        try {
            for (int i = 0; i < count; i++) {
                URLEncoder.encode("test 2" + i, encoding);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings trying to catch all in " + (end - start) + "ms");
    }

    private static void test3(int count) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            URLEncoder.encode("test 3 " + i);
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings with a deprecated method in " + (end - start) + "ms");
    }

}

      

Running it gives me (JDK 1.6.0_13 on Windows XP) output:

Performed 2500000 encodings trying to catch each in 4906ms
Performed 2500000 encodings trying to catch all in 2454ms
Performed 2500000 encodings with a deprecated method in 2953ms

      

So the answers are pretty close (we're saying something so trivial that it doesn't matter), btu I'm curious!

Further...

People suggested that JVM optimizations get in the way - I agree. So, I split each test into its own class / main method and each separately. The results of this:

1 - Performed 2500000 encodings trying to catch each in 5016ms
1 - Performed 5000000 encodings trying to catch each in 7547ms
1 - Performed 5000000 encodings trying to catch each in 7515ms
1 - Performed 5000000 encodings trying to catch each in 7531ms

2 - Performed 2500000 encodings trying to catch all in 4719ms
2 - Performed 5000000 encodings trying to catch all in 7250ms
2 - Performed 5000000 encodings trying to catch all in 7203ms
2 - Performed 5000000 encodings trying to catch all in 7250ms

3 - Performed 2500000 encodings with a deprecated method in 5297ms
3 - Performed 5000000 encodings with a deprecated method in 8015ms
3 - Performed 5000000 encodings with a deprecated method in 8063ms
3 - Performed 5000000 encodings with a deprecated method in 8219ms

      

Interesting observations:

  • The gap between catching every call and catching everything outside of the loop is bridged in its own JVM (I suppose the optimization doesn't go all the way down the chain in the case of "all tests in one" due to other iterations that were done)
  • The gap between try / trick on my side and try / catch inside URLEncoder.encode () is now much smaller (half a second over 5,000,000 iterations), but still persistently exists ...
0


a source to share


3 answers


Running in the order you sent it:

Done 2,500,000 encodings trying to catch each one in 34208ms
Done 2,500,000 encodings trying to catch everything in 31708ms
Done 2,500,000 encodings with an obsolete method at 30738m

Reverse order:



Completed 2,500,000 encodings with outdated method at 32598ms
Executed 2,500,000 encodings trying to catch everything in 31239ms
Executed 2,500,000 encodings trying to catch everyone at 31208 m.

So I don't really think you see what you think you see (of course test1 is not 66% slower than test3, which is what your tests suggest)

+1


a source


Yes, you have your own explanation, I think:

3 is slightly slower than 1 due to the call to an additional method.



2 is faster than either because it does not "tune" and "reset" the bytecode associated with the exceptions in each cycle. You can hack byte code to see the difference with javap - see http://www.theserverside.com/tt/articles/article.tss?l=GuideJavaBytecode

Whether you use 2 or 1 depends on what behavior you want, since they are not equivalent. I would pick 1 out of 3, since then you are not using a legacy method that is more important than a tiny increase in speed, but as it happens, 1 is still faster.

0


a source


Please correct me, but test2 for-loop only takes 1 step, due to throwing exception and test1 caught the exception inside the loop and is executed 2500000 times.

When you catch an exception outside the loop, the loop will not start again. Print out "int i" to see how many steps are done in the loop.

The third is the slowest because the method delegates the call to the deprecated method.

0


a source







All Articles