Archive for the 'Benchtesting' Category

09
Feb
12

HTML5 Game Dev. Removing elements from the screen. Finding the fastest method.

Using removeChild to clear off a few in-game elements I noticed a bit of lag when testing on some devices so thought I’d better have a look at what the fastest removal methods are.

The three methods I selected to test were removeChild, display=”none” and a simple hide the element offscreen. Again, testing has been carried out at JSPerf.com.

My first test was on Chrome 16 and the results were pretty conclusive. display=”none” was very slow, and hide the element was by far the fastest – over 4 times faster than display=”none”.

So, conclusive proof – I should just hide my elements off the screen.

Err, no. I next tested Firefox 9.0.1. Ah, here removeChild was 2.5 times faster than both display=”none” and hiding the elements.

IE7.0 then. display=”none” and the hiding elements method were nearly 3 times faster than removeChild.

What about devices?
With Android 2.2 (Galaxy Tab 1) display=”none” was the fastest method, but only marginally so over the other two.

Safari on iPad #1 (4.2.1) flips the results on their head again with removeChild() being nearly 3 times quicker than the other two.

So how do we interpret this data? A chief decision to make would be what the target devices are. Then choose the quickest method. If we wanted a more generic approach then a series of conditionals would allow for all three methods to be present, using the most relevant one for the current browser.

For the prototypes I am working on, number one target is the iPad. A lot of my focus has been on trying to avoid using the Canvas element (entirely due to horrible performance on Android with it).

Element removal.

The (very simple) code used is here (for simplicity’s sake I use the inverse method as well to bring the element back onto the stage for subsequent removal):


var testDIV = document.createElement(‘div’);
testDIV.innerHTML = “Hello World”;

function displayIsNone()
{
testDIV.style.display=”block”;
testDIV.style.display=”none”;
}

function removeChild()
{
document.body.appendChild(testDIV);
document.body.removeChild(testDIV);
}

function moveVideo()
{
testDIV.style.left=”10px”;
testDIV.style.left=”-9999px”;
}

Try the tests yourself here: http://jsperf.com/removing-an-element-from-the-screen/3.

Advertisement
27
Oct
10

Keyboard Woes

I came across a problem today. Surely I should should have spotted this sooner – but maybe I just never used these key combinations.

It seems that there are issues with using ARROW KEYS and SPACE. Specifically on my keyboard the combination LEFT, DOWN and SPACE doesn’t work. I’ve spotted that other key combinations fail on different keyboards. Another laptop I have fails with LEFT, UP and SPACE as does my desktop at work.

Here is a quick app that will tell you what keys are being accepted. Try different combinations of arrow keys and space to see if you have any fails.

Seemingly this is nothing to do with Flash and everything to do with keyboard design. The problem varies from model to model, but is VERY common.

Test your keyboard.

Keyboards use a matrix to wire up the keys and register presses. The matrix is made up of columns and rows. When a key is pressed the column and row contact each other completing a circuit. The controller for the keyboard detects this and registers the key press. ‘Ghosting’ and ‘Masking’ of key presses can occur with a matrix keyboard. Here is a technical explanation of the issue. This article is from a decade ago, seemingly the drive to fix these keyboard problems hasn’t been strong enough.

Let’s gauge how bad it is. Try the Keyboard Woes app out and then let me know if there are any issues with your set-up.

How to fix this? The ONLY solution is not to use the SPACEBAR in combination with the ARROW keys.

12
Mar
09

Fastest Way to Copy An Array: Concat() or Slice(0)

What is the fastest way to copy an array? Concat or Slice? There is only one way to find out. FIGHT!

OK, so we can dismiss any kind of for-loop – far too slow, so that leaves us with:
1) array.concat() – i.e. concatenate an array onto nothing and deliver that as a new array.
2) array.slice(0) – i.e. return a new array consisting of all of the elements of the old array – from 0 till the end (up to a max of 16777215)

I’ve set up an array with a cool 1million entries (ok, it is not big, and it is not clever so it certainly isn’t cool). I need to copy this. The following code executes each method once on every iteration. It keeps a running total and records the average time each takes. I’ve limited the code to 100 iterations.

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.utils.*;
public class TestConcat extends Sprite
{
private var iteration_count:int=0
private var concat_total:int=0
private var slice_total:int=0
private var clone_total:int=0
private var tf:TextField = new TextField()
private var test_array:Array = [];

public function TestConcat():void
{
tf.x = tf.y = 100; tf.width = 600;
addChild(tf)

//Set up array to copy
for(var i:int = 0; i < 1000000; i++) test_array.push(i);
//Mouse click to rerun test
stage.addEventListener(MouseEvent.CLICK, go);
//First run
go()
}

private function go(e:Event = null):void
{
iteration_count=concat_total=slice_total=clone_total=0
addEventListener(Event.ENTER_FRAME, iterate)
}

//Loop through tests
private function iterate(e:Event=null):void
{
concat_total +=testConcat()
slice_total += testSlice()
clone_total += testByteArrayClone()
iteration_count++
tf.text = "Av. Concat time=" + (concat_total / iteration_count)
+ "ms Av. Slice time=" + (slice_total / iteration_count)
+ "ms Av. BA Clone time=" + (clone_total / iteration_count) + "ms";
if(iteration_count<99) removeEventListener(Event.ENTER_FRAME,iterate)
}

//test array slice
private function testSlice():int
{
var time_slice_start:Number = getTimer();
var slice_copy:Array = test_array.slice(0);
return getTimer()-time_slice_start
}

//test array concat
private function testConcat():int
{
var time_concat_start:Number = getTimer();
var concat_copy:Array = test_array.concat();
return getTimer()-time_concat_start
}

//test BA Clone method
private function testByteArrayClone():int
{
var time_concat_start:Number = getTimer();
var concat_copy:Array = clone(test_array);
return getTimer()-time_concat_start
}

//Clone method for Deep Objects(via Bruno)
private function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
}
}

On my laptop I’m clocking the concat at 14ms and the slice at over 29ms.

So a conclusive result. concat is twice the speed (with large arrays – the difference diminishes considerably with smaller arrays)

Give the code a few run throughs and see what you get. Let me know if your results are markedly different.

UPDATED:
I have updated the code and added a swf to try out here and the source code here

Fastest way to copy an array

Test the array copy for yourself


I’ve also added in a test for the Byte Array Clone method suggested by Bruno (see his comments below). This method seems a great one for copying ‘deep’ arrays – arrays of complex objects (arrays, objects or other types). In this context and test (copying shallow arrays) the instantiation, writing and reading adds too much overhead. I’ll need to test this in a useful context: with deep arrays.

Demo: Array Copy test
Source: Source.as




Categories

Reasons to be Creative 2012

FITC Amsterdam 2012

Flash on the Beach 2011

Flash on the Beach 2010

Swingpants at Flash on the Beach

Flash on the Beach 2009

Swingpants at FOTB2009

Twitter Updates