3

I love MXML but am starting to notice some of its drawbacks. The main one I'm struggling with is its larger memory usage due to the need for binding. In the super simple code snippet below, which I've tested on Flex 4.0

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            [Bindable] private var xPos:Number = 20;
            [Bindable] private var yPos:Number = 20;
            [Bindable] private var testo:String = "hello";
            [Bindable] private var colorVar:uint = 0x212122;
            private const xPosConst:Number = 20;
            private const yPosConst:Number = 20;
            private const testoConst:String = "hello";
            private const colorVarConst:uint = 0x212122;
        ]]>
    </fx:Script>
<!--    <s:Label x="20" y="20" text="hello" color="0x212122"/>-->

    <s:Label x="{xPos}" y="{yPos}" text="{testo}" color="{colorVar}"/>

<!--    <s:Label x="{xPosConst}" y="{yPosConst}" text="{testoConst}" color="{colorVarConst}"/>-->
</s:Application>

the variables for an mxml labels get set using either (a) magic numbers, (b) [Bindable] variables and (c) consts. Interestingly (to me at least) scenario (c) takes up more memory than (a) but less than (b) - I would have assumed it'd be equal to one of the two and was hoping it would be the same as (a) but I guess not.

My main question: is there any way to set variables in MXML that doesn't eat up memory? I'm aware that I can do this explicitly in AS and keep MXML as a bare bone structure but was wondering if there was an alternative path.

Secondary question: why memory usage in c different from a and b? I've looked up at the intermediate code and it seems like the const case still sets up some binding logic but not as much and have been wondering why that is.

thank you!

J_A_X
  • 12,857
  • 1
  • 25
  • 31
fred august
  • 1,109
  • 12
  • 31
  • 1
    I'm kind of curious how you got the memory footprint of all this. Can you make up a chart of all the memory allocation? It would be great for scientific measurements :) – J_A_X Jun 02 '11 at 17:34
  • I used the memory profiler in Flash Builder 4.0. Will try to rerun and post values. – fred august Jun 02 '11 at 17:46

1 Answers1

2

Well, it's kind of a loaded question. No matter what you do, if you add code, you're going to use memory. Now, 'eat up memory' is relative to what you're doing and I would love to see more information on the memory allocation of each use case.

As for why one uses more memory than the other is a fairly simple (I think). It has everything to do with how Flash manages objects. By default, Flash uses reference base variables, however primitives do not count and are duplicated over. For example:

var a:Object = {};
var b:Object = a;
// then a === b as in the same reference in memory (check it in debugger)
// However
var a:String = 'weee';
var b:String = a;
// Then a !== b since the String is duplicated in memory

The reason for this is because they wanted to keep Actionscript simple enough and not have the developers have to worry about memory references (like using the '&' in front of a variables in C or Java for a variable). But as you've pointed out, the caveat of this is the duplication of primitives. In the grand scheme of things, it's very minimal compared to everything else being created, plus I'm fairly sure you'll be using models and such to store your data as you should ;)

As for the 'magic numbers' placed inline, I believe the reason why that takes room is because it's now storing the String version of that value and the 'real' version (since mxml does the casting for you). As for the constants, I'm not exactly sure why that's using more memory; I would of imagined it would be exactly the same as the variables since it's duplicating both, but I could be because it needs to 'lock' that variable so nobody can change it.

I would recommend you try to do the same test but with Objects and models instead to see what you find out. I would imagine that a generic Object would use more memory than a Class, but it would be neat to see what you find :)

EDIT: Forgot to point out that it wouldn't really matter if it's MXML or pure AS, they should work exactly the same way (except for the 'magic numbers' one). Binding does add extra memory of course, but it's a tradeoff; less memory or the utility of binding. I would also suggest you try to do the same in pure Actionscript and compare it to it's mxml counterpart (using BindingUtils for binding in AS) and show those results as well.

J_A_X
  • 12,857
  • 1
  • 25
  • 31
  • Thanks for the answer. I agree that binding is super convenient and thus should come at a cost. However, in many cases some of the variables that appear in an MXML component (say x and y in the example above) are not going to change and thus binding loses its usefulness. This should be obvious to the compiler if you use set something to a const for instance. Do you know of any way to set a variable in MXML without binding that doesn't have all the drawbacks of using magic numbers? – fred august Jun 02 '11 at 21:35
  • I understand where you're coming from since you're trying to use constants which are being 'duplicated'. The 'binding' of constant isn't really binding, it's just a one time setter since they don't change, however since they're primitives in this example, they will be copied over to the component, not referenced. What you can do is use a class to hold all you variables (a model) which can then be sent to the component and eliminating copying primitives since it's not referencing the model. – J_A_X Jun 02 '11 at 21:57
  • Ok, so I played around with using a model (created a bindable class, assigned the four values to public variables in the class, then used myClass.xPos in the MXML code, etc). Flash profiler claims equal expenditure of memory for the app in this case as in the variables case (775K) vs. 757K for the magic number case. That seems like a huge difference, although it's hard to tell what causes it from the profiler output itself. But then again, my understanding of what Flex does under the hood is still limited, so maybe I'm misinterpreting the profiler (or your advice). – fred august Jun 02 '11 at 23:05
  • Again, if you are to bind to a *primitive* (even if it's in a model), it's going to duplicate that primitive within the component you're binding it do. However, if you bind the *whole* model to that component, only the reference is sent over, hence no extra memory usage :) You do understand what I mean by primitives right? – J_A_X Jun 03 '11 at 02:44
  • I think I do :-). I guess I don't know how to bind the whole model to a standard component, i.e. in the example above I can see how I could create my own label class that has a [Bindable] public var and bind that to it but I'm not sure how you'd do that for an off the shelf component. In any case, thank you for all your help! – fred august Jun 03 '11 at 03:21
  • You can't do it to a standard component, only custom ones that can take a model. Normally when creating custom ui components, you want to use primitives so that it's reusable without having a dependency to another class (the model). So yeah, in the grand scheme of things, there's not much you can do about primitive duplication, it's just the way it is. In a large application though, it's still a fairly small amount more of memory usage and as long as you employ good practices, you shouldn't have too many UI components on the screen to use up memory. Please accept my answer if acceptable. – J_A_X Jun 03 '11 at 13:29