Constructor Slowdown?
I’ve heard from several sources that code in a constructor executes slower than code outside a constructor. So I decided to do a test. How much slower are constructors?
The methodology for the test is to run some expensive code in a constructor function and the same expensive code in a non-constructor function. This code is duplicated and not factored out to ensure that the the constructor function is doing the work directly rather than indirectly via a function call. Normally, you should factor this out, but here it would defeat the purpose of the test.
The work I’ve chosen to do is a big loop full of addition. The result of the computation is pointless, but stored in a public variable just to make sure that the compiler will not optimize out the loop, even though it probably wouldn’t anyhow.
Without further ado, here is the test app:
package { import flash.text.*; import flash.events.*; import flash.display.*; public class ConstructorTest extends Sprite { private var __logger:TextField = new TextField(); public function ConstructorTest() { __logger.autoSize = TextFieldAutoSize.LEFT; addChild(__logger); // Do the next frame so we don't test code in functions called FROM // a constructor, just in case. addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(ev:Event): void { // We just wanted to do the test once removeEventListener(Event.ENTER_FRAME, onEnterFrame); // Constructor test var tester:Tester = new Tester(log); // Non-constructor test tester.init(log); } private function log(msg:*): void { __logger.appendText(msg + "\n"); } } } import flash.utils.*; class Tester { public var total:int; public function Tester(log:Function) { var total:int = 0; var beforeTime:int = getTimer(); for (var i:int; i < 50000; ++i) { for (var j:int = 0; j < i; ++j) { total += j; } } log("constructor time: " + (getTimer()-beforeTime)); this.total = total; } public function init(log:Function): void { var total:int = 0; var beforeTime:int = getTimer(); for (var i:int; i < 50000; ++i) { for (var j:int = 0; j < i; ++j) { total += j; } } log("init() time: " + (getTimer()-beforeTime)); this.total = total; } }
The output I get on a 2.2Ghz Intel Core 2 Duo with 2GB of RAM on Mac OS X 10.6 (Snow Leopard) is:
constructor time: 3446 init() time: 3437
The results I get on a 3.0Ghz Intel Core 2 Duo with 2GB of RAM on Windows XP SP3 are:
constructor time: 2518 init() time: 2519
These results seem to match, except for overall scale. While the init() function can sometimes be a tiny bit faster than the constructor, it is indeed a tiny bit. Unless you are doing almost all of your time-critical work in constructors, I don’t think you have anything to worry about.
#1 by Alec McEachran on September 16th, 2009 ·
Thanks for the interesting article.
I’m not sure you can call that a performance improvement because the margin of error is so slim; you’d need a much bigger sample of constructors to have any confidence.
As a performance-irrelevant aside, I have two reasons to favour init over the constructor:
1. You can call super.init(…) from anywhere in a sub-class’s init method;
2. Once you construct a super-class with parameters the compiler commits you to writing out that constructor for any sub-class.
They’re good enough to prefer init over the constructor when no other overriding reason presents itself, in my opinion.
Regards, Alec.
#2 by jackson on September 16th, 2009 ·
Thanks for the comment. The point of the article was to show that there is no performance gain or loss either way. It simply doesn’t matter if the code is in the constructor or an init() function. I did try a few other types of constructors, including some making calls to more native-heavy code like Math.sqrt(), and saw no difference, so I posed just this.
I agree about when to use init() over constructors. Object re-use is a big deal when trying to eliminate GC slowdown and allocation time. It also allows free lists, as today’s article points out. Personally, I like to do just as much in the constructor as is necessary for the object to be constructed in a valid, known state, per the RAII approach. Then the user should call init() or other functions to further set up the object as required.
Thanks again for the comment.
#3 by Henke37 on September 15th, 2010 ·
I think the issue is simple: constructors are interpreted instead of JITed. But the content debugging players doesn’t use JITing apparently. So the test is flawed, assuming that it was run in a content debugging player.
#4 by jackson on September 15th, 2010 ·
I never run my performance tests in the content debugging player. The point of the article is to debunk the myth that– for whatever reason– code in a constructor executes slower than code outside of a constructor.
#5 by bwhiting on October 20th, 2010 ·
I wrote this a wee while ago but never posted it being lazy
http://blog.bwhiting.co.uk/?p=69
but now I have, maybe of interest to you to see what is going on under the hood.
#6 by manu on November 23rd, 2010 ·
I agree with you and am still am looking for a “constructor” slowdown example… WIth AS3 everything is jitted except for $cinit and $init functions which are not constructors that are called everytime you create a new object. So I have not seen any slowdowns like what this other person claims in the link below in real example :(
I am waiting for my copy of Visual Studio 8 to arrive pretty soon so that I can compile tamarin and dig into the object creation sequence in the VM….
http://blog.classsoftware.com/index.cfm/2010/11/4/Heavy-constructor-JIT-optimisation-in-ActionScript#c33099700-D56E-59C1-07EACFF9ED89BF3A
#7 by jackson on November 23rd, 2010 ·
There’s definitely a chance that it’s just hard to come up with an example where constructors are slower than other functions, but it’d be really good to know if there are cases where constructors actually are slower. Let me know what you find out once you’ve got a chance to dig in.
#8 by Justin Mclean on November 23rd, 2010 ·
Did you run the tests as a release compile in the release version (ie non debug) of the Flash Player? If you do I think you will find there is a difference – that’s been my experience anyway.
#9 by jackson on November 23rd, 2010 ·
I always test with a release build in a release version of the Flash Player browser plugin. Debug performance is almost always vastly slower and, frankly, irrelevant since end users are almost never running the debug version.