Saturday, July 31, 2010

Hardware Accelerated Browsers are a great step forward for Web potentials, but not all of them are able to accelerate properly the canvas element.

When it comes to performances, we should be aware about those practices able to slow down consistently not that powerful devices such Netbooks and smart pad or phones.

The Tesla Experiment

This demo has a mere entertainment purpose and it is specially suitable for iPad since it becomes more funny via multi touch screens.

It is possible to customize almost everything via the Tesla class, and for the example page we can simply use the query string.

All properties has been explained in the source code of the index page, when the Tesla instance is initialized.

Here another configuration example ( more "Dragon Ball" style :D )

It has been interesting to test how the blur can destroy performances, as interesting was to realize that with current canvas API, a nicer FX as this one could be is quite impossible if performances matters for nowadays mobile devices.

Tuesday, July 27, 2010

... he he, I know the title could not be worst, but after my last post about Arrayfication I have thought: "... hey, the Thing.ify(object) could be more than handy in many occasions such mixins and duck typing ...".

Since the function requires a Object.getOwnPropertyNames call for its prototype in order to be able to inject it's properties and methods in whatever object, the ify method is lazily assigned.This code makes "Function.ification" easy so that precedent post could be summarized via:

and be performed at light speed every other time while it won't cost at all until it's performed on whatever constructor the first time only.

Well, at least the technique may result interesting, unfortunately without ES5 it's not possible to reproduce the same behavior without knowing in advance all possible keys part of the native prototype (it's possible for user defined ones tho)

Why We Perform Such Operation

The Function.prototype.apply works only with object created through the [[Class]] Array or Arguments.In latter case we may like to avoid ES3 arguments and named arguments mess when dealing with indexes.Finally, in most of the case we would like to perform Array operations over ArrayLike objects to filer, map, splice, change, modify, etc etc ...

The Slice Cost

Let's perform over an ArrayLike object of length 2000, 2000 slice calls (change the length if you have such powerful machine):

The average time in my Atom N270 based Netbook is 1750 ms, and numbers are not that unreasonable.While a list of 2000 generic values may be not that common, the number of slice.call may be definitively more than 2000 during an application life cycle. All this wasted time to simply transform a generic list into an Array? And maybe just to loop and re-loop over it to filter or change values and indexes?

Alternative One: __proto__

If we modify the __proto__ property of whatever object and in almost all browsers (not IE, of course), we can somehow "promote" the current object to Array, except for the [[Class]] that will still be the generic Object, or Arguments.The undesired side effect is that the modified object won't find anymore in its prototype its original methods, so we can define this technique really greedy.But what about performances?

// the result using precedent arguments objectalert(testProto(arguments));

The average elapsed time in this case is 40 ms but we have to remember is that we are not converting the object into an Array instance, we are simply overwriting it's inherited properties and methods with those part of the Array.prototype object.This means that push, unshift, splice, forEach, or other operations, will be accessible directly through the object (e.g. arguments.forEach( ... ))If these methods are the reason we would like to slice the generic object, this solution is definitively preferred.

Alternative Two: Arrayfication

To avoid the undesired side effect obtained via __proto__ assignment, the removal of inherited methods, we may consider to use call or apply directly via Array.prototype.The imminent side effect of this technique is that potentially every function may like to use one of the Array prototype methods against the same object which is always passed by reference.A simple solution could be the one to attach directly a method to this object, so that every part of the application will be able to use, as example, a forEach call for this object, without accessing every time the Array.prototype.forEach method.

arguments.forEach = Array.prototype.forEach;// now use forEach wherever we need// with arguments object

Since every function may like to use one or more Array methods, how about creating a function able to attach all of them in one shot?

The average elapsed time for this operation is 3 ms.After a single call we can consider the generic object an Array duck, preserving its inheritance.The greedy aspect is about possible overwrites, but I have personally never called a method forEach if this is not exactly representing the Array.forEach method.

Arrayfied Operations

The last benchmark we can do is about common Array operations over our Arrayfied object.The first consideration to do is that slice, as every other Array operation, seems to be extremely optimized for real Array objects.In few words if we need to transform because we need many calls to forEach, filter, map, slice, etc, the transformation via slice is probably what we are looking for.But if we need a generic loop over a generic callback and just few times, Array.fy proposal is probably the most indicated one. Here some extra test:

The last test is against a classic slice.call and it costs basically the same.First and seconds demonstrate that if we slice to use native power we are actually spending more time than using native power directly.Bear in mind that if the variable is already an Array, slice will cost much less and the average against the last test will be 1350 ms.

IE And Conclusions

I keep saying that IE should simply have normalized Array.prototype, ignoring those person that wrongly rely in for in loops over arrays when it's not necessary, and making this Array.fy portable for IE world as well since the internal proto variable is a pointer to the original Array.prototype then automatically ready for natives standard enhancements.The nice part is that rather than see Array.prototype.something.call in every piece of code we can easily use one fast call to have them all ... so, you decide :-)

.. last minute Example ...

Just because sometimes we lack of fantasy, here a generic usage for Array.fy: