My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label performances. Show all posts
Showing posts with label performances. Show all posts

Wednesday, December 21, 2011

Coercion Performances

There are cases where JS coercion may be wanted/needed/necessary, at least logically speaking.

A classic case is a list of primitives, e.g. strings, or numbers, and a check we would like to perform without creating a new function each time.

// recycled function
function alreadyThere(value) {
// wanted coercion, no cast needed
return value == this;
// shitty code, logically speaking
// one cast per iteration
return value === "" + this;
}

var listOfNames = ["Me", "You", "Others"];

// the pointless check
listOfNames.some(
// the recycled callback
alreadyThere,
// the *passed as object* this
"You"
); // will be true

Now, for above specific case anyone would use an indexOf but this is not the point.
The point is that in some case we may want to do more complicated stuff and compare the result with this

// know if word was already in the dictionary
function alreadyThere(value) {
return value.toLowerCase() == this;
}

// convert the check once per iteration
listOfNames.some(
alreadyThere,
"yoU".toLowerCase()
); // still true


It's About Optimizations

The whole point is to try to perform as less runtime computations as possible.
Following this logic, we may decide to lower-case all items in the list once, and never again, but unfortunately this will require duplicated amount of RAM used per each collection.
The String#toLowerCase() is fast enough for a not so frequent check so why bother the RAM?
The optimization is also to avoid this.toLowerCase() per each entry of the dictionary.
The concept here is again simple, avoid duplicated entries in a generic list of chars, but things may be similar with numbers.

Performances

I have created a specific test able to understand performances gap between coercion and cast per iteration.
Surprising Google Chrome seems to be able to optimize in core once per iteration the cast, resulting almost twice as fast as competitors.
Specially on mobile, the in core coercion seems to be faster, sometimes almost twice as fast as the cast per iteration is.

JIT Oriented Development ?

I believe we should code logically, rather than trust JIT optimization. What I mean is that performances test are always welcome but we all know that better logic and algorithms are always winning in therms of performances and maintainability. In this specific case, specially where mobiles suffer the most, I would never suggest to do the cast per iteration: first of all because only one engine seems to be able to optimize such cast, but we don't know if a more complex object/scenario would perform that well, secondly because if I see a cast per each loop iteration I start smelling laziness all over the place ... the boxing/unboxing has always been a well known problem performances speaking, so how can a developer approve a logic similar to (String)alwaysSameObject per each iteration?

As Summary

Tools such JSLint should just do their business in these cases ... coercion is wanted/needed/logical, and unless every browser will show such gap in common tasks against coercion, I will rarely promote a cast per iteration ... and you know what? I believe that gap in Chrome, is a missed optimization in Chrome itself.

Friday, November 25, 2011

On Complex Getters And Setters

A common use case for getters and setters is via scalar values rather than complex data.
Well, this is just a programmer mind limit since data we could set, or get, can be of course much more complex: here an example

function Person() {}
Person.prototype.toString = function () {
return this._name + " is " + this._age;
};
// the magic identity configuration object
Object.defineProperty(Person.prototype, "identity", {
set: function (identity) {
// do something meaningful
this._name = identity.name;
this._age = identity.age;
// store identity for the getter
this._identity = identity;
},
get: function () {
return this._identity;
}
});

With above pattern we can automagically update a Person instance name and age through a single identity assignment.

var me = new Person;
me.identity = {
name: "WebReflection",
age: 33
};

alert(me); // WebReflection is 33

While the example may not make much sense, the concept behind could be extended to any sort of property of any sort of class/instance/object.

What's Wrong

The problem is that the setter does something in order to keep the object updated in all its parts but the getter does nothing different than returning just the identity reference.
As summary, the problem is with the getter and the reason is simple: from user/coder perspective this may not make sense!

me.identity.name = "Andrea";

alert(me); // WebReflection is 33

In few words we are changing an object property, the one used as identity for the me variable, leaving the instance of Person untouched ... and semantically speaking this looks wrong!

A Better Approach

If the setter aim is to update a state there will be only a well known amount of properties to re-assign before this status can be updated.
In this example we would like to be sure that as soon as the identity has been set, the instance toString method will produce the expected result and without relying an external reference, the identity object itself.

// listOfNames and listOfAges are external Arrays
// with same length
for (var
identity = {},
population = [],
i = 0,
length = listOfNames.length;
i < length; ++i
) {
// reuse a single object to define identities
identity.name = listOfNames[i];
identity.age = listOfAges[i];
population[i] = new Person;
population[i].identity = identity;
// out of this loop we want that each
// instanceof Person prints out
// the right name and surname
}

// we cannot do it lazily in the toString method ...
// this will fail indeed
Person.prototype.toString = function () {
return this._identity.name + " is " + this.identity._age;
};

Got it? It's basically what happens when we use an object to define a property, more properties, or to create inheriting from another one: properties and values are parsed and assigned at that moment, not after!

var commonDefinition = {
enumerable: true,
writable: true,
configurable: false
};

var
name = (commonDefinition.value = "a"),
a = Object.defineProperty({}, "name", commonDefinition),
name = (commonDefinition.value = "b"),
b = Object.defineProperty({}, "name", commonDefinition)
;
alert([
a.name, // "a"
b.name // "b"
]);

As we can see if the property assignment would have been lazy the result of the latest alert would have been "b", "b" since the object used to define these properties has been recycled ... I hope you are still following ...

A Costy Solution

There is one approach we may consider in order to make this identity consistent ... the one that stores an identity with getters and setters.

// the magic identity configuration object
Object.defineProperty(Person.prototype, "identity", {
set: function (identity) {
var self = this;

// do something meaningful
self._name = identity.name;
self._age = identity.age;

// store identity as fresh new object with bound behavior
this._identity = Object.defineProperties({}, {
name: {
get: function () {
return self._name;
},
set: function (name) {
self._name = name;
}
},
age: {
get: function () {
return self._age;
},
set: function (age) {
self._age = age;
}
}
});
},
get: function () {
return this._identity;
}
});

What changed ? The fact that now we are able to pass through the instance and operate through the identity:


me.identity.name = "Andrea";

alert(me); // Andrea is 33

Cool hu ? ... well, it could be better ...

A Faster Solution

If for each Person and each identity we have to create a fresh new object plus at least 4 functions, 2 for getters and 2 for relative setters, our memory will fill up so quickly that we won't be able to define any other person identity soon and here comes the fun part: use the knowledge gained by this pattern internally!
Yes, what we could do to make things slightly better is to recycle the internal identity setter object definition in order to borrow maximum 4 functions rather than 4 extra per each Person instance ... sounds cool. uh?

function Person() {}
Person.prototype.toString = function () {
return this._name + " is " + this._age;
};

(function () {

var identityProperties = {
name: {
get: function () {
return this.reference._name;
},
set: function (name) {
this.reference._name = name;
},
configurable: true
},
age: {
get: function () {
return this.reference._age;
},
set: function (age) {
this.reference._age = age;
},
configurable: true
},
reference: {
value: null,
writable: true,
configurable: true
}
};

Object.defineProperty(Person.prototype, "identity", {
get: function () {
return this._identity;
},
set: function (identity) {
// something meaningful
this._name = identity.name;
this._age = identity.age;

// set the reference to the recycled object
identityProperties.reference.value = this;

// define the _identity property
if (!this._identity) {
Object.defineProperty(
this, "_identity", {value: {}}
);
}
Object.defineProperties(
this._identity,
identityProperties
);
}
});

}());

var
identity = {},
a = new Person,
b = new Person
;

identity.name = "a";
identity.age = 30;
a.identity = identity;

identity.name = "b";
identity.age = 31;
b.identity = identity;

alert([
a, // "a is 30"
b // "b is 31"
]);

So what we have there? A lazy _identity definition, good for those scenario where some getter or setter may never been invoked, plus a smart recycled property definition through a single object descriptor, and performances boosted up N times per each instance since no multiple different functions are assigned per identity properties getters and setters and no extra objects are created runtime ... arf, arf .. are you still with me ?

As Summary

Some JS developer keep asking for standard ways to do these kind of crazy stuff without realizing that few other programming languages are that flexible as JavaScript is ... it's maybe not that simple to find better, optimized, in therms of both memory consumption and raw performances, patterns to cover weird scenario but what we should appreciate is that with JS we almost have, always, a way to simulate something we did not even think about until the day before.
Have fun with JS ;)

Saturday, April 09, 2011

ES5 NOW! ... or better, @falsyvalues

Update more than a person asked me more details and here I am: The workshop will be Thursday 19th of May on Track 3 and from 9am to 5pm. Registrations open at 8am and to be sure everything I have written is correct, please double check the schedule.

This time is not about my uncle, this time is about my workshop in Warsaw, during Falsy Values Event, and this is its description:

Massive rumours behind buzz words such HTML5 and ES5, the latest updated specification about JavaScript programming language, have surely increased confusion about where is JavaScript today, and how this language should be in the future.

Unfortunately, we all know that many users are still trapped behind really outdated browsers and their relative JS engines.

This could lead us to be stuck with old coding patterns and style but here I am to show most recent performances oriented techniques that could make the transition to this new specification less painful and efficient

  • Size matters: code size oriented techniques and advantages of a proper build process

  • Why Array extras, Object creation, and other new ES5 entries are not scary

  • Mobile and performance oriented applications: DO and DONTs

  • JS Harmony purpose and the future of JavaScript


The "It's Scripting" Logic

Too many times we convince ourself that if it is about a scripting programming language, performances are not important. Unfortunately, or fortunately, I have already said we don't have choices when it comes to "web browser environment".
It's not that if we need speed, we change programming language, this is not an option for us ... we want be fast, as fast as possible!
Everybody knows already that, even in JavaScript, a proper algorithm can be faster than a bad one written in C or ASM.
This rule could be readapted more generically considering a better pattern faster than a worse one.


ES5 Oriented Patterns

Specially on mobile and tablet, recently on desktops as well, the latest version of JavaScript could bring many advantages in therms of performances but this is not it: ES5 brings different and new approaches that we should better consider now rather than wait that all browsers "will be there" and we'll see during this workshop different examples of graceful degradation.


Performances Speaking

Not all of us are that lucky to use JavaScript on the server side only.
Even in this case, we will most likely deal with http connections and we'll have to serve some content, possibly with JavaScript as well if it's not a RESTFull service only.
Performances on web have many faces: from download size to lazy loading advantage, up to browser specific builds and the best way to serve them. All these topics will be discussed during the workshop but hey ... if I have to be honest, there are many others there that could stimulate your interest ... I am just saying :P

See you in Warsaw ;)

Friday, December 24, 2010

The Status of Mobile Browsing

In this year I have done more tests than ever over all these tiny and shiny portable devices and I'd like to share with the Web community the result of my experiments at the end of this 2010. "why not before xmas, ffs?" ... because whatever you bought as present for you or your relatives, will hopefully be updated soon with latest systems and related browsers :)

The Dedicated WebKit ... Nightmare!

As ppk mentioned already in Front Trends conference, we have basically only 5 browsers in our desktop PCs/Macs/Linuxes machines. Much more fun comes when we think we are dealing with a single browser, a generic WebKit based one, and we discover that there's no browser similar to another one, every bloody device has its own implementation with few exceptions represented by Safari Mobile, almost the same in iPad, iPod, and latest iPhone.

WebKit and CSS(3)

Even if the CSS engine is basically the same for every single specific implementation, the number of supported, and so called, CSS3 features, are platform and device dependent. Something works as expected, something simply does not work, while something pretends to work but it does not until we force the rendering trying to activate Hardware Acceleration.
The classic trick to do this is to apply 3D transformation to the main container of our styled stuff:

#styled-stuff-container {
-webkit-transform: translate3d(0, 0, 0);
}

Above technique could solve many headaches when a portion, or the whole body, looks fucked up ... give it a try but please note that GPU buffer will rarely support big images and these could cause a massive performances impact.
An ideal document size for mobile browsing should not reach more than 2~3000 pixels height ... considering a reasonable width, after that we could have problems.

Tricks a part, the horrible side effect of unsupported CSS features is that features detections are not really a solution ... "eye result" detection would be the way to go but it requires a pixel per pixel check.
The "eye result" detection is something I have invented right now as CSS check automation. We should have a snapshot of the container, saved as png, a snapshot created runtime from the rendered container, impossible with current DOM API, and two canvas elements in order to compare both image data ... where to speed up the process in JS world, we could simply compare the returned base64 encoded result of both snapshots as fast char-by-char (threaded as ints) match (e.g. "a" == "a").
This is fantasy right now, and it implicates complex, bandwidth greedy, operations I would never suggest ... but I am just saying ... that we should never trust the result we have on our desktop WebKit or another device WebKit based, we should always test results in target if we would like to avoid surprises.
Finally, messed up CSS could cause indirectly so many computation behind the scene we cannot even imagine ... until we discover the the whole interaction is compromised.
As example, those pages strongly styled in an unreasonable way through tons of overwritten or inherited CSS, in a deeply nested DOM, simply are unusable!

WebKit and JavaScript(ES5)

Under the flag "we support HTML5", many things implemented in ES5 specs are already there indeed. In few words these tiny devices are already "10 years" ahead whatever destktop browser based on Internet Explorer ... which is good, which gives us the possibility to forget all crap we use to detect, filter, change, assume, until now.
This is the reason 99% of common web libraries out there are obsolete when it comes to the massive amount of features detections these libraries use to understand the exact version of IE, Firefox, or Opera ... all this stuff is crap, is bandwidth unfriendly, and unnecessary.
A good library for mobile browsing is a library dedicated for mobile browsing ... where even features detections could cost time (slower CPUs) and where most of the time these features detection, specially those for edge cases, can be dropped in favour of the good old User Agent string.
Yes, you read correctly, features detections we know could simply fail in all these variants of WebKit based browsers.
Some device could expose hosted features that are not available, some other could not expose anything but still support what we are looking for ... there are many examples that caused me nightmares during my experiments and no simple solution.
The User Agent sniff sometimes is the best, cheap, fast, solution we could possibly adopt and it will rarely fail when it comes to mobile.
Last, but not least, faster WebKit implements V8 engine, the google diamond, but others may implement the classic JavaScriptCore, with or without "Extreme" acceleration.

Native JSON Support

Almost all mobile browsers support native JSON. This is essential for fast and safe JSON strings and JS objects conversion into JSON strings.
I am counting seconds for the day Douglas Crockford JavaScript implementation of JSON will be redundant/superfluous, same as I am counting seconds until attachEvent will disappear from the Earth!

GeoLocation API

A mobile browser that does not come with GeoLocation API support is a death device. Mobile therm talks by itself, it's the user "on the way", full stop. Remove the possibility to share or know the location and good by "to go" experience.

session and local Storage Limits

Whatever freaking cool idea you come with these storages is not enough. What all these demo and examples around the net are saying is not exact. First of all the correct way to set an item is via official API, and not via direct access:

localStorage.setItem("setItem", "whatever");

// rather than
localStorage.setItem = "whatever";

// cause you don't want unexpected results later
localStorage.getItem("setItem"); // whatever

localStorage.setItem // ... what do you expect?
// a method or "whatever"

To know more about this problem, if interested, have a look.

Finally, and most important, setItem could fail once the storage reaches the memory limit which is not exposed (hopefully yet) through the API.
In few words we can have a nice Exception the moment we try to set an item, even the same, and the storage is "full".
To avoid problems, even if this is not a solution, use a bloody try catch block every time we need to set an item:

try {
localStorage.setItem("key", "bigValue");
} catch(e) {
// now we are fucked ... where do we put bigValue?
// we can still do stuff or clear some value
localStorage.clear(...)
}

The limit I am talking about is around 2Mb but it may vary.

Database API

Something nobody liked that much, something I love since the beginning. The SQLite database behind the scene is the best portable, tiny, and cross platform database engine we could possibly use on a browser. I am not a big fun of all these NoSQL fuzz, just use what the fuck you need when the fuck you need.
In this case the Web Database API provides a nice message automatically when the application tries to store more data than allowed, letting us being able to pass the limit specified at the beginning.
A good compromise is to set the initial storage value to 2 megabyte, maximum 5, and after that limit it will be the device able to allocate more space if necessary, adding other 2, up to 5, megabytes to curent database.
Rather than try catch mandatory blocks, we have callbacks for error handling but, right now, I have never been able to reproduce in a real scenario problems with the SQLite database size.

WebWorkers

These beasts could be the ideal solution in a multi-core device. Unfortunately, webworkes do not come for free with current mobile CPUs. It does not matter if these are operated behind the scene since the scene itself could interact slower than usual due tasks priorities.
Not a big deal considering webworker are not widely supported yet ... but still bear in mind the CPU is "that one", you better learn better algo or JS practices to speed up things rather than delegate piece of massive stuff to computate on the background.
A tiny temporary block is, in my opinion, much better than a persistently slow interaction due webworkers.

Touch Support

Touch events are the mandatory choice for mobile web development ... people should completely forget about mouseover and this kind of interaction bullshit, when it comes to device ... there is no fucking mouse on device, and these events should be used only as quirk fallback for those devices that do not expose properly touch events.
Touches are truly simple and everything we need for whatever interaction: touchstart, touchmove, touchend.
There will never be a touchmove without a touchstart, neither a touchend without a touchstart. Things are slightly complicated when we assume that a touchstart, followed by a touchend, won't fire a touchmove in the meanwhile.
When we start touching our smartphone screen the area we cover with our finger may vary due pressure on the screen. If a touchstart event has been fired already but the area is "enlarging" from the same finger, we won't have another touchstart, we will be notified with a touchmove.
There are concepts as "touch tolerance" that are already applied on all layers, included hardware, but this is not enough if we would like to have full control.
Finally, touch events are a classic example where features detections fails. The only way to be sure 100% that the device will work with touch events is to listen to both touchstart and mousedown and accordingly with the one fired first, usually the touch if fired, we can switch/communicate that the device is compatible. All our detections may fail accordingly with the device or the implemented WebKit version.

The Click Event

In some device, as is for example the delicious Palm Pre 2 I am testing these days (thanks again Palm!) there are no touches, even if the browser exposes them, so it is not possible to drag or scroll via JavaScript but it is possible to trust the classic click event.
The click is indeed the only universal fallback we can use to simulate interactions. Both new and old devices, included most recent Windows Mobile with that brEwser, will always react on click events. Pal Pre 2 does not expose right functionality for quirks mousemove neither ... and I am talking about web pages, if we create our own Application through Mojo framework ... well, things changes (again).

The Canvas Element

Almost every mobile browser supports canvas. Unfortunately, the Hardware Accelerated Canvas is still a myth. Canvas will be HW Accelerated hopefully soon, but what I have spotted right now, is that as example iOS 4.0.2 or lower has a tremendously faster canvas manipulation than iOS 4.2, or the latest iOS you can install in your iPad or iPhone. I am really sorry if you have already screwed up your mobile browsing experience updating this OS with latest ... since we all know you cannot go back now, let's hope Apple QA will test properly, next update, canvas performances ... epic fail from my point of view (and I can easily demonstrate it with eye test over exactly same operations ...)

Flash ... maybe

The world #1 plugin sucks for mobile ... not all of them, but still sucks. At least the render is faster via bytecode than canvas one could be, but since we have HTML5 video element as well and since the interaction in a small screen cannot contain all those details and cool effects that Flash has given us 'till now, I don't think Flash should be considered mandatory for a mobile experience ... still, if present, Flash could be our best friend as fallback for all those "not implemented yet" HTML5 features (or in some case, give us even more ... accordingly with security risks we may face).

Gestures ... if any ...

I still don't know how to pronounce this word properly ... but it does not matter.
The only browser able to expose properly gesture and to make developers life easy is Safari Mobile. Even if all recent smartphones support gestures on OS level, this topic seems to be the most complicated thing ever to expose through the browser.
The problem number one is the conflict that these events could cause with System Gestures. If I think about Palm Pre 2 "cards" interaction and the way I love to use this phone, I can instantly imagine how many side effects "my own gestures" could cause from UX perspective ... specially if I am able to avoid System gestures defaults. The problem number two is that we may find gestures variants, just to make our life, as developers, more interesting ... isn't it? Well, as soon as these variant will be part of the newer browser version we can find on these devices, I will dedicate a post about them ... so, patience is the key! (isn't it Weronika :P)
However, if touches events are exposed correctly, some crazy dude out there (and I am not excluding me) could implement gestures through touches events.
gesturestart is when touch list length is greater than 1, gesturechange is only if gesturestart has been fired and both scale and rotate are simple Math operations, while gestureend is fired when the touch list length goes down to 1 or 0 ... almost easy stuff, we don't really need them as long as touches work.

Opera Mobile

This is a must have browser if you want a common cross device web experience or a better browser than the one you have preinstalled in that phone.
Opera Mobile does not expose touches or gestures and the interaction is compromised but as render engine and web surfing, it is a pretty damn fast and cool browser that will be hopefully installable in the most recent Windows Mobile OS, since this has the worst browser you could ever imagine, compared with all others.

Mozilla Fennec

This is in my opinion too young and too featureless to compete with WebKit based implementations first and Opera Mobile after. Mozilla guys are working harder and improving a lot ... but still too much to do and hopefully a stable and cool release before next summer?

Nothing Else

Starting from the fact I could not test all of them, and ppk is here again the man you are looking for, all I can say is that the only superior mobile browser is WebKit based, no matters which branch, as long as things I have talked about are, more or less, supported.

Marry Christmas Everybody

Sunday, October 24, 2010

The Layer ... Of The Layer ... Of The Layer ...

When I read tweets like this one I cannot avoid a quick comment but the reason I am posting, is simply to explain that every time we write a web page/application, we are dealing with at least 4 different layers.
Moreover, this post is complementary for few slides I have introduced at front-trends, specially regarding the "avoid classic OOP emulation when not necessary" point.

Layer #1: JavaScript Libraries

We all know the DOM is a mess, and this is most likely the reason we chose a JS library rather than deal directly with possible problems we can have when we develop an x?HTML page.
Even if many developers don't care, I keep saying that every millisecond gained in this first layer, the page itself, is important.
Moreover, if we have a good understanding of the JavaScript programming language, we can easily realize that all these "Java Pretending Style Frameworks" emulating classic inheritance and OOP are not easier to maintain neither faster for what we need on mobile devices, included Netbooks.
The "easier to maintain" fuzz, associated with "Java style JavaScript", a sentence that does not make sense itself, is only a Java developer point of view.
Well written JavaScript without any "wannabe another language" pragmas, is truly much easier to both understand and write, modify, or fix, while the great magic behind this or that framework/library could become our first enemy when something goes wrong and we would like to understand and debug that magic 'cause we had a problem and we have strict deadline that may not match with a bug lifecycle.
Finally, as easily demonstrated via this test page, we can all spot how much more it costs to simply initialize a new instanceof constructor, compared with proper way to go natively via JavaScript, in that case made easier by this essential script, developed following TDD and tested here cross browser.
Anyway, common sense first and fast production quality, should always be kept in mind when we decide an approach, rather than another one. So, here frameworks play usually quite good role, the one to bring same functionality cross browser.
But what is a browser?

Layer #2: The Browser

As libraries are considered an abstract way to reach same goal in all browsers, browsers are simply abstract applications able to bring the web cross platform.
This is were the browser speed may vary, accordingly with the platform, and were every technique able to speed up render ( DOM+CSS engine such Gecko, Trident, others ) and JavaScript ( engine a part such V8, JavaScriptCore, SpiderMonkey ) is more than welcome. These guys are implementing any sort of trick to make the page and the code that fast, even if they have to deal with different operating systems. And guess what is an operating system?

Layer #3: The Operating System

We are even lucky if the browser deals directly with the operating system graphic API, since many other middle layers could be part of this stack ( flash or third parts plugins, as example ).
You cannot expect that Linux, Mac, and Windows, just mentioning fews Desktop related ( more choices on mobile world ) magically display and provide browser functionalities via the same API. We would need something like a jOSQuery library here to make it happens ... but even worse, every operating system may have another abstract layer able to use, as example, Hardware Acceleration.

Layer #4: The Hardware

Open GL ES 2.0 is simply another abstraction able to transform API calls into specific hardware driver calls which means that starting back from the DOM and the used WebGL or CSS3 with HW support, things have been modified, translated, re-created at least a couple of times.
In few words, if we asked too many things to do on first abstract layer, and being the first the slower one, nothing can be that fast.

As Summary

We, as web or scripting programming languages developers, rarely think that performances on the highest level ever can be that important but unfortunately, that highest level is the slowest one ever so, specially if we would like to reach best frame rate via canvas, WebGL, or CSS3 animations, it's highly recommended to be sure that the strategy/code we are using is the best one for our requirements.
As example, if we spend just a millisecond more to create each object we need for a single frame, we can easily switch from 30fps, a decent visual framerate, to 29 or less, were things will start to be visually slower for our eyes ...
Finally, kudos for Opera Mini and its growing market share, I am pretty sure it will become soon the IE for mobile platforms, making developers life easier, being a portable browser fallback for whatever website or application, hoping will not have all IE problems we all know.

Wednesday, June 30, 2010

JavaScript Random Hints

Update some point has been made more clear, thanks to Dmitry Soshnikov for suggestions.


Forget the global undefined


Too many developers relies into undefined variable in ES3, and all they should do is to set undefined = true on global scope and see if the application or all unit tests break or not. I am going to demonstrate how simple is, at least in ES3, to redefine by mistake the global undefined.

// inside whatever closure/scope
function setItem(key, value) {
this[key] = value;
}

// later in the scope, setItem may be reused
// through call or apply for whatever object
setItem.call(myObject, myKey, "whatever value");

// if for some reason the first argument used as context
// is undefined, the "this" will point to the global context

// if for some reason the second argument used as key
// is undefined, the accessor will cast it as undefined string

// the result of latter call with these two
// common or simple conditions
// is the quivalent of:

window.undefined = "whatever value";

// where window["undefined"] or window[undefined]
// are the equivalent of window.undefined

undefined; // "whatever value"

Here a list of side effects every time we deal with undefined:

  • it is not safe to compare variables against undefined since it is simply implicitly declared as unassigned variable, as var u; could be, but in the global scope

  • it is not possible to minify it since it is a well known variable

  • its access is slow, since requires scope lookup potentially up to the global one every time we write that bloody variable name in our code, wherever it is


Here is a list of best practices to avoid the usage of undefined:

  • define your own undefined variable, if necessary, via var undefined;, and only if you are sure that nothing can change it's value in the current scope (e.g. eval)

  • the first point will allow minifiers/compilers to shrink the undefined variable into, possibly, one char, so it is size safe

  • if null value can be considered undefined as well, where both undefined and null do not support accessors such unknown.stuff, compare the potential undefined variable against null, since by specs null == null && null == undefined && null != 0 && null != "" && null != NaN && null != false && null != whateverThatIsNotNullOrUndefined


About latter point, null is a constant so no lookup is performed since we cannot re-assign the null value and every time somebody tells you something like: "doooode, JSLint is complaining about that 'v == null'" simply tell him that JSLint is suggesting a bad practice and point this person to this post :D
About typeof v === "undefined" ? Bullshit! a typeof operation with an eqeqeq against a string that cannot be minified ... are you a programmer that knows the language or you think JSLint, as automation tool, is the bible? In the second case I have already posted JSLint: The Bad Part why this tool is not always ideal: have a look!
It must be told that in ES5 the global undefined won't be enumerable/writable/configurable anymore, and that showed example will fail since this reference, when null or undefined is passed through call/apply, will be null as well (errors).

Cache the bloody variable or namespace !


It does not matter how fast and cool are nowadays CPUs, it's about common sense.
If you spot something like:

my.lib.utils.Do.stuff(some);
my.lib.utils.Do.stuff(thing);

fix it ASAP!
This is a list of side effects caused by duplicated access for whatever it is:

  • a namespace requires a lookup usually up to the global scope, this costs time behind the scene

  • minifiers/compilers cannot optimize anything so far since properties cannot be shrinked so this technique is bigger application size prone

  • getters are always invoked, and 99.9% of the time this is not what we are looking for. JavaScript has a beautiful and easy interface exposed to developers but behind the scene there are 90% of the time getters which means slower performances for everybody.


About latter point, we can simply check, from one of the fastest browsers in the market, how much a simple node.childNodes[0] could cost.
If you are not familiar with C++, just imagine this piece of JavaScript every time we access an index of some Array:

Array.prototype.item = function (index) {
var
undefined,
pos = 0,
// useless if we return lastItem but for some reason there ...
n = this.slice(0, 1)
;
// optimized for multiple access with the same index
if (this._isItemCacheValid) {
if (index == this._lastItemOffset)
return this._lastItem;

var
diff = index - this._lastItemOffset,
dist = Math.abs(diff)
;
if (dist < index) {
n = this._lastItem;
pos = this._lastItemOffset;
}
}
if (this._isLengthCacheValid) {
if (index >= this._cachedLength)
return undefined;

var
diff = index - pos,
dist = Math.abs(diff)
;
if (dist > (this._cachedLength || (this._cachedLength = this.length)) - 1 - index) {
n = this[this._cachedLength - 1];
pos = this._cachedLength - 1;
}
}
if (pos <= index) {
while (n && pos < index) {
n = this[pos];
++pos;
}
} else {
while (n && pos > index) {
n = this[pos];
--pos;
}
}
if (n) {
this._lastItem = n;
this._lastItemOffset = pos;
this._isItemCacheValid = true;
return n;
}
return undefined;
};

Array.prototype._lastItemOffset = 0;

[1,2,3].item(0);

Now, consider above code against what we usually do which is simply arr[0] ... and consider that this is just the single item access for a ChildNodeList collection ... how many other operations we want to perform through DOM searches, namespaces, Array access, etc etc? Cache It Whenever It Is Possible!, and this should be the point number one in every "performances oriented" article or book.

The only thing to consider when we cache are object methods, if we "de-context" a method that use this reference inside, we can simply cache the object, it is going to be enough, but if we access a property twice, as often happens with domNode.style property, as example, cache it!

// my.name.space.Do.stuff is a method
// of my.name.space.Do where this is used

// WRONG
var stuff = my.name.space.Do.stuf;
stuff(); // global this in ES3, error in ES5

// BETTER
var Do = my.name.space.Do;
Do.stuff();


Use the in operator


For the same getter/access reason, this classic check can be harmful:

if (someObject.property) {
// do stuff with property
}

Specially if we are dealing with host objects, some access could cause errors (e.g. (domNode || unknown).constructor in IE or similar operations) while a classic:

if ("property" in object) {
// do stuff with object.property
}

can "save the world" since we do not access the property but we simply check if it is accessible ... a tiny difference extremely important and fast in any case.

Avoid redundant Function Expressions


We are kinda lucky here, since functions as first class objects, are truly fast to create in JavaScript. These do not require a class to be used, neither an object or special tricks, these are simply variables able to be invoked executing what has been defined inside their body through an activation context process, plus named arguments, the length of these arguments, the name of the function, if any, plus arguments variable if accessed in the body, and "almost nothing else" ... but we can already get the fact functions do not come for free, do we?

Here there are a couple of function expression common mistakes.

Closure inside a Loop



// WRONG
// the classic way to avoid
// unexpected behavior on lazy evaluation
// the equivalent of 20 functions
for (var i = 0; i < 10; ++i) {
(function (i) {
setTimeout(function () {
alert(i);
}, 15);
}(i)); // trap it!
}

// BETTER
// 11 functions rather than 20
// same behavior, better performances
for (var
getTimeout = function (i) {
return function () {
alert(i);
};
},
i = 0; i < 10; ++i
) {
setTimeout(getTimeout(i), 15);
}


Array.extras Misunderstood



// WRONG
// a new expression for each Array.extra operation
// a lookup to access another this reference
var self = this;
what.forEach(function (value, index, what) {
// do something
self[index] = value;
});
ever.forEach(function (value, index, what) {
// do something
self[index] = value;
});

// BETTER
// 1 function against N
// this reference through the native interface
// easier to debug/maintain/improve/change
function forThisEachCase(value, index, what) {
this[index] = value;
}
what.forEach(forThisEachCase, this);
ever.forEach(forThisEachCase, this);


Use Natives !!!


Newcomers are lazy, it does not matter if they are noob or they have 10 years of Java, PHP, Python, C#, or Ruby over their shoulders, they will always look for a framework able to do truly simple stuff for the simple reason that they don't know/get yet JavaScript which is different from every other common programming language. This is the best starting point to slow down every little operation.
Many frameworks offer classes, mixins, native wrapper which aim is often the one to invert arguments for whatever reason simplifying operations (e.g. the classic $.eash in jQuery which is making junior developers think that the native forEach will pass the index as first argument and this as current reference).
If three lines based on native prototypes/functionality are more than 1 magic method call, go for it!
Specially if standard, natives will never change while libraries are constantly improving and APIs changing as well for whatever valid reason.
If you need a for in loop, do the for in knowing what you are doing, ignoring JSLint if necessary 'cause you are dealing with objects that inherits from objects and you may be interested into inherited properties/methods as well.
If the problem is the list of property, we can always create safer ways to interact with what we would like to enumerate, as example:

var SafeLoop = (function (id) {
function SafeLoop() {
this[id] = [];
}
SafeLoop.prototype.keys = function() {
return this[id];
};
SafeLoop.prototype.enum = function (key) {
var enumerable = this.keys();
enumerable.push.apply(
enumerable,
typeof key !== "object" ? arguments : key
);
return this;
};
return SafeLoop;
}(Math.random()));

var o = new SafeLoop().enum("a", "b");
o.a = o.b = o.c = o.d = 123;
o.e = 456;

// enum accepts N arguments or an array
o.enum(["c", "d"]);

// fast and safe, without an hasOwnProperty call for each item
for (var key = o.keys(), i = key.length; i--;) {
alert([key[i], o[key[i]]]);
// d, c, b, and a with 123
}

// extend the prototype if necessary
SafeLoop.prototype.forEach = function (callback, context) {
for (var
enumerable = this.keys(),
i = 0, length = enumerable.length,
key;
i < length; ++i
) {
key = enumerable[i];
callback.call(context, this[key], key, this);
}
};

o.forEach(function (value, key, o) {
alert([value, key, o]);
// 123,a|b|c|d,[object Object]
});

Above code is just an example "AS IS" and there are many part to improve. The concept is that JavaScript allows us to define what we need in such simple way and most of the time we don't want to include and "move" a whole framework to do something simple as loops are, as example, do we? If we do, well, we are creating redundant function expressions, including extra bytes for just some extra functionality, and potentially making the application slower ... remember: we are in the mobile era, CPUs are not those you have in your MacBook Pro and frameworks should be used only when we have real benefits, e.g. selector engines or much more complicated methods. Do you agree?

Sunday, March 28, 2010

new Constructor VS Object.create

just a quick post about ES5 Object.create performances. While in More ES5 Friendly Patterns paragraph I have described how to use new ES5 features to create instances in a better way, I have never tested directly performances against classic ES3 pattern.

The Benchmark Logic

Pretty simple, create a new object with a "privileged property" plus an inherited one. The test prototype looks like this object:

var proto = {toString:function () {
return this.name;
}}

The assumption is that somehow the object should be able to return it's name, which is not shared via prototype.

ES3 Game

I hope I don't have to explain this piece of code:

function F(name) {
this.name = name;
}
F.prototype = proto;

To test above classical pattern, all we need is to confirm this behavior:

var o = new F("instance");
alert(String(o) === "instance");


ES5 Game

Using an updated browser, it should be possible to replicate ES3 behavior via this piece of code:

var o = Object.create(proto, {
name: {
value:"object"
}
});

Right, Object.create comes with much more power than a simple property assignment, but here we are testing a basic task just to analyze what's the outcome, right? Just to be sure about the result:

alert(String(o) === "object");


Optimized ES5 Game

What can we do to improve performances? Avoid global scope look up, the Object constructor, plus use a static/fixed property to cheat the test:

var fixed = {
name: {
value: "static"
}
};

var create = Object.create;

var o = create(proto, fixed);

// the assertion
alert(String(o) === "static");


The Benchmark

Let's put these patterns together inside a closure, execute them 100000 times, retrieving elapsed time.

setTimeout(function () {

var proto = {toString:function () {
return this.name;
}};

var fixed = {
name: {
value: "static"
}
};

function F(name) {
this.name = name;
}
F.prototype = proto;

var o;

for(var i = 100000, instance = new Date; i--;) {
o = new F("instance");
}
instance -= new Date;

for(var i = 100000, object = new Date; i--;) {
o = Object.create(proto, {
name: {
value:"object"
}
});
}
object -= new Date;

for(var create = Object.create,
i = 100000, static = new Date; i--;
) {
o = create(proto, fixed);
}
static -= new Date;

alert([instance, object, static].join("\n").replace(/-/g,"ms: "));

}, 1000);


The Result

Based on Atom N270 nad testing via Chrome 5 for devs, this is what I read in the alert:

ms: 7
ms: 2325
ms: 2218

The first result goes up to 54ms, reaching 5ms, the second one is pretty much stable while the latest one goes down 'till 1987 ms ...

Conclusion

new Constructor seems to be the best option for those cases where the initialize/init/construct method needs to somehow setup the created instance. Only if we need special Object.create features it is worth it to use it, but if we base a whole framework over Object.create, considering eventually emulations for old browsers, this framework will be inevitably slower than older code. This means that as example a classic Point class option, should still be exactly like this:

function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}

or eventually like the next one, if we don't need chained methods, neither new before each call:

function Point(x, y, z) {
return {x:x, y:y, z:z};
}

by my good old AStar algorithm time, the fastest option ever!

Saturday, February 13, 2010

arguments, callee, call, and apply performances

We have dozens of best practices to improve performances. We also have common practices to accomplish daily tasks. This post is about the most used JavaScript ArrayLike Object, aka arguments, and its performances impact over basic tasks.

Why arguments

While it's natural for JavaScripters to use such "magic" variable, as arguments is, in many other languages everybody knows it does not come for free and it is rarely used.

<?php
function myFunc() {
// function call for each execution
// rarely seen in good PHP scripts
$arguments = func_get_args();
}
?>

One clear advantage in PHP, Python, and many others, is the possibility to define a default value for each argument.

<?php

class UserManager extends MyDAL {
public function exists($user='unknown', $pass='') {
return $this->fetch('SELECT 1 FROM table WHERE user=? AND pass=?', $user, $pass);
}
}
?>

This approach may brings automatically developers to code as if arguments does not exist. It's not an important value, everything has a default ... so, why bother?

Why callee

Specially because of black sheep Internet Explorer and its inconsistent/bugged (it does not exist, imho) concept of named function expression, our laziness frequently bring us to use this "shortcut" to refer the current executed function.

// the classic case ..
setTimeout(function
/*
if named, IE will pollute the current scope
with chose name rather than let it "be" only
inside the function body, as is for every other browser
*/
() {
// do stuff
setTimeout(arguments.callee, 1000);
}, 1000);

Even if we are in a closure so that no risk will occur if we name the callback, we are still lazy and we don't even think about something like:

setTimeout(function $_fn1() {
// do stuff
setTimeout($_fn1, 1000);
}, 1000);

return function $_fn2() {
// if stuff $_fn2() again;
};

Of course, how many $_fn1, $_fn2, $_fn3 we can possibly have in the current scope?
Somebody could even think about silly solutions such:

Function.prototype.withCallee = (function ($) {
// WebReflection Silly Ideas - Mit Style
var toString = $.prototype.toString;
return function withCallee() {
return $("var callee=" + toString.call(this) + ";return callee")();
};
})(Function);

// runtime factorial
alert(function(n){
return n * (1 < n ? callee(--n) : 1);
}.withCallee()(5)); // 120

// other example
setTimeout(function () {
// bit slower creation ... but
// much faster execution for each successive call
if (animationStuff) {
setTimeout(callee, 15);
}
}.withCallee(), 15);


OK, agreed that 2 functions rather than one for each function that would like to use callee could require a bit more memory consumption ... but hey, we are talking about performances, right?

Why call and apply

Well, call and apply are one of the best JavaScript part ever. Everything can be injected into another scope, referenced via this, and while Python, as example, has a clear self as first argument, we, as JavaScripters, don't even think about such solution: we've got call and apply, who needs to optimize a this?
Well, somehow this always remind us that we are dealing with an instance, an object, rather than a primitive or whatever value sent as argument.
This means that even where it is possible to avoid it, we feel cooler using such mechanism:

function A(){};
A.prototype = (function () {
// our private closure to have private methods
function _doStuff() {
this.stuff = "done";
}
return {
constructor:A,
doStuff:function () {
_doStuff.call(this);

// it could have been a simple
_doStuff(this);
// if _doStuff was accepting a self argument
}
};
})();

Furthermore, apply is able to combine both worlds, via lazy arguments discovery, and context injection ... how cool it is ...

The Benchmark

Since we have all these approaches to solve our daily tasks, and since these cannot come for free, I have decided to create a truly simple bench, hopefully compatible with a wide range of browsers. There is nothing there, except lots of executions, defined by times parameter in the query string, and a simple table to compare runtime these results.

Interesting Results

The scenario is apparently totally inconsistent across all major browsers, and this is my personal summary, you can deduct your one as well:
  • in IE call and apply are up to 1.5X slower while as soon as arguments is discovered, we have up to 4X performances gap. There is no consistent difference if we discover callee, since it seems to be attached directly into arguments object.
  • in Chrome call is slower than apply only if there are no arguments sent, otherwise call is 4X faster than apply and, apparently, even faster than a direct call. arguments costs generally up to 2.5X while once discovered, callee seems to come for free giving sometimes similar direct call results.
  • in Firefox things are completely different again. Direct call, as call and apply, do not differ that much but as soon as we try to discover arguments.callee, for one of the first browser that got named function expression right, the execution speed is up to 9X slower.
  • Opera seems to be the most linear one. Direct call is faster than call, and call is faster than callee. To discover arguments we slow down up to 2X while callee does not mean much more.
  • In Safari we have again a linear increment, but callee costs more than Opera and others, surely not that much as is for Firefox


Summarized Results

A direct call is faster, cross browser speaking, and specially for those shared functions without arguments, we could avoid usage of call or apply, a self reference as argument is more than enough.
arguments object should be forbidden, if we talk about extreme performances optimizations. This is the only real constant in the whole bench, as soon as it is present, it
slows down every single function call and most of the time
consistently.

HINTS about arguments

To understand if an argument has not been sent, we can always use this check ignoring JSLint warnings about it:

function A(a, b, c) {
if (c == null) {
// c can be ONLY undefined OR null
}
}

If we compare whatever value with == null, rather than === null, we can be sure this value is null or undefined.
Since generally speaking undefined is not an interesting value and null is used instead, also because undefined is a variable and it costs to compare something against it and it could be redefined as well while null cannot, it does not make sense at all to do tedious checks like this:

function A(a, b, c) {
// JSLint way ...
if (c === undefined || c === null) {
// bye bye performances
// bye bye security, undefined can be reassigned
// hello redundant code, == null does exactly the same
// check in a more secure way since it does not matter
// if undefined has been redefined
}
}

Do we agree? That warning in JSLint is one of the most annoying one, at least this is my opinion.
Let's move forward.
If we would like to know arguments length we have different strategies:

function Ajax(method, uri, async, user, pass) {
if (user == null) {
// we know pass won't be there as well
// received probably 3 arguments
// if user is not null, we expect 5 arguments
// and we use all of them
}
if (async == null) {
// this is a sync call
// received 2 arguments
}
}

function count(a, b, c, d) {
// not null, we consider it as a valid value
var argsLength = (a != null) + (b != null) + (c != null) + (d != null);
alert(argsLength);
// rather than alert(arguments.length);
}

count();
count(1);
count(1, 2);
count(1, 2, 3);
count(1, 2, 3, 4);

About latest suggestion please consider that only Chrome is slower, but Chrome is already the fastest browser so far while in IE, as example, arguments.length rather than null checks costs up to 6X the time.
Every other browser will have better performances than arguments.length, then we need to test case after case since a function, as String.fromCharCode could be, cannot obviously use such strategy due to "infinite" accepted arguments.
In these cases, e.g. runtime push or similar methods, we don't have many options ... but these should be exceptions, not the common approach, as is for many other programming languages with some arguments support.

Conclusion

I do not pretend to change developers code style with a single post and things are definitively not that easy to normalize for each browser.
Unfortunately, we cannot even think about features detection when we talk about performances, we don't want 1 second delay to test all performances cases before we can decide which strategy will speed up more, do we?
At least we are now better aware about how much these common JavaScript practices could slow down our code on daily basis and, when performances do matter, we have basis to avoid some micro bottleneck.

Tuesday, October 06, 2009

NWMatcher - A Quick Look

As usual, as soon as I decide it's time to go to sleep, somebody :P has to post a stunning benchmark about a selector matcher ... did I shut down? No, I had to read the entire source code of the library, and this is my quick summary, but consider I am tired ...

NWMatcher, A Selector Monster

First of all, I did not know or remember this project and I must congrats with Diego Perini for different reasons.
The first one is that Diego used almost all best and unobtrusive technique to make it as reliable as possible, which is good, the second one is that Diego introduced something new to achieve its goal: create a Ferrari matcher via pre-compiled functions.

About NWMatcher

It is a lightweight stand alone library (so far, but already namespaced) which aim is to standardize some common DOM related task. The initial aim was to create a faster way to understand if a node matches a specific selector, something truly useful with event delegation.

About The Technique

To make things as fast as possible, Diego used a pre compilation strategy which is absolutely brilliant. Without XPath transformation, which is also not fully compatible with CSS in any case, and taking care of every single browser "gotcha", Diego creates once, and never again, the function able to perform selector related tasks. The result is that first call a part, with a new selector, the match method will perform a light speed!

This is the notable good part of NWMatcher, and now there's the bad one (not that bad in any case)

Few Inconsistencies

Except a weird procedure to understand if array slice could be performed over nodes, something I always got in 3 lines:

var slice = Array.prototype.slice;
try{slice.call(document.childNodes)}catch(e){slice=function(){
// whatever to emulate slice for this scope
}};

Diego uses a callback to understand native methods from fakes. This is generally good, and this function is isNative, but since these kind of checks are for greedy developers with global pollution maniac, I cannot understand why at some point there is a root.addEventListener ? ... and no checks if addEventListener is native one, something that could make the entire caching system useless or able to generate errors. OK, that would be silly, I mean to inject an event like that, impossible to emulate in Internet Explorer, but who knows what a library could do with such event ...
Another inconsistency is about being unobtrusive, goal reached 99.9% ... what is that, a public property attached directly in the used context? We need to be aware that the document will probably have a snapshot, plus an isCaching property, not a drama, but I think those are the exception that confirm the rule.
Another thing I'll never get is the usage of new in front of functions which aim is to return a non primitive value.

function A(){
return {};
};

Above function could be called with or without new and the result will be always the same, the returned object. This simply means that if we use new we are consuming CPU and RAM for no reason. So why a performances based library should not take care of this simple fact?

// example
function Snapshot(){
// here this exists
// and it has a prottype attached
// and it has been internally initialized
// to be used as Snapshot instance

// we return an instanceof Object?
// well done, so the garbage collector
// has to consider this instance
// which is a ghost instance, never used
// but it has been created
return {
// whatever ...
};
};

// let every comment inside the function
// make sense simply adding new
var snap = new Snapshot();

// a non-sense, imho, since this
// would have produced exactly the same
// without instance generations
var snap = Snapshot();

That's it. This stuff is really simple to get with C, C++, or those languages where we have to declare types, names, etc etc, and a new in front of a function is not transparent, is something to think about, cause a new is a new, we are asking for an instance, and a function able to return always another value, rather than the generated instance, shouldn't be called via new.

Diego, I am sorry, I am using this irrelevant gotcha simply because I wrote about these things dunno how many times ... please remove every new Snapshot from your code, or just use the instance, attaching proeprties.

Snapshot =
function() {
this.isExpired = false;
this.ChildCount = [ ];
this.TwinsCount = [ ];
this.ChildIndex = [ ];
this.TwinsIndex = [ ];
this.Results = [ ];
this.Roots = [ ];
}

Makes sense? For performances reason, I still suggest to simply remove every new, leaving just Snapshot ... OK, that is probably more than I was planning to say ...

Mutation Events Side Effects

For compatible browsers NWMatcher uses mutations events such DOMAttrModified, DOMNodeInserted, and DOMNodeRemoved. The cache is partially arbitrary, activated by defaults, deactivated via setCache(false).
Mutations events are used to cache results. Why mutation events? Let's say in a single function is so common, specially in jQuery world as example, to search the same bloody thing hundreds of time ...

$("body").doStuff($whatever);
$("body").doOtherStuff($whatever);
$("body").doSomethingElse();

Above way to code is present in dunno how many examples, articles, books, and is as elegant as illogical. If we need a collection, I know we all like the $("thingy") style, but it's that difficult to write code such:

var $body = $("body"); // that's it, wrapped once, SPEED!
$body.doStuff($whatever);
$body.doOtherStuff($whatever);
$body.doSomethingElse();
I am sure it is difficult, and Diego knows this stuff better than me, indeed he is using result cache to avoid repetitive expensive searches over potentially massive structures as a DOM could be, in order to guarantee best returned results performances. So far, so good ... and mutations events, attached to the root of the DOM, the document, are able to clear the cache ... how? via a callback. Simple? Sure, it is simple ... but there is a little detail we should consider.

Nowadays, Ajax based Web applications are constantly muted, eachAjax call aim is to change something, show something, or remove something. With these perpetual changes whatever event is attached into a mutation event will be fired dozen of times but Diego, which is not the last JavaScript hacker, found a way to partially avoid this problem. He removes the mutation so the first fired one, will avoid same operations for other N times. This is good, but there is still an event to manage, internally, and a callback to call, but the bad part is that for each select, those events have to be reassigned, or checked, again (isCached attaced property).
Talking about performances, we need to consider the real case scenario, rather than a static benchmark over the same selection, or couple of selections, where nodes are, as I have said, constantly changed via innerHTML, innerText, appendChild, removeChild, insertBefore, insertAfter, all operations probably present in every single function of our JavaScripted page.

Now, is it truly worth it to cache results? Why, if it was the key, browser vendors are not caching results when we perform a getWhateverByWhatever or querySelectorAll?
Is our library truly that slow that a couple of searches performed consecutively are such big problem so we need to increase libraries complexities, side effects, and browser problems/behaviors, for something that on daily basis will be used I guess 5% of the time due to constant DOM manipulation?

Always Cached Matches

The brilliant strategy used to pre compile functions could be a bit greedy if used lots of time, over lots of different CSS queries, and for a long online session. What am I talking about? Mobile devices, a la iPhone with 2Mb of RAM limit, and all those lambdas stored in any case in memory. Is there any test about this? I'd love to see or create one, but I need a good iPhone web app before. Finally, this is just a hint, when the selector "*" is present, I think there is no point to parse anything or create the pre-compiled function. That return true in the body, should be enough, so in dozen of reg exp, I would have used a simple "*" check, and return just true. OK, talking about consistency, this is not a real case scenario, 'cause we have to be silly to know if a node matches "*" ... of course it will ... but what we should not forgot, at least in version 1.1.1, is that a node, not present in the DOM, will match "*" in any case, as is for every other match. This could be Diego aim as well, not sure WebKit and FF nightly behave the same, but I honestly don't think a non rendered element should match a CSS selector...

As Summary

NWMatcher is definitively the best answer I have seen so far to match a css. Diego experience is everywhere in the code, and people in credits gave good help and advices as well. I have been probably too strong about these few things I have spot in the code, but I am planning to use NWMatcher and to test it on mobile devices as well so the purpose of this post is: please, make it perfect Diego, and thanks a lot, truly good stuff!

Friday, September 04, 2009

@font-face we are already doing wrong

Update - Now We Do Right

Thanks everybody for your tests and contributions. For those interested about why we were doing wrong please read both post and comments but for those just interested about the best way so far to serve correctly one or more font-face, this is the hack:

@font-face {
// define the font name to use later as font-family
font-family: "uni05_53";
// define the font for IE which totally ignores local() directive
src: url(../font/uni05/uni05_53.eot);
// use local to let IE jump this line and
// redefine the src for this font in order to let
// other clever browser download *only* this font rather than 2
src: local("uni05_53"), url(../font/uni05/uni05_53.ttf) format("truetype");
}

You can test directly this technique in my HTML5 Prime Directives Test Page



Credits

  • Paul Irish for its Bulletproof @font-face syntax

  • Mikuso, comments, for his suggestions about server configurations, instantly followed by Weston Ruter for its excellent article Efficiently Serving Custom Web Fonts

  • last, but not least, Scott Kimler, for his Better @font-face Syntax and his patience, testing directly inside a trace log, rather than trust 100% Fiddler or Firebug - P.S. my hat is off for that page, unfortunatly you have trolls problems as well, reading the first comment from somebody that got -1% of what you have done!
Links, snippets, tests, we have got everything we need to understand why font-face CSS plus file serving has been generally misunderstood and how we should do correctly, trolls included (the problem is not the browser).

Good Stuff!
Just last quick info for Scott Kimler, IE simply lacks "local" directive support, and this is the reason it ignores the second call.
If we put local(fontName), url(fontName.eot) it will not load the eot, neither the ttf - local is the key for this trick, but we'll have problems the day IE will understand local, unless the first src will not considered synchronous.
Hopefully, that day IE will support ttf since windows does already without problems.


Few weeks with new browsers and @font-face support that suddenly everybody started to suggest the "cross browser way" to include them ... which is 90% of cases apparently wrong.

The Wrong Way



/* IE first */
@font-face {
font-family: nomeDelFont;
src: url( /nomeDelFont.eot );
}

/* Firefox 3.5/Safari/Opera 10 */
/* but IE will download in any case */
@font-face {
font-family: nomeDelFont ;
src: url( nomeDelFont.ttf );
}

almost the equivalent showed here, via Ajaxian, and Edit ...

What Is Exactly Wrong


It does not matter if we use conditional comments, it does not matter if we put the right font for Internet Explorer before the other one (tricky, since IE does not overwrite the rule just because it does not understand the truetype format).

Our "favorite" browser, and others as well in some case, will always request the truetype as well, and being fonts not that lightweight, our page response could sensibly increase.

HTML5 Prime Directives


Inspired by RoboCop, I have created a simple test page that does not suffer the problem described before.
What we have there is an extremely compact and valid HTML5 page which size is up to 140Kb, and almost 67Kb just for the font.

Plus, as I've said, If we use common suggested snippets Internet Explorer will download in any case the non IE font, try yourself!

First Suggestions To Try To Solve The Problem



  1. never forget to specify the format, format("truetype"), which is apparently able to let IE misunderstand correctly the url and the result is a Error 404, still better than 70Kb to download

  2. moreover, use whatever strategy you know to avoid non IE file serving for IE as well (use Fiddler to monitor the network)

  3. try to create gzipped or deflated version of each font, possibly not runtime, and serve them via proper headers (69Kb down to 22Kb, as example, with 7Zip deflate)

  4. please tell us how you avoided IE wrong font download without using an horrible JavaScript document.write as I did in my little test page


Thanks, and I hope you agree about Prime Directives :D

Wednesday, September 02, 2009

PHP 5.3 Singleton - Fast And Abstract

In this same blog I talked different times about Singleton Pattern, in latter link "poorly" implemented in PHP 5.

I say poorly, because being Singleton a pattern, there are many ways to implement it and via PHP 5.3 things are more interesting.

There are several ways to define a Singleton class and to extend it, being able to automatically create another one that will follow that pattern.

Here is my implementation, which is extremely fast, logic, and simple as well.

<?php // Singleton :: The WebReflection Way

namespace pattern;

// this is just a pattern ...
// so no new Singleton is allowed
// thanks ot abstract definition
abstract class Singleton {

// note, no static $INSTANCE declaration
// this makes next declaration a must have
// for any extended class
// protected static $INSTANCE;

// @constructor
final private function __construct() {
// if called twice ....
if(isset(static::$INSTANCE))
// throws an Exception
throw new Exception("An instance of ".get_called_class()." already exists.");
// init method via magic static keyword ($this injected)
static::init();
}

// no clone allowed, both internally and externally
final private function __clone() {
throw new Exception("An instance of ".get_called_class()." cannot be cloned.");
}

// the common sense method to retrieve the instance
final public static function getInstance() {
// ternary operator is that fast!
return isset(static::$INSTANCE) ? static::$INSTANCE : static::$INSTANCE = new static;
}

// by default there must be an inherited init method
// so an extended class could simply
// specify its own init
protected function init(){}

}

?>


The static Trick


static is a magic keywords able to open hundreds of closed doors with old PHP versions. Thanks to this keyword it is possible to avoid a lot of redundant code, being sure that when static is called, it will be the current class call and not the one where self has been used. Thanks to this keyword is then possible to refer directly the current class instance, the one that will extend pattern\Singleton, using its own init method if preset, the empty abstract inherited otherwise.

Example



<?php

// for this test only, this class
// is in the root, same level of autoload.php

// include basic stuff ...
require_once 'autoload.php';

// define a singleton class
class SingA extends pattern\Singleton {

// my Singleton requires a
// protected static $INSTANCE variable
// if not present, nothing will
// be executed - Fatal error
protected static $INSTANCE;

// let's define something else
protected $a = 'A';
protected $b;

// let's try the init method
protected function init(){
// assign a random value to b
$this->b = rand();
}
}

// define another singleton class
class SingB extends pattern\Singleton {
protected static $INSTANCE;
}

// let's try the Singleton
$sa = SingA::getInstance();
$sb = SingB::getInstance();
$sb->runTime = 'here I am';
$sa2 = SingA::getInstance();

echo '<pre>',
var_dump($sa),
var_dump($sb),
var_dump($sa2),
var_dump($sa === $sa2),
var_dump($sa !== $sb),
'</pre>'
;

?>

Above test case will produce exatly this output:

object(SingA)#2 (2) {
["a":protected]=>
string(1) "A"
["b":protected]=>
int(31994)
}
object(SingB)#3 (1) {
["runTime"]=>
string(9) "here I am"
}
object(SingA)#2 (2) {
["a":protected]=>
string(1) "A"
["b":protected]=>
int(31994)
}
bool(true)
bool(true)

assuming the file autoload.php is present in the same level:

<?php

// simple autoload function
spl_autoload_register(function($class){

// assuming this file is in the root
// (just as example)
require __DIR__.
DIRECTORY_SEPARATOR.
// fix namespace separator ...
str_replace(
'\\',
DIRECTORY_SEPARATOR,
$class
).
// add classes suffix
'.class.php'
;
});

// that's it

?>


Why This Is Faster, Why This Is Better


The reason I posted about my own PHP 5.3 implementation is a php mailing list discussion which pointed to another extended Singleton for PHP 5.3.
That implementation will perform for each getInstance() call a callback which aim is to discover the class caller, get_called_class(), plus 2 up to 3 lookups plus an assignment over a static associative array, self::$instance[$class].
Finally, even if it could not make sense, extended Singleton classes cannot access to their own Singleton instances, aka: less control and overhead being Singleton a truly common pattern.
At least you know there is an alternative which aim is to let us remember that a singleton is a unique instance, the one we need to define as protected $INSTANCE, and that performances are always welcome, at least in my daily code/life style.

Enjoy!

Friday, August 14, 2009

Defeat Internet Explorer - Can You?

While I was creating a stand alone implementation of the LSSP described in my last HTML5 sessionStorage project, I did some test and bench as every Agile developer should do.

Well, what I have discovered, is that apparently Internet Explorer could perform some common task better than any other browser, at least in my good old Intel Centrino 1.6 Ghz.

I have created a benchmark page able to freeze my Firefox 3.5.2, to ask me if I would like to continue an Array.join execution with an average score that points out my Internet Explorer 8 wins with a score under 300 milliseconds against Chrome, Firefox and Safari.

As summary, is my Centrino dead or there's something we all did not consider about JScript engine?

P.S. Opera 10 beta 2 seems to score about 130 milliseconds as average, good stuff!

Thursday, April 23, 2009

vice-versa project, a philosophy rather than a library


Array.forEach(document.all, function(node, i, all){
// vice-versa project
});

well, there are few things I can say here, and first one is: please, if interested, help me!
The second one is my vision, a web where rather than criticisms, there is more collaboration to obtain good overall performances improving code quality.
This is not my old JSL project, this is a new groove, a new project, a non library, something I hope you will all appreciate.
But, if not, I am here to discuss about it :)
vice-versa project
Have fun with Web Development!


Update
Implemented a TaskSpeed test file for vice-versa project. Here first results ordered by average.



browser Pure vice Moo qoox dojo YUI AVG
Dom versa Tools doo
--------------------------------------------------------------------
Safari 4 198 114 392 205 246 410 260.83
Chrome 1 251 273 589 279 336 692 403.33
Opera 10 215 206 764 267 311 659 403.67
FireFox 3 404 670 2962 3557 1197 792 1597.00
IE 8 876 1031 10312 1470 2267 1749 2950.83
IE 7 795 1767 8174 1734 7796 3329 3932.50
IE 6 3941 4686 67590 16611 22388 24591 23301.17

Wednesday, April 22, 2009

Internet Explorer with V8 Engine :: A Partial Reality

Update now it works with Internet Explorer 7 and 8 with O3D plug-in enabled.

Today, via ajaxian, I discovered the new Google O3D project and as a nerd first, and a developer after, I instantly read the API.
Few seconds and I spot this: Use the V8 engine

OK, OK, whatever code you read there will not instantly work ... you have to understand the library and how to retrieve the dreamed eval function to make JavaScript execution possible inside the extremely fast V8 engine.

Obviously V8 integration is great with FireFox and other browsers, but a bit different in Internet Explorer.

This limitation is about the DOM manipulation, something that would make IE a good browser, but everything else, executed via V8 engine and without browser engine references, will perform 5 to 100 time faster.

Function creations, optimized loops, numbers, string manupulation, etc etc ... if we could use a little plugin to fully integrate V8 inside Explorer, we could all forget nowadays benchmark because it will perform better than many other browsers!

Bearing in mind the relationship between V8 variables, different 100% from JScript vars, and latter variables, we can delegate computational tasks to this engine makin IE fast as it has never (and will probably never) been!

What I have so far, is just a poor example about V8 inside IE possibilities, a page that does not work if you do not have V8 inside Exlorer and you do not enable its usage everywhere.

Write a loop like this in the textarea:

for(var a = [], i = 0; i < 500000; ++i)
a[i] = Math.random();

and switching between default and V8 you can read that the difference is about 5 times slower with the default Internet Explorer JavaScript engine, and Google V8.

Still, so far what I can spot as pros and cons is this:
Pros

  • mathematical operations up to 100 times faster

  • computational functions speed up

  • common AI patterns (AStar) finally usable in the web

  • games, chess, cards, whatever involves logic, speed up



Cons

  • even if you assign a V8 Array.prototype.forEach to native Array.prototype.forEach, the plugin cannot solve engine related dependencies problems ... so it will be simply slower, much slower, because of the data interchange between the method executed externally, and the original engine

  • DOM is not integrated, V8 in IE does not understand nodes so no way to speed up common libraries or add prototypes to native HTMLElement constructor

  • last, but not least, with my laptop I cannot even test the example page I posted before because the JS is not that perfect (Google guys, makeClients accept an id but you check .id === "o3d" in the loop ... does it make any sense?) and my card apparently does not support OpenGL or whatever library the o3d plugin requires



As Summary


This was just a quick post and an experiment which in my opinion is already god enough. I have a vision, about Internet Explorer 8.1 ... those guys created an April fool that is everything but not a fool. Come on Microsoft, let others replace your old, problematic, slow, JScript engine, and let us developers be free to create Web Applications as we would like to do ... please give to Google whatever they need to make V8 IE integartion possible, and let us dream about a not that far possible Web future!

Friday, April 03, 2009

A fast Array slice for every browser

It is an extremely common task and one of the most used prototype in libraries and applications: Array.prototype.slice
The peculiarity of this prototype is to create an Array from an Array like Object such arguments, HTMLCollection, other kind of lists as jQuery results.

Every browser, except Internet Explorer, allows direct calls via native prototype obtaining, obviously, best performances.

In IE, we have different ways to make this task possible, and these ways are mainly classic loops, or the isArray check to know when it is possible to perform the native call or not.


isArray = (function(toString){
return function(obj){
return toString.call(obj) === "[object Array]";
};
})(Object.prototype.toString);

Even using a closure, above function could slow down performances, specially in those libraries where Array conversions are performed almost everywhere.

As we all know, Internet Explorer behaves weird "sometimes", and one of the weirdest things is that native Objects are not instanceof Object.

In few words, instead of call a function to define if native slice could be applied, all we need to do is to check if the generic object is instanceof Object.
In this way native Arrays, arguments, everything with a length user defined, will be passed via native Array.prototype.slice, while for native objects, the good old loop will do the dirty job.

A better general purpose slice

$slice = (function(slice){
// WebReflection - Mit Style License
try {
// Chrome, FireFox, Opera, Safari, WebKit
slice.call(document.childNodes);
var $slice = slice;
} catch(e) {
// Internet Epxlorer
var $slice = function(begin, end){
// false with native objects/collections
// suitable for Array like Object (e.g arguments, jQuery, etc ...)
if(this instanceof Object)
return slice.call(this, begin || 0, end || this.length);
// ... every other case ...
for(var i = begin || 0, length = end || this.length, len = 0, result = []; i < length; ++i)
result[len++] = this[i];
return result;
};
};
return $slice;
})(Array.prototype.slice);

Simple, isn't it? And here a test case:
(function(){
try {

// HTMLCollection [object, ...]
$slice.call(document.getElementsByTagName("*"));

// arguments [3,2,1]
$slice.call(arguments);

// Array [1,2,3]
$slice.call([1,2,3]);

} catch(e) {

// should never happen
alert(e.message);
};
})(3,2,1);

where if nothing happen, simply means $slice worked without problems.

Side effects? With sandbox variables (iframes) IE will always use the loop, unless we do not bring its native Object constructor into the function (or the function into the sandbox)

Saturday, February 28, 2009

On JavaScript Inheritance Performance - One Step Back

Few days ago I wrote a post about this argument, proposing an alternative "best option" way to use an injected parent in each method.

As soon as more developers read my post, more sparkles came out from the fire: true classical inheritance simulation via missed methods in the chain, exception during methods execution that could trap the temporary injected parent, and other interesting stuff again.

At the end of all these tests, benchmark, and libraries evaluation, I decided to step backward about my proposal, making things simple, logic, and extremely fast (as much as possible).

My Conclusions


  1. if we inject a parent, we have to change and/or wrap the original method, adding noise in the execution and inevitably more operations to perform (read: less performances)

  2. for each inherited metod, even if it is the same of the parent one, we need to add functions and code which means more RAM and less portability

  3. more we over-mess the simple JavaScript inheritance stack, less control we'll have for debugging and maintenance

  4. using strategies like the one adopted from the YUI library could only add confusion because if we put the instance in a parent method, the super one or the super.super.super (and go on), its parent will be still the original one and if we call this.superclass in the wrong context, results will be always unpredictable for that method (unless we did not write down every specific case, if the instanceof A called that method ... if the instanceof B called that method, etc etc)


Accordingly, the fact we are all lazy developers should not mean we can loose performances, use more RAM, make things more complicated than we need, specially in this Web era where devices with limitations could use our code without problems (iPhone) but only if performances are reasonable and downloaded code size is, again, reasonable.


The new best option to use a parent method

Following the test proposed in the old post, this is how I can obtain best performances even against classical way to use parent methods:

function WRSub(name, age){
// classical and debug prone parent call (fastest)
WRClass.call(this, name);
this.age = age;
};
wr.extend(WRSub, WRClass, {
// WebReflection parent method call in closure
// faster than runtime method resolution:
// WRClass.prototype.toString.call(this)
toString:(function(toString){
return function(){
return toString.call(this) + ": " + this.age;
}
})(WRClass.prototype.toString)
});



Summary

I love performances, readable code (big lol from kangax? :P), code portability, logic execution, and all we need is already there in the language.
We do not need to over mess the inheritance chain, the only thing we need is a god way to extend able to understand if the browser is missing hidden methods (toString, etc) and nothing else.
Once we have this good way to extend a constructor, everything else will be fast, readable, debug prone, and compatible with every possible situation, without breaking our neck to understand why that method in that case behaved differently, or that parent did not change as expected, etc etc ... robust, reliable, and fast code? Forget all these parent/$super/superclass implementations, put what you need in a closure to simplify and speed up the code and that's it, as my new benchmark shows where my clean and simple implementation bites every other library, even the classical full namespace way.


News about WebReflection Library

I have added a couple of things which are truly common on daily basis development. You can find a list of all JS 1.6 Array methods to use with whatever list you want, DOM Collections included.

wr.Array.forEach.call(document.getElementsByTagName("div"), function(div, i, collection){
div.innerHTML = "I am div " + (i + 1);
});

Those are compatible with ECMAScript specs, native performances for updated browsers, best performances for IE and others.
The wr.Object.forIn is the classical for in loop plus hidden methods in IE, something we can use to extend constructors or to inspect objects.
I am considering to put the hasOwnProperty check by default to loop only properties assigned, and not those inherited, but for extending purpose, we need to loop everything.
setInterval and setTimeout are natives or wrapped to support extra arguments as well.
wr.id is the classic method to generate an expando or a unique id for each call while wr.is is a function with all native checks via Object.prototype.toString.

The purpose of the library is not (yet) to substitute other libraries, it is just about basic things we always need, focused on performances, compatibility, etc.
I'll add more, but so far enjoy the extend, now free of bugs since different, the forIn, the is, the id, and current Array implementations.