I have 16 Google Wave invites (updated)

 

James

Ok, so here’s the deal. I have 8 Google Wave invites. Whoever wants one must send a photo of themself giving the double thumbs up ala James Hall, pictured above. Three rules: 1) both thumbs need to be up and visible, 2) mouth must be open, and 3) the photo must be atleast 800×600. I’ll pick the eight best photos and deliver the invites. Simply send an email to jonnie[at]destroytoday[dot]com with the attached photo. Be sure to say hi.

[note] By sending me your photo, you are allowing me to post your photo on this article.

[update] Here are the first few photos that came in and out the invites went. Google, however, gave me another eight invites, so keep the photos coming!

Picture-2

ryanmckernan

Photo-on-2009-11-25-at-15.05-#2

app7818151259179950

P1010156.JPG

onj

thumbsup

200911262315

Photo-on-2009-11-27-at-20.32

tu7

image

How to handle untyped returns

 

Ideally, you never want to use untyped variables or returns. Sometimes, there are no other options. For example, in DestroyTwitter 2.0, I have a PreferenceManager class. This class has two methods for getting and setting preferences from a specific account or the application as a whole. Since some preferences are Strings and others are Numbers, the return for the getter is untyped.

With an untyped return on my hands, I want to know the best way to handle the variables once I get them. Do I typecast them, use the as operator, or simply do nothing? The answer is pretty surprising. With all literals tested, typecasting is faster than using the as operator, but doing nothing wins. In the non-literal Sprite test, the as operator is faster than typecastng, but once again, doing nothing wins.

Here’s the results and code. For comparison, I tested typed returns as well.

[SWF] Application.swf - 395,961 bytes after decompression
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
typed Number (1000000 iterations)                                       
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
typed Number                                                771     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
none Number (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
none Number                                                 864     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cast Number (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
cast Number                                                 895     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
as Number (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
as Number                                                   924     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
typed int (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
typed int                                                   788     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
none int (1000000 iterations)                                           
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
none int                                                    859     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cast int (1000000 iterations)                                           
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
cast int                                                    909     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
as int (1000000 iterations)                                             
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
as int                                                      920     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
typed uint (1000000 iterations)                                         
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
typed uint                                                  789     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
none uint (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
none uint                                                   862     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cast uint (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
cast uint                                                   903     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
as uint (1000000 iterations)                                            
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
as uint                                                     923     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
typed String (1000000 iterations)                                       
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
typed String                                                799     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
none String (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
none String                                                 815     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cast String (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
cast String                                                 855     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
as String (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
as String                                                   873     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
typed Sprite (1000000 iterations)                                       
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
typed Sprite                                                810     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
none Sprite (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
none Sprite                                                 813     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cast Sprite (1000000 iterations)                                        
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
cast Sprite                                                 946     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
as Sprite (1000000 iterations)                                          
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
as Sprite                                                   886     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package app.test { 
	import com.gskinner.utils.PerformanceTest;
 
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.utils.setTimeout;
 
	public class Test extends Sprite {
		public var p:PerformanceTest;
 
		public var n:Number;
		public var i:int;
		public var u:uint;
		public var string:String;
		public var sprite:Sprite;
 
		protected var _valueNumber:Number;
		protected var _valueInt:int;
		protected var _valueUint:uint;
		protected var _valueString:String;
		protected var _valueSprite:Sprite;
 
		public function Test() {
			p = PerformanceTest.getInstance();
 
			_valueNumber = 48151623.42;
			_valueInt = 4815162342;
			_valueUint = 4815162342;
			_valueString = "4815162342";
			_valueSprite = new Sprite();
 
			setTimeout(run, 1000);
		}
 
		public function run ():void {
			var it:uint = 1000000;
 
			p.testFunction(testTypedNumber, it, "typed Number");
			p.testFunction(testNoneNumber, it, "none Number");
			p.testFunction(testCastNumber, it, "cast Number");
			p.testFunction(testAsNumber, it, "as Number");
 
			p.testFunction(testTypedInt, it, "typed int");
			p.testFunction(testNoneInt, it, "none int");
			p.testFunction(testCastInt, it, "cast int");
			p.testFunction(testAsInt, it, "as int");
 
			p.testFunction(testTypedUint, it, "typed uint");
			p.testFunction(testNoneUint, it, "none uint");
			p.testFunction(testCastUint, it, "cast uint");
			p.testFunction(testAsUint, it, "as uint");
 
			p.testFunction(testTypedString, it, "typed String");
			p.testFunction(testNoneString, it, "none String");
			p.testFunction(testCastString, it, "cast String");
			p.testFunction(testAsString, it, "as String");
 
			p.testFunction(testTypedSprite, it, "typed Sprite");
			p.testFunction(testNoneSprite, it, "none Sprite");
			p.testFunction(testCastSprite, it, "cast Sprite");
			p.testFunction(testAsSprite, it, "as Sprite");
		}
 
		public function getValueTypedNumber():Number {
			return _valueNumber;
		}
		public function getValueNumber():* {
			return _valueNumber;
		}
		public function getValueTypedInt():int {
			return _valueInt;
		}
		public function getValueInt():* {
			return _valueInt;
		}
		public function getValueTypedUint():uint {
			return _valueUint;
		}
		public function getValueUint():* {
			return _valueUint;
		}
		public function getValueTypedString():String {
			return _valueString;
		}
		public function getValueString():* {
			return _valueString;
		}
		public function getValueTypedSprite():Sprite {
			return _valueSprite;
		}
		public function getValueSprite():* {
			return _valueSprite;
		}
 
		public function testTypedNumber ():void {
			n = getValueTypedNumber();
		}
		public function testNoneNumber ():void {
			n = getValueNumber();
		}
		public function testCastNumber ():void {
			n = Number(getValueNumber());
		}
		public function testAsNumber ():void {
			n = getValueNumber() as Number;
		}
 
		public function testTypedInt ():void {
			i = getValueTypedInt();
		}
		public function testNoneInt ():void {
			i = getValueInt();
		}
		public function testCastInt ():void {
			i = int(getValueInt());
		}
		public function testAsInt ():void {
			i = getValueInt() as int;
		}
 
		public function testTypedUint ():void {
			u = getValueTypedUint();
		}
		public function testNoneUint ():void {
			u = getValueUint();
		}
		public function testCastUint ():void {
			u = int(getValueUint());
		}
		public function testAsUint ():void {
			u = getValueUint() as int;
		}
 
		public function testTypedString ():void {
			string = getValueTypedString();
		}
		public function testNoneString ():void {
			string = getValueString();
		}
		public function testCastString ():void {
			string = String(getValueString());
		}
		public function testAsString ():void {
			string = getValueString() as String;
		}
 
		public function testTypedSprite ():void {
			sprite = getValueTypedSprite();
		}
		public function testNoneSprite ():void {
			sprite = getValueSprite();
		}
		public function testCastSprite ():void {
			sprite = Sprite(getValueSprite());
		}
		public function testAsSprite ():void {
			sprite = getValueSprite() as Sprite;
		}
	}
}

Combining Strings and variables—yet another performance test

 

I’ve been doing a ton of performance testing lately. It’s important to know which methods are the fastest, especially if you’ve been using some of the slowest methods all your life—I’m a victim. Getting in the mindset of “performance first” starts the snowball in improving your apps. This time I’m testing methods for combining Strings, with the hope that I can save a few milliseconds.

Taking a step back to look at memory, Strings are surprisingly heavy. It’s such a commonly used class, you’d think they would be the lightest of them all, but nope. The String class is THE heaviest class in DestroyTwitter, accounting for 40% of its memory usage. The Class class comes in second with 39% and TextField in third with a measly 4%. I always thought BitmapData took the crown, but it limps in fifth with 1.5% just behind the Function class.

Back to speed, we have three of the fastest String combination methods facing off. There’s String+String, String+=String, and String.concat(). I really wish AS3 handled String combination like PHP, allowing embedded variables without multiple Strings or slow methods like StringUtil.substitute(). Because of this, combining Strings and variables involve a ton of quotes and plus signs or a slower String.concat() method. Here are the results followed by the code:

[SWF] Application.swf - 392,771 bytes after decompression
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
+ (100000 iterations)                                                   
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
+                                                           336     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
+= (100000 iterations)                                                  
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
+=                                                          369     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
concat (100000 iterations)                                              
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
concat                                                      496     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package app.test { 
	import com.gskinner.utils.PerformanceTest;
 
	import flash.display.Sprite;
	import flash.utils.setTimeout;
 
	public class Test extends Sprite {
		public var p:PerformanceTest;
 
		public var string:String = "";
		public var firstname:String = "Jonnie";
		public var lastname:String = "Hallman";
		public var adjective:String = "fun";
		public var noun:String = "guy";
 
		public function Test()
		{
			p = PerformanceTest.getInstance();
 
			setTimeout(run, 1000);
		}
 
		public function run ():void {
			var it:uint = 100000;
 
			p.testFunction(stringAddition, it, "+");
			p.testFunction(stringAdditionEquals, it, "+=");
			p.testFunction(stringConcat, it, "concat");
		}
 
		public function stringAddition ():void {
			string = "" +
				firstname +
				lastname +
				"is" +
				"a" +
				adjective +
				noun +
				"to" +
				"be" +
				"around."
		}
		public function stringAdditionEquals ():void {
			string = "";
			string += firstname;
			string += lastname;
			string += "is";
			string += "a";
			string += adjective;
			string += noun;
			string += "to";
			string += "be";
			string += "around.";
		}
		public function stringConcat ():void {
			string = "";
			string.concat(
				firstname,
				lastname,
				"is",
				"a",
				adjective,
				noun,
				"to",
				"be",
				"around.");
		}
	}
}

For Each loops are fast—don’t believe the hype

 

Growing up a young boy in rural Macungie, I was always reminded how slow For In loops are and to avoid them when possible. The frequency of this scarred me so deep, I never trusted any two-worded For loop, until now. Looking over a co-workers code, I noticed he was using a For Each loop to access XML nodes. At first, I was going to bring up (because of the scarring) how For Each loops are slower, but then I decided to test it first—I’ve been burned before. I was startled to see that For Each loops CRUSH For loops when accessing XML. The For Each loop is almost five times faster than my beloved For loop!

This had me thinking—if a For Each loop is so much faster with XML, what about Objects and Arrays? It turns out they are slightly faster, but the difference is negligible. Even so, the amount of typing you save with a For Each loop is easily enough for me to ditch For loops when possible. Of course, there are situations in which a For Each loop simply isn’t an option, so don’t go thinking it’s a replacement.

Below are the results and the code used in the tests. I started using Grant Skinner’s PerformanceTest class—if you don’t have it, pick it up. Also, you might notice I adopted Adobe’s coding conventions. After years of using my own standards and getting weird looks from other developers, I decided to conform. I’m actually happy with the cleaner look.

[SWF] Application.swf - 393,881 bytes after decompression
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forInLoopObject (10000 iterations)                                      
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forInLoopObject                                              23     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forEachLoopObject (10000 iterations)                                    
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forEachLoopObject                                            11     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forLoopArray (10000 iterations)                                         
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forLoopArray                                                 13     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forInLoopArray (10000 iterations)                                       
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forInLoopArray                                               50     0.01
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forEachLoopArray (10000 iterations)                                     
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forEachLoopArray                                             11     0.00
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forLoopXML (10000 iterations)                                           
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forLoopXML                                                  336     0.03
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forInLoopXML (10000 iterations)                                         
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forInLoopXML                                                345     0.03
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
 
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
forEachLoopXML (10000 iterations)                                       
Player version: MAC 10,0,32,18 (debug)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
method...................................................ttl ms...avg ms
forEachLoopXML                                               70     0.01
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package app.test {
	import com.gskinner.utils.PerformanceTest;
 
	import flash.display.Sprite;
	import flash.utils.setTimeout;
 
	public class Test extends Sprite {
		public var tester:PerformanceTest;
		public var xml:XML;
		public var object:Object;
		public var array:Array;
 
		public function Test()
		{
			tester = PerformanceTest.getInstance();
 
			xml = 
				<tdd>
					<user>ben</user>
					<user>chris</user>
					<user>james</user>
					<user>jonnie</user>
					<user>omar</user>
				</tdd>;
 
			object = {ben:"ben",chris:"chris",james:"james",jonnie:"jonnie",omar:"omar"};
 
			array = ["ben", "chris", "james", "jonnie", "omar"];
 
			setTimeout(test, 1000);
		}
 
		public function test():void {
			var iterations:uint = 10000;
 
			tester.testFunction(forInLoopObject, iterations, "forInLoopObject");
			tester.testFunction(forEachLoopObject, iterations, "forEachLoopObject");
			tester.testFunction(forLoopArray, iterations, "forLoopArray");
			tester.testFunction(forInLoopArray, iterations, "forInLoopArray");
			tester.testFunction(forEachLoopArray, iterations, "forEachLoopArray");
			tester.testFunction(forLoopXML, iterations, "forLoopXML");
			tester.testFunction(forInLoopXML, iterations, "forInLoopXML");
			tester.testFunction(forEachLoopXML, iterations, "forEachLoopXML");
		}
 
		public function forInLoopObject ():void {
			var user:String;
			for (var key:String in object) {
				user = object[key];
			}
		}
		public function forEachLoopObject ():void {
			for each (var user:String in object) {
			}
		}
		public function forLoopArray ():void {
			var user:String;
			var m:uint = array.length;
 
			for (var i:uint = 0; i < m; ++i) {
				user = array[i];
			}
		}
		public function forInLoopArray ():void {
			var user:String;
			for (var key:String in array) {
				user = array[key];
			}
		}
		public function forEachLoopArray ():void {
			for each (var user:String in array) {
			}
		}
		public function forLoopXML ():void {
			var user:XML;
			var m:uint = xml.user.length();
 
			for (var i:uint = 0; i < m; ++i) {
				user = xml.user[i];
			}
		}
		public function forInLoopXML ():void {
			var user:XML;
			for (var key:String in xml.user) {
				user = xml.user[key];
			}
		}
		public function forEachLoopXML ():void {
			for each (var user:XML in xml.user) {
			}
		}
	}
}

DestroyTwitter 2.0 Preview: Account canvas

 

DestroyTwitter 2.0 Preview: Account canvas

In DestroyTwitter 2.0, the Account canvas gets a major overhaul. As much as it was nice to change your name, bio, and location in 1.x, I found most people only used it once, if at all. I also discovered that more users were interested in seeing their own profile and viewing it in the People canvas made it a pain, constantly needing to reload.

Because of these issues, the Account canvas in 2.0 extends the People canvas. It displays the active user’s info, including API status, in semi-realtime. This means any time you login, tweet, send a DM, receive a DM, follow someone or unfollow someone, this info is updated without using an additional API call. The API status is actually updated any time DestroyTwitter receives any data from the Twitter API without using an additional call. Also, when you click a user’s icon or username in a tweet, if it’s the active account, DestroyTwitter will know to go to the Account canvas rather than the People canvas.

This screenshot does lack a few buttons I plan to add, such as logout, but it’s mostly all done. I’m really excited about these fine-tunings and improvements over 1.x. Do realize I’m working every night to get this out the door. It’s coming along, but will endure a solid private testing period. I’ll make an announcement soon regarding how to sign up. In the meantime, hold tight.

DestroyTwitter 2.0 Preview: Improved item rendering

 

DestroyTwitter 2.0 Preview: Tweet recycling

The biggest feature in DestroyTwitter 2.0 is multiple accounts. Because of this, a serious amount of planning went into memory optimization. I didn’t want usage to double with each account added, so I adopted a few approaches that worked beyond my wildest expectations. One technique I used is improved item rendering. A few weeks back, I wrote a post about scrolling methods. The current one used in DestroyTwitter 1.7.2 uses preallocation and masking. It’s great for scrolling speed, but awful for instantiation speed and memory usage.

In 2.0, I adopted what I call fixed-height smooth recyclable scrolling. Instead of 200 list items for 200 tweets, I have only the visible items and a data list of 200 tweets. So far, it’s proving its worth. In recent testing, I’ve seen a 20mb memory reduction when using three accounts simultaneously in 2.0 compared to one account in 1.7.2. Results like this make me a happy developer.

DestroyTwitter 2.0 Preview: Preferences canvas

 

DestroyTwitter 2.0 Preview: Preferences canvas

Here’s a first glimpse at DestroyTwitter 2.0. Relating to yesterday’s post regarding preferences, I decided to segue into the Preferences canvas. In the current release, this canvas is a bit long-winded and claustrophobic. To combat these issues, I adopted an accordion layout where each set of preferences is expandable and collapsible. Not only does this clean up things a bit, but it also allows me to reuse components, which reduces memory. And finding new ways to reduce memory is like Christmas come early.

DestroyTwitter 2.0 Preview: Differentiating between preferences

 

DT2 Preferences

With multiple accounts in DestroyTwitter 2.0, there are a number of things to consider—one being preferences. In the current release, preferences are global across all accounts. In 2.0, however, some preferences are specific to each account. Above is my plan for divvying them up. Most rest under application, constant across all accounts, but there are a few that might differ from account to account.

Settings like refresh intervals are a given since some accounts require more frequent updates than others while some have canvases that don’t even need to update at all. The ability to disable Quick Friend Lookup when typing “@” is a new preference that is specific to each account. For instance, I want this enabled for my @destroytoday account since I frequently tweet to friends. On the reverse, I want it disabled for @destroytwitter since I only tweet to someone who asks a question or submits feedback.

Over the next few weeks, I’ll write a post previewing the upcoming release. I’m hoping to get it out this month, for private testing at the very least. Check back often for insight into what to expect.

DestroyTwitter on UserVoice

 

UserVoice

I recently signed up with UserVoice to handle feature requests and bug reports. I’m going to give it a shot and see how things go. After answering hundreds of emails each month, I realized many of them pertain to similar suggestions. UserVoice allows users to easily vote for features they want and see status on those already submitted. The service recently provided a year free for Twitter app developers, so why not? Check it out, go wild with requests, and I’ll do my best to stay active on it.

Interview on RIA Radio

 

RIA Radio

The RIA Radio podcast episode that I was a guest on the other week has been posted to the InsideRIA website. It’s a solid hour and a half, so if you plan to listen get a bag of popcorn—I’m a bit long-winded. We discuss my new job at Adobe, how I got started with AIR, the origins of “Destroy Today”, and so much more. Check it out and keep track of how many times I say “you know.”