instanceof vs ClassCastException performance, which is faster?

Say you are writing a for loop for a java server application. This for loop is iterating over something that in practice (i.e. in production) is always of a specific subtype. But in theory it might not be, so being an average java developer, you add some defensive checking.

Now since the for loop will be run at least once for every request your platform receives, and you receive many millions of requests a week (perhaps you’re working at a place like the BBC?), you decide to spend 5 minutes making it “fast enough”.

So, should you keep that  if(!(r instanceof HttpServletRequest)) that you put in, replace it with try { ... } catch(ClassCastException e) { ... }, or remove the check completely?

Just to be clear: this is a really silly question and you should really just not bother spending your brain cycles thinking about it: java is fast and well-optimized over many years, it will be fast enough and many times faster than all your I/O handling and whatnot.

But, you now asked yourself this question and you really really want to know. You google for it and find no good answer. So you write a microbenchmark:

class InstanceOfBenchmark {
    static long globalCounter = 0;
    static long noCheck = 0;
    static long classCast = 0;
    static long instanceOf = 0;
    
    public static void main(final String[] args) {
        final int loops = 10000;
        final int encounterB = 1000;

        final A[] instances = new A[loops];
        for(int i = 0; i < loops; i++) {
            //if(i % encounterB == 0) {
            //    instances[i] = new B();
            //} else {
            instances[i] = new C();
            //}
        }
        
        for(int i = 0; i < 1000; i++) {
            testNoop(instances);
        }

        for (int i = 0; i < 1000; i++) {
            testClassCast(instances);
        }

        for (int i = 0; i < 1000; i++) {
            testInstanceOf(instances);
        }

        System.out.println("globalCounter = " + globalCounter);
        System.out.println(String.format(
                "Time for no-check test: %d", noCheck));
        System.out.println(String.format(
                "Time for ClassCastException test: %d", classCast));
        System.out.println(String.format(
                "Time for instanceof test: %d", instanceOf));
        System.out.println(String.format(
                "instanceof is slower than classCast by %f ms",
                1.0 * (instanceOf - classCast) / 1000 / 1000 / loops));
        System.out.println(String.format(
                "instanceof is slower than no check by %f ms",
                1.0 * (instanceOf - noCheck) / 1000 / 1000 / loops));
    }
    
    static void testNoop(final A[] instances) {
        long start, end;

        start = System.nanoTime();
        for (final A instance : instances) {
            final C c = (C)instance;
            c.otherDoNothing();
        }
        end = System.nanoTime();
        noCheck += end - start;
    }

    static void testClassCast(final A[] instances) {
        long start, end;

        start = System.nanoTime();
        for (final A instance : instances) {
            final C c;
            try {
                c = (C) instance;
                c.otherDoNothing();
            } catch (ClassCastException e) {
                // ignore
            }
        }
        end = System.nanoTime();
        classCast += end - start;
    }

    static void testInstanceOf(final A[] instances) {
        long start, end;

        start = System.nanoTime();
        for (final A instance : instances) {
            final C c;
            if (!(instance instanceof C)) {
                continue;
            }
            c = (C) instance;
            c.otherDoNothing();
        }
        end = System.nanoTime();
        instanceOf += end - start;
    }
    
    static class A {
        public void doNothing() {
            // does nothing
        }
    }

    static class B extends A {
    }

    static class C extends A {

        public void otherDoNothing() {
            // does _almost_ nothing, but not enough to be a no-op
            globalCounter++;
        }
    }
}

Here’s some sample results on my machine:

globalCounter = 30000000
Time for no-check test: 23981000
Time for ClassCastException test: 21082000
Time for instanceof test: 21551000
instanceof is slower than classCast by 0.000047 ms
instanceof is slower than no check by -0.000243 ms

globalCounter = 30000000
Time for no-check test: 27874000
Time for ClassCastException test: 21886000
Time for instanceof test: 35174000
instanceof is slower than classCast by 0.001329 ms
instanceof is slower than no check by 0.000730 ms

globalCounter = 30000000
Time for no-check test: 26983000
Time for ClassCastException test: 22007000
Time for instanceof test: 22568000
instanceof is slower than classCast by 0.000056 ms
instanceof is slower than no check by -0.000442 ms

So for performance it really doesn’t matter. It’s safe to assume that the JVM JITs and Hotspots its way to the most optimal code path in all cases.

If you want to fiddle some more, note that the above test has some code to allow you to vary the success/failure path; just uncomment/comment a few lines and tweak encounterB. The result is the same in all cases: performance is the same.

Now with that settled once and for all, I can keep my instanceof and get back to work!

Administrative stuff to take care of when moving to the UK

As I’ve found out recently, the UK is not exactly the easiest country in the world for foreigners to move to, and it also isn’t exactly the most digitized. Navigating the maze of different rules and institutions depends on doing things in the right order. Here is that order:

  1. Get a pre-paid mobile phone – just walk into a shop and buy one. Lots of institutions want a UK phone number; you can’t get a mobile subscription until you have proof of residency. Get a pre-paid USB 3G dongle. You should get your dongle from Vodafone because with them your pre-paid bandwidth does not expire after a month.
  2. Get a residential address where you can receive mail. Lots of institutions require one. It cannot be a business address and it cannot be a post box. So ask a friend or collegue! Alternatively if you are going to go for a flatshare arrangement you might be able to get that by paying cash up front and that becomes your address.
  3. Get a bank account with Barclays. They seem to be the only bank that can easily deal with foreigners moving to the country. You cannot apply online. Find the local branch using the barclays website, and ring them or walk in for an appointment. A lot of the people at the branch will think they cannot help you, but you should usually be able to find at least one account manager that knows that (s)he can help you. For your appointment you will need your UK phone number, your UK address and two forms of ID (for example passport and drivers’ license). If you have an ID that has an address on it (does not have to be your UK address) that helps. Make it clear that you are already employed in the UK, that you get paid well, that your salary will go into this new account, and you are also happy to put some significant amount of cash in your new account immediately. Be prepared for the appointment to take at least two hours. Make sure to get online banking. You get your bank account number and sort code number immediately and your bank card and online banking details in 5-7 working days.
  4. Register for online banking on the barclays website.
  5. Give your bank details (bank, account number, sort code, local branch) to your employer.
  6. Get a flat or flatshare. findaproperty.com is the best site to use for finding a flat, moveflat.co.uk is the best site for finding a flatshare. Offering to pay rent in advance tends to take care of most housing agent concerns (like you not having a referral from another UK housing agent). You also have to be able to set up a standing order, for which you need bank account number, sort code number, and address details of your local bank branch.
  7. If you got your own flat, get a BT landline. You cannot do this online, instead call 0800 800 150. I called Friday at 7:30 pm and was helped quickly. You can order broadband at the same time if you want. Don’t bother trying to get a phone line anywhere else – its significantly more painful than going with BT.
  8. Walk into your local Barclays branch to change your address details. Bring your bank card, account details and identification.
  9. Give your new address details to your employer.
  10. Register for council tax with your local council. How to do so depends on the council; check their website. I e-mailed my council who then sent me forms to fill out and send back.
  11. Register for utilities (electricity, water, gas). Your landlord or agent should be able to help figure this out, though utilities are handled through a commercial setup so you have to pick a provider. Again you should set up standing orders/direct debit for paying your bill.
  12. If you own a TV, register for a TV License. You can do this online. Set up direct debit.
  13. Once your BT phoneline is set up, you can opt to get Sky satellite TV. If you live in a house or small block of flats you can do this online, otherwise you have to check with your landlord about whether there is a minidish for your block, and if there is, call sky at 08442 410 137.
  14. Once you get a utility bill, you can finally get a mobile phone subscription plan. When you walk into the shop, bring a utility bill, proof of ID (i.e. passport), bank and address details, and your landline phone number. (faking a utility bill is obviously not very hard, and I’ve heard reports from people that have done this to get a subscription.)
  15. Give your new phone details to your employer. If you care about your bank being able to call you, pay yet another visit to the local branch.
  16. Once you’ve received salary in your new bank account at least twice, you can apply for a credit card. With Barclays you can do this online as long as you’re already registered for online banking.
  17. Get a National insurance number. I have yet to try this out. According to this website I have to call 0845 600 0643 (8.00 am to 6.00 pm Monday to Friday) and then go through an interview.
  18. Give your employer your national insurance number.

I was happy to have several collegues around that had been through the same process so I got many useful tips from them, but even then I found that all in all it takes quite a bit of calendar time for all these things to get sorted out. Because of that, I recommend to start with the first steps as soon as you know you’re moving to the UK.

Have you recently moved to the UK? Did you do things the same way or did perhaps find a more efficient route? Any hints or tips to share?