When you instantiate one of your classes, how much memory does it use? Today’s article tries out a lot of combinations and counts the bytes used. The conclusion is easy to remember and will give you a solid understanding of how much memory your app is using.

Let’s start with an empty class and use flash.sampler.getSize() on it:

class ClassZero{} // 32

We start off with 32 bytes of overhead. Just to confirm, let’s make sure that static variables don’t affect the size. Since they’re not part of a class instance, this shouldn’t be the case.

class ClassStaticVar{static var a:int;} // 32

Good. Now let’s proceed to add an integer:

class ClassInt1{var a:int;} // 40

Wait, the int type only holds a 4 byte integer in AS3 so why did the memory usage jump up 8 bytes? Let’s explore by adding another integer:

class ClassInt2{var a:int;var b:int;} // 40

That int took no more space than the class without it. This means that the version with just one int had already reserved another 4 bytes of space which this int used. Next let’s see if that pattern continues by adding another int:

class ClassInt3{var a:int;var b:int;var c:int;} // 48

Yep, 8 more bytes were used by adding a single 4-byte int. If the pattern holds true, the next int will be “free”:

class ClassInt4{var a:int;var b:int;var c:int;var d:int;} // 48

And the next int will take 8 more bytes:

class ClassInt5{var a:int;var b:int;var c:int;var d:int;var e:int;} // 56

We can keep adding int fields with an easy-to-predict pattern:

class ClassInt6{var a:int;var b:int;var c:int;var d:int;var e:int;var f:int;} // 56
class ClassInt7{var a:int;var b:int;var c:int;var d:int;var e:int;var f:int;var g:int;} // 64

Next let’s try uint, which is another 4-byte integer type:

class ClassUint1{var a:uint;} // 40
class ClassUint2{var a:uint;var b:uint;} // 40
class ClassUint3{var a:uint;var b:uint;var c:uint;} // 48
class ClassUint4{var a:uint;var b:uint;var c:uint;var d:uint;} // 48
class ClassUint5{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;} // 56
class ClassUint6{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;var f:uint;} // 56
class ClassUint7{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;var f:uint;var g:uint;} // 56

As expected, all the sizes for uint are the same as with int. So how about Boolean? It just stores one bit of information, but as seen four years ago in The Size of Empty, it’s actually using 4 whole bytes! If still true, the class sizes should look identical to the int and uint versions.

class ClassBool1{var a:Boolean;} // 40
class ClassBool2{var a:Boolean;var b:Boolean;} // 40
class ClassBool3{var a:Boolean;var b:Boolean;var c:Boolean;} // 48
class ClassBool4{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;} // 48
class ClassBool5{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;} // 56
class ClassBool6{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;var f:Boolean;} // 56
class ClassBool7{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;var f:Boolean;var g:Boolean;} // 64

Sadly, this is still the case with Boolean. A single bit of information is being stored using 32 bits.

Now for something a bit different: Number. We know that it’s a 64-bit (8-byte) floating point value, so it should take up more space and yield larger memory sizes.

class ClassNumber1{var a:Number;} // 40
class ClassNumber2{var a:Number;var b:Number;} // 48
class ClassNumber3{var a:Number;var b:Number;var c:Number;} // 56
class ClassNumber4{var a:Number;var b:Number;var c:Number;var d:Number;} // 64
class ClassNumber5{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;} // 72
class ClassNumber6{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;var f:Number;} // 80
class ClassNumber7{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;var f:Number;var g:Number;} // 88

Indeed, Number is taking up its full 8 bytes with each addition. There is no extra 4 bytes of padding like with int, uint, and Boolean.

Next we’ll leave the land of basic types and explore Object.

class ClassObject1{var a:Object;} // 40
class ClassObject2{var a:Object;var b:Object;} // 48
class ClassObject3{var a:Object;var b:Object;var c:Object;} // 56
class ClassObject4{var a:Object;var b:Object;var c:Object;var d:Object;} // 64
class ClassObject5{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;} // 72
class ClassObject6{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;var f:Object;} // 80
class ClassObject7{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;var f:Object;var g:Object;} // 88

The Object sizes match those of Number, indicating that it too takes up 8 bytes. This makes sense given that I’m testing with a 64-bit (x64) CPU where pointers/references take up, well, 64 bits or 8 bytes.

Untyped variables are also pointers/references, so they should be the same

class ClassUntyped1{var a:*;} // 40
class ClassUntyped2{var a:*;var b:*;} // 48
class ClassUntyped3{var a:*;var b:*;var c:*;} // 56
class ClassUntyped4{var a:*;var b:*;var c:*;var d:*;} // 64
class ClassUntyped5{var a:*;var b:*;var c:*;var d:*;var e:*;} // 72
class ClassUntyped6{var a:*;var b:*;var c:*;var d:*;var e:*;var f:*;} // 80
class ClassUntyped7{var a:*;var b:*;var c:*;var d:*;var e:*;var f:*;var g:*;} // 88

And so should String variables, since they too are just pointers/references:

class ClassString1{var a:String;} // 40
class ClassString2{var a:String;var b:String;} // 48
class ClassString3{var a:String;var b:String;var c:String;} // 56
class ClassString4{var a:String;var b:String;var c:String;var d:String;} // 64
class ClassString5{var a:String;var b:String;var c:String;var d:String;var e:String;} // 72
class ClassString6{var a:String;var b:String;var c:String;var d:String;var e:String;var f:String;} // 80
class ClassString7{var a:String;var b:String;var c:String;var d:String;var e:String;var f:String;var g:String;} // 88

Really, this should hold true for any pointer/reference type that isn’t copied when you assign it to a variable or pass it to a function. Let’s just make sure by using our empty class:

class ClassClassZero1{var a:ClassZero;} // 40
class ClassClassZero2{var a:ClassZero;var b:ClassZero;} // 48
class ClassClassZero3{var a:ClassZero;var b:ClassZero;var c:ClassZero;} // 56
class ClassClassZero4{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;} // 64
class ClassClassZero5{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;} // 72
class ClassClassZero6{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;var f:ClassZero;} // 80
class ClassClassZero7{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;var f:ClassZero;var g:ClassZero;} // 88

Now let’s delve a little deeper into these two sizes—4 bytes and 8 bytes—to see what happens when you mix and match them. First, let’s use one 4 byte value (int) followed by one 8 byte value (Number).

class Class48{var a:int;var b:Number;} // 48

Remember that 32 bytes were used for the empty class. When we added an int, the size grew by its 4 bytes plus 4 bytes of padding. When we add this 8-byte Number we shouldn’t have enough room in the padding and should spill over into the next 4 bytes for a total of 44 bytes. However, the 4 byte values all grew in chunks of 8. This seems to be what’s happening here since we ended up with a 48 byte size.

We should have 4 more bytes of padding available, so let’s try to use it by adding another 4-byte int.

class Class484{var a:int;var b:Number;var c:int;} // 48

Since the size didn’t grow, this seems to validate the theory. There should be no padding left now. Adding another Number should expand the size by 8 bytes. Adding another int should expand the size by 4 bytes with another 4 bytes of padding.

class Class4848{var a:int;var b:Number;var c:int;var d:Number;} // 56
class Class4844{var a:int;var b:Number;var c:int;var d:int;} // 56

The next int we add will fit in the padding, but the next Number won’t fit and we’ll need to expand to the next 8 byte level.

class Class48444{var a:int;var b:Number;var c:int;var d:int;var e:int;} // 56
class Class48484{var a:int;var b:Number;var c:int;var d:Number;var e:int;} // 64

That about sums up all of the 4 and 8 byte values. One final piece of information to confirm is that functions don’t take up any space. Let’s start with just one function:

class ClassFunction{public function a():void{}} // 32

This is the empty size of 32 bytes, so the function didn’t add to the size. Are derived classes the same?

class ClassDerived extends ClassFunction{} // 32

Yes, derived classes don’t add to the size either. How about overriding functions?

class ClassDerivedOverride extends ClassFunction{override public function a():void{}} // 32

Overriding also doesn’t grow the size. One final check: static functions.

class ClassStaticFunction{public static function a():void{}} // 32

No problem there, either.

In conclusion, class sizes are always a multiple of 8. An int, uint, or Boolean will result in 4 extra bytes of padding if not followed by another int, uint, or Boolean. Static variables, extending classes, and functions of all types don’t add anything to the size.

Here’s the full test source code if you want to try this out yourself:

package
{
	import flash.display.*;
	import flash.utils.*;
	import flash.text.*;
	import flash.sampler.*;
	import flash.system.*;
 
	public class SizeOfClasses extends Sprite
	{
		private var logger:TextField = new TextField();
		private function row(...cols): void
		{
			logger.appendText(cols.join(",") + "\n");
		}
 
		public function SizeOfClasses()
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(logger);
 
			if (!Capabilities.isDebugger)
			{
				row("This app requires a debug player");
				return;
			}
 
			row("ClassZero", getSize(new ClassZero()));
			row("ClassStaticVar", getSize(new ClassStaticVar()));
 
			row("ClassInt1", getSize(new ClassInt1()));
			row("ClassInt2", getSize(new ClassInt2()));
			row("ClassInt3", getSize(new ClassInt3()));
			row("ClassInt4", getSize(new ClassInt4()));
			row("ClassInt5", getSize(new ClassInt5()));
			row("ClassInt6", getSize(new ClassInt6()));
			row("ClassInt7", getSize(new ClassInt7()));
 
			row("ClassUint1", getSize(new ClassUint1()));
			row("ClassUint2", getSize(new ClassUint2()));
			row("ClassUint3", getSize(new ClassUint3()));
			row("ClassUint4", getSize(new ClassUint4()));
			row("ClassUint5", getSize(new ClassUint5()));
			row("ClassUint6", getSize(new ClassUint6()));
			row("ClassUint7", getSize(new ClassUint7()));
 
			row("ClassBool1", getSize(new ClassBool1()));
			row("ClassBool2", getSize(new ClassBool2()));
			row("ClassBool3", getSize(new ClassBool3()));
			row("ClassBool4", getSize(new ClassBool4()));
			row("ClassBool5", getSize(new ClassBool5()));
			row("ClassBool6", getSize(new ClassBool6()));
			row("ClassBool7", getSize(new ClassBool7()));
 
			row("ClassNumber1", getSize(new ClassNumber1()));
			row("ClassNumber2", getSize(new ClassNumber2()));
			row("ClassNumber3", getSize(new ClassNumber3()));
			row("ClassNumber4", getSize(new ClassNumber4()));
			row("ClassNumber5", getSize(new ClassNumber5()));
			row("ClassNumber6", getSize(new ClassNumber6()));
			row("ClassNumber7", getSize(new ClassNumber7()));
 
			row("ClassObject1", getSize(new ClassObject1()));
			row("ClassObject2", getSize(new ClassObject2()));
			row("ClassObject3", getSize(new ClassObject3()));
			row("ClassObject4", getSize(new ClassObject4()));
			row("ClassObject5", getSize(new ClassObject5()));
			row("ClassObject6", getSize(new ClassObject6()));
			row("ClassObject7", getSize(new ClassObject7()));
 
			row("ClassUntyped1", getSize(new ClassUntyped1()));
			row("ClassUntyped2", getSize(new ClassUntyped2()));
			row("ClassUntyped3", getSize(new ClassUntyped3()));
			row("ClassUntyped4", getSize(new ClassUntyped4()));
			row("ClassUntyped5", getSize(new ClassUntyped5()));
			row("ClassUntyped6", getSize(new ClassUntyped6()));
			row("ClassUntyped7", getSize(new ClassUntyped7()));
 
			row("ClassString1", getSize(new ClassString1()));
			row("ClassString2", getSize(new ClassString2()));
			row("ClassString3", getSize(new ClassString3()));
			row("ClassString4", getSize(new ClassString4()));
			row("ClassString5", getSize(new ClassString5()));
			row("ClassString6", getSize(new ClassString6()));
			row("ClassString7", getSize(new ClassString7()));
 
			row("ClassClassZero1", getSize(new ClassClassZero1()));
			row("ClassClassZero2", getSize(new ClassClassZero2()));
			row("ClassClassZero3", getSize(new ClassClassZero3()));
			row("ClassClassZero4", getSize(new ClassClassZero4()));
			row("ClassClassZero5", getSize(new ClassClassZero5()));
			row("ClassClassZero6", getSize(new ClassClassZero6()));
			row("ClassClassZero7", getSize(new ClassClassZero7()));
 
			row("Class48", getSize(new Class48()));
			row("Class484", getSize(new Class484()));
			row("Class4844", getSize(new Class4844()));
			row("Class4848", getSize(new Class4848()));
			row("Class48444", getSize(new Class48444()));
			row("Class48484", getSize(new Class48484()));
 
			row("ClassFunction", getSize(new ClassFunction()));
			row("ClassDerived", getSize(new ClassDerived()));
			row("ClassDerivedOverride", getSize(new ClassDerivedOverride()));
			row("ClassStaticFunction", getSize(new ClassStaticFunction()));
		}
	}
}
class ClassZero{}
class ClassStaticVar{static var a:int;}
 
class ClassInt1{var a:int;}
class ClassInt2{var a:int;var b:int;}
class ClassInt3{var a:int;var b:int;var c:int;}
class ClassInt4{var a:int;var b:int;var c:int;var d:int;}
class ClassInt5{var a:int;var b:int;var c:int;var d:int;var e:int;}
class ClassInt6{var a:int;var b:int;var c:int;var d:int;var e:int;var f:int;}
class ClassInt7{var a:int;var b:int;var c:int;var d:int;var e:int;var f:int;var g:int;}
 
class ClassUint1{var a:uint;}
class ClassUint2{var a:uint;var b:uint;}
class ClassUint3{var a:uint;var b:uint;var c:uint;}
class ClassUint4{var a:uint;var b:uint;var c:uint;var d:uint;}
class ClassUint5{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;}
class ClassUint6{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;var f:uint;}
class ClassUint7{var a:uint;var b:uint;var c:uint;var d:uint;var e:uint;var f:uint;var g:uint;}
 
class ClassBool1{var a:Boolean;}
class ClassBool2{var a:Boolean;var b:Boolean;}
class ClassBool3{var a:Boolean;var b:Boolean;var c:Boolean;}
class ClassBool4{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;}
class ClassBool5{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;}
class ClassBool6{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;var f:Boolean;}
class ClassBool7{var a:Boolean;var b:Boolean;var c:Boolean;var d:Boolean;var e:Boolean;var f:Boolean;var g:Boolean;}
 
class ClassNumber1{var a:Number;}
class ClassNumber2{var a:Number;var b:Number;}
class ClassNumber3{var a:Number;var b:Number;var c:Number;}
class ClassNumber4{var a:Number;var b:Number;var c:Number;var d:Number;}
class ClassNumber5{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;}
class ClassNumber6{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;var f:Number;}
class ClassNumber7{var a:Number;var b:Number;var c:Number;var d:Number;var e:Number;var f:Number;var g:Number;}
 
class ClassObject1{var a:Object;}
class ClassObject2{var a:Object;var b:Object;}
class ClassObject3{var a:Object;var b:Object;var c:Object;}
class ClassObject4{var a:Object;var b:Object;var c:Object;var d:Object;}
class ClassObject5{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;}
class ClassObject6{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;var f:Object;}
class ClassObject7{var a:Object;var b:Object;var c:Object;var d:Object;var e:Object;var f:Object;var g:Object;}
 
class ClassUntyped1{var a:*;}
class ClassUntyped2{var a:*;var b:*;}
class ClassUntyped3{var a:*;var b:*;var c:*;}
class ClassUntyped4{var a:*;var b:*;var c:*;var d:*;}
class ClassUntyped5{var a:*;var b:*;var c:*;var d:*;var e:*;}
class ClassUntyped6{var a:*;var b:*;var c:*;var d:*;var e:*;var f:*;}
class ClassUntyped7{var a:*;var b:*;var c:*;var d:*;var e:*;var f:*;var g:*;}
 
class ClassString1{var a:String;}
class ClassString2{var a:String;var b:String;}
class ClassString3{var a:String;var b:String;var c:String;}
class ClassString4{var a:String;var b:String;var c:String;var d:String;}
class ClassString5{var a:String;var b:String;var c:String;var d:String;var e:String;}
class ClassString6{var a:String;var b:String;var c:String;var d:String;var e:String;var f:String;}
class ClassString7{var a:String;var b:String;var c:String;var d:String;var e:String;var f:String;var g:String;}
 
class ClassClassZero1{var a:ClassZero;}
class ClassClassZero2{var a:ClassZero;var b:ClassZero;}
class ClassClassZero3{var a:ClassZero;var b:ClassZero;var c:ClassZero;}
class ClassClassZero4{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;}
class ClassClassZero5{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;}
class ClassClassZero6{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;var f:ClassZero;}
class ClassClassZero7{var a:ClassZero;var b:ClassZero;var c:ClassZero;var d:ClassZero;var e:ClassZero;var f:ClassZero;var g:ClassZero;}
 
class Class48{var a:int;var b:Number;}
class Class484{var a:int;var b:Number;var c:int;}
class Class4848{var a:int;var b:Number;var c:int;var d:Number;}
class Class4844{var a:int;var b:Number;var c:int;var d:int;}
class Class48444{var a:int;var b:Number;var c:int;var d:int;var e:int;}
class Class48484{var a:int;var b:Number;var c:int;var d:Number;var e:int;}
 
class ClassFunction{public function a():void{}}
class ClassDerived extends ClassFunction{}
class ClassDerivedOverride extends ClassFunction{override public function a():void{}}
class ClassStaticFunction{public static function a():void{}}

Run the test app

Spot a bug? Have a question or suggestion? Post a comment!