PDA

View Full Version : Flex compiler


wvxvw
04-12-2009, 11:03 PM
Have you ever though about Flex compiler can be a bit smarter?..

I had almost never seen such ideas in the wish-list, or any boards. But, digging deeper into framework stuff and, especially into generated code I keep catching myself at thinking that the code is way to far from being optimized... Well, you may know how smart C compilers can be, and, actually, they can compile very different sources into the same bytecode making optimization whenever possible, independent of your coding techniques and style it may give you pretty optimized example in the end...
Do you remember, there was Flasm utility once that let you optimize the AS bytecode after it was compiled. Well, the code generated if you use MXML and, especially if you use it with mx framework is highly nonproductive... let alone it imports so much needless stuff, it also makes it work very slow...
Imagine this simple example:
<mx:Button id="myButton" click="clickHandler()"/>
You'd guess it'd be translated into AS code like this:
myButton.addEventListener(Event.CLICK, clickHandler);
private function clickHandler(event:Event = null):void { ... }
Guess you ware ware wrong... it'd be:
myButton.addEventListener(Event.CLICK, _my_package_myClass_myButton_clickHandler);
public function _my_package_myClass_myButton_clickHandler(event:Ev ent):void
{
clickHandler();
}
private function clickHandler():void { ... }
So, we have here:
- one useless callback
- one sticking outside public method (what for?)
- if you don't know how compiler generates the names for the listeners you'd never be able to removeEventListener. But, even if you do, that's the same way a lot of string parsing involving describeType(), getDefinitionByName() etc...

Well, I can imagine this was an easiest way to generate the handler, but, sure this way is far from being perfect!
And you really don't want to look into how Flex generates binding... that's not just ugly, it's totally wrong... if you'll ever happen to have more then one instance of the same MXML component you'd run into this problem some time ever so often...
Now, if you ever had run the profiler, you could see how many objects and of what type are created during your application being executed... Now think about how many classes and, potentially, objects could be created by all the must-import Flex classes - let me reassure you that if all the objects that may be created by using the framework where created only once it would probably break the profiler, just because there are to many of them.
But, instead of optimizing the compiler, making it smarter, the framework introduces bunches of dirty workarounds!.. Like, for instance, generating UIDs for all framework objects (which is quite computation intensive process), every class that depends on other classes doublechecks, or even triplechecks if the input was correct... even though there are compile- / run-time errors!
Every even the most simple thing has:
- all the framework classes in it's dependencies
- is 10 times bigger / has way much more functions than an average developer would ever need.
- it's functionality is always covered by 2-3 similar classes...

Speaking of data management:
- Why, oh, why should ArrayCollection implement IList? There's no reason on Earth it should.
- If it wouldn't implement it, you could pool it from the framework and use it alone. But, since it does, at some point it gets to refer Application.application in a hardcoded way. So, not a chance you can pool it out of the framework! (BTW. Application.application is technically synonymous to _root in AS2, but much worse, because _root was just an alias and Application.application is the real non-player class that will force you into importing all the framework, including resource bundles, default styles etc.).

Now, because the framework is heavy, and you cannot use it in any other way, but in one piece, there's another workaround - shared RSLs, which, again, are buggy to the point you would finally decline this option. Besides, they are available only for few SDK builds, which are not always the builds you like to use... Even though, after you took your chances with signed RSLs and have your application sliced into numerous modules, you discover that modules are also buggy up to the point you don't want to even try to use them... But, even, imagine you hacked around the ModuleLoader (basically have it rewritten and recompiled instead of the one you have in the SDK), the file isn't going to get less than 50K! You can leak your elbows, but you cannot remove useless stuff from your framework SWF...

Sorry, I may be delirious after a few days of banging my head against the wall trying to get data that is compiled into the SWF with -services argument... And this is again, because it is done in the SDK in the pretty ugly way:
the compiler just adds this line:
ServerConfig.xml =
<services>
....
</services>
Into the Application-generated.as file... but that's just stupid there's no way to get it if your project isn't using framework... :mad:

Flash Gordon
04-28-2009, 08:56 AM
it also makes it work very slow...
Imagine this simple example:
<mx:Button id="myButton" click="clickHandler()"/>
You'd guess it'd be translated into AS code like this:
Nah, I'd guessed the second option besides the public namespace. It makes sense, click calls a method which takes no params called clickHandler or better name performClickTask since it isn't a handler. The _my_package_myClass_myButton_clickHandler is actually the handler which calls performClickTask. If you want the mxml method call on click to be the handler, pass the event as well which I suspect will give you very different results.

As for data management, I see no framework dependencies in IList, everything is an Object or Array or int.

wvxvw
04-28-2009, 06:38 PM
ArrayCollection extends ListCollectionView. ListCollectionView depends on SystemManager and ResourceManager... Sorry, it wasn't IList, but it doesn make it any better...
like, for instance, thie piece of code... why would one need an interface if he just uses it in this way:
private var resourceManager:IResourceManager =
ResourceManager.getInstance();
ListCollectionView, line 126...

As to the click handler, you'd be surprised, but somehow lots of people believe that AS compiler can unroll loops, and do other similar optimizations... And, being honest it is not difficult to spot a valid listener when it is present instead of creating an additional one...
Meaning, that the generated code for the valid listener would be like this:
_generatedListener(event:Event):void
{
clickListener(event);
}
Yet another bad thing about it, the generated code will include something like:
public var childDescriptor:Function = function():Object
{
return { events { click: "_generatedListener" } }
}
Both creating a useless string field (instead of just picking the reference to the listener) and generating anonymous function (while it could be just object)...

On a side note, I needed to make my component compatible with the framework, but not to use / rely on SystemManager / Application (i.e. it needed to compile alone as well as a part of the framork.)
This is how it starts:
public class Player extends Sprite implements IUIComponent, ISystemManager,
IDeferredInstantiationUIComponent, IStyleClient
The actual implementation of all those interfaces, including some useless methods like:
public function createReferenceOnParentDocument(parentDocument:IFl exDisplayObject):void
{
;
}
Etc. are now implemented exactly like this :) (I.e. not implemented at all) And still the component code is over 1,5K lines... and I cannot split it because it all has to be in one file :)
Besides, only the implementation of these interfaces made me use 43 framework classes, which added around 40K to the size of the project (in release mode)...
Sorry, I'm still anxious about it...