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

Saturday, August 13, 2011

How To JSONP A Static File

Update I have discussed this object a part and I agree that the url could be used as unique id as well.
In this case the server should use the static url as unique id:

StaticJSONP.notify("http://cdn.com/static/article/id.js",{..data..});

So that on client side we can use the simplified signature:

StaticJSONP.request(
"http://cdn.com/static/article/id.js",
function (uid, data) {
}
);

The callback will receive the uid in any case so that we can create a single callback and handle behaviors accordingly.
The script has been updated in order to accept 2 arguments but, if necessary, the explicit unique id is still supported.



Under the list of "incomplete and never posted stuff" I found this article which has been eventually reviewed.
I know it's "not that compact" but I really would like you to follow the reason I thought about a solution to a not so common, but quite nasty, problem.

Back in 2001, my early attempts to include callbacks remotely were based on server side runtime compilation of some JavaScript data passed through a single function.

<?php // demo purpose only code

// do something meaningful with server data

// create runtime the output data
$output = '{';
foreach ($data as $key => $value) {
$output .= $key.':"'.$value.'"';
}
$output .= '}';

echo 'jsCallback('.$output.')';

?>

Above technique became deprecated few years ago thanks to the widely adopted JSON protocol and its hundreds of programming languages native/coded implementations.
Moreover, above technique became the wrong way to do it thanks to a definitively better solution as JSONP has been since the very beginning.
Here an example of what JSONP services do today:

<?php // still demo purpose only code

echo $_GET['callback'].'('.json_encode($data).')';

?>


JSONP Advantages

The callback parameter is defined on the client side, which means it can be "namespaced" or it can be unique per each JSONP request.
If we consider the first example every script in the page should rely into a single global jsCallback function.
At that time I was using my code and my code only so problems like conflicts or the possibility that another library would have defined a different jsCallback in the global scope were not existent.
Today I still use "my code and my code only" :D when it comes to my personal projects, but at least I am more than ever aware about multiple libraries conflicts the primordial technique may cause, even if all these libraries are my own one.

JSONP Disadvantages

Well, the same reason that makes JSONP powerful and more suitable technique, is the one that could make JSONP the wrong solution.
If we still consider the first code example, nobody could stop me to be "really smart" and precompile that file into a static one.

// static_service.js by cronjob 2011-08-14T10:00:00.000Z
jsCallback({category:'post',author:'WebReflection',title:'JSONP Limits'});

While precompiled static content may be or may be not what we need for our application/service, it is clear that if no server side language is involved the common JSONP approach will fail due limitations of "the single exit point" any callback in the main page depends on: the jsCallback function.

Advantages Of Precompiled Static Files

The fastest way to serve a file from a generic domain is a static one.
A static file can be both cached into disk memory, rather than be seek and retrieved each time, or directly into server RAM.
Also a static file does not require any programming language involved at all and the only code that will be executed will eventually be the one in charge of serving the file over the network, aka: the HTTP Server.
The most common real world example about static files is represented by a generic CDN where the purpose is indeed to support as many requests per second as possible and where static files are most likely the solution.
The only extra code that would be eventually involved is the one in charge of statistics on the HTTP Server layer but every file can be easily mirrored or stored in any sort of RAID configuration and be served as fast as possible.

Another real world example could be a system like blogger.com where pages do not necessarily need to be served dynamically.
Most of the content in whatever blog system can be precompiled runtime and many services/blog applications are doing it indeed.

Same is for any other application/service that does not require real times data computations and different cron job behind the scene are in charge of refreshing the content every N minutes or more.
If we think about any big traffic website we could do this basic analysis:

# really poor/basic web server performances analysis

# cost of realtime computation
1% of average CPU + RAM + DISK ACCESS per each user
# performances
MAX_USERS = 100;
AVERAGE_MAX_USERS = 100;

# cost of a threaded cron job
20% of average CPU + RAM + DISK ACCESS per iteration
# cost of static file serving
0.1% of CPU + RAM + DISK ACCESS per user
# performances
MAX_USERS_NOCRON = 1000;
MAX_USERS_WHILECRON = 800; # MAX_USERS_NOCRON - 20%
AVERAGE_MAX_USERS = 900;


If we consider that we may chose to delegate the cronjob to a server a part behind the intranet and the only operation per each changed static file will be a LOCK FILE $f EXCLUSIVE, WRITE NEW CONTENT INTO $f, UNLOCK FILE $f EXCLUSIVE so that basically only the DISK ACCESS will be involved, we can even increase AVERAGE_MAX_USERS to 950 or more.
I know this is a sort of off topic and virtual/conceptual analysis but please bear with me, I will bring you there soon.

Static Content And RESTful APIs

There is a huge amount of services out there based on JSONP. Many of them requires realtime but many probably do not. Specially in latter case, I bet nobody is implementing the technique I am going to describe.

A Real World Example

Let's imagine I work for Amazon and I am in charge of the RESTful API able to provide any sort of article related data.
If we think about it, a generic online shopping cart article is nothing more than a group of static info that will rarely change much during the day, the week, the month, or even the year.
Do online users really need to be notified realitme and per each request about current user rating, reviews, related content, article description, author, and any sort of "doesn't change so frequently" related to the article itself? NO.
The only field that should be as much updated as possible is the price but still, does the price change so frequently during the lifecycle of an Amazon article? NO.
Can my infrastructure be so smart that if, and only if, a single field of this article is change the related static file could be updated so that everybody will receive instantly the new info? YES.
... but how can do that if JSONP does not scale with static files ?

My StaticJSONP Proposal

The only difference from a normal JSONP request is that passing through the callback call any sort of library should be able to be notified.
Being the client side library in charge of creating the requested url and having the same library knowledge about what is going to be received and before what is going to ask, all this library needs is to be synchronized with the unique id the static server file will invoke. I am going to tell you more but as quick preview, this is how the static server file will look:

StaticJSONP.notify("unique_request_id", {the:response_data});


Server Side Structure Example

Let's say we would like to keep the folder structure as clear as possible. In this Amazon example we can think about splitting articles by categories.

# / as web server root

/book/102304.js # the book id
/book/102311.js
/book/102319.js

/gadgets/1456.js
/gadgets/4567.js

A well organized folder structure will result in both better readability for humans and easier access for most common filesystems.
Every pre compiled file on the list will contain a call to the global StaticJSONP object, e.g.

// book id 102311
StaticJSONP.notify("amazon_apiv2_info_book_102311",{...data...});


The StaticJSONP Object

The main, and only, purpose of this tiny piece of script that almost fits in a tweet once minzipped (282 bytes) is to:

  • let any library, framework, custom code, be able to request a static file

  • avoid multiple scripts injection / concurrent JSONP for the same file if this has not been notified yet

  • notify any registered callback with the result


Here an example of a StaticJSONP interaction on the client side:

var
// just as example
result = [],

// library 1
client1 = function (uri, uid, delay) {
function exec() {
StaticJSONP.request(uri, uid, function (uid, evt) {
result.push("client1: " + evt.data);
});
}
delay ?
setTimeout(exec, delay) :
exec()
;
},

// library 2
client2 = function (uri, uid, delay) {
function exec() {
StaticJSONP.request(uri, uid, function (uid, evt) {
result.push("client2: " + evt.data);
});
}
delay ?
setTimeout(exec, delay) :
exec()
;
}
;
// library 1 does its business
client1("static/1.js", "static_service_1", 250);
// so does library 2
client2("static/2.js", "static_service_2", 250);

setTimeout(function () {
// suddenly both requires same service/file
client1("static/3.js", "static_service_3", 0);
client2("static/3.js", "static_service_3", 0);

setTimeout(function () {
alert(result.join("\n"));
}, 500);
}, 1000);

It is possible to test the live demo ... just wait a little bit and you will see this alert:

// order may be different accordingly
// with website response time x file
client1: 1
client2: 2
client1: 3
client2: 3

If you monitor network traffic you will see that static/3.js is downloaded only once.
If the response is really big and the connection not so good ( 3G or worse than 3G ) it may happen that same file is required again while the first request is not finished yet.
Since the whole purpose of StaticJSONP is to simplify server side life any redundant request will be avoided on the client side.

The Unique ID ...

StaticJSONP can be easily integrated together with normal JSONP service.
As example, if we need to obtain the list of best sellers, assuming this list is not static due too frequent changes, we can do something like this:

// this code is an example purpose only
// it won't work anywhere

// JSONP callback to best sellers
JSONP("http://amazon/restful/books/bestSellers", function (evt) {
// the evt contains a data property
var data = evt.data;

// data is a list of books title and ids
for (var i = 0, li = []; i < data.length; i++) {
li[i] = '<a href="javascript:getBookInfo(' + data[i].id + ')">' + data[i].title + '</a>';
}

// show the content
document.body.innerHTML = '<ul><li>' + li.join('</li><li>') + '</li></ul>';


});

// the function to retrieve more info
function getBookInfo(book_id) {
StaticJSONP.request(

// the url to call
"http://amazon/restful/static/books/" + book_id + ".js",

// the unique id accordingly with the current RESTful API
"amazon_apiv2_info_book_" + book_id,

// the callback to execute once the server respond
function (uid, evt) {
// evt contain all book related data
// we can show it wherever we want
}
);
}

Now just imagine how many users in the world are performing similar requests right now to the same list of books, being best sellers ...

Unique ID Practices

It is really important to understand the reason StaticJSONP requires a unique id.
First of all it is not possible, neither convenient, to "magically retrieve it from the url" because any RESTful API out there may have a "different shape".
The unique id is a sort of trusted, pre-agreeded, and aligned information the client side library must be aware of since there is no way to change it on the server side, being the file created statically.
It is also important to prefix the id so that debugging will be easier on client side.
However, the combination to generate the unique id itself may be already ... well, unique, so it's up to us on both client and server side to define it in a possibly consistent way.
The reason I did not use the whole uri + id info on StaticJSONP request method is simple:
if both gadgets/102.js and books/102.js contains a unique 102 id there is no way on the client side to understand which article has been required and both gadgets and books registered callbacks will be notified, one out of two surely with the wrong data.
It's really not complicated to namespace a unique id prefix and this should be the way to go imho.

Conclusion

It's usually really difficult to agree unanimously to a solution for a specific problem and I am not expecting that from tomorrow everyone will adopt this technique to speed up server side file serving over common "JSONP queries" but I hope you understood the reason this approach may be needed and also how to properly implement a solution that does not cause client side conflicts, that scales, that does not increase final application size in any relevant way, and it's ready to go for that day when, and if, you gonna need it. Enjoy

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!

Tuesday, April 07, 2009

JavaScript Static Collection - A New Type Of Variable

Nowadays, I am working over a crazy manager between an XML with form information, another XML with custom rules to drive the XML with form information (DropDown onchange events, validation, and much more) and both to drive a runtime Ext.form.FormPanel with runtime components manipulated runtime via those two XML and over regular (x)HTML ... a runtime nightmare, but it is not the point.

While I was working over an Easy XPath Library for (x)HTML, trying to obtain best performances with the black sheep Internet Explorer, I ended up in an msdn page which explains the attributes HTML Element property.

Funny enough, that kind of property has truly a weird behavior, it is between VBScript and JavaScript. There are two ways to access its key/value pairs, the normal and logical one, plus the WTF!!! one. Example:

for(var
attrs = document.body.attributes,
len = attrs.length,
i = 0;
i < len;
++i
)
attrs(i) === attrs[i]; // true

The first though was: damn it, somebody poisoned my coffee again! (where the first time was when I read about Microsoft adopting WebKit as browser engine ...) but after few millisecond of brain delay, I realized that was brilliant!

The StaticCollection Type


Every Function in JavaScript has a length property, which tell us how many arguments that function accepts. In a completely dynamic language as JS is, this property has probably never been used, specially because every function has an ArrayObject arguments variable injected for each function call (but I guess would be interesting to use checks like: arguments.length > arguments.callee.length, for secret extra arguments to send ... anyway ... ).

Peculiarity of this property, we cannot overwrite it!
In few words, it is possible to create an Object via Function with immutable access over a collection, array, ArrayObject variable. This is the code:

var StaticCollection = (function(
name, // function name to assign
join // toString method from Array.prototype
){
// (C) WebReflection - Mit Style License
return function(){
var args = arguments, // trap sent arguments
length = args.length, // just a shortcut
i = 0, // used to assign values in order
callback; // Function to create and return
eval(
// create a function with a $name and $length arguments
// to block its length property
"callback = function ".concat(
name, "(",
new Array(length + 1).join(",$").substring(1),
// return first sent key from external arguments
"){return args[arguments[0]];}"
));
// assign in order properties via index ([0], [1], etc)
while(i < length)
callback[i] = args[i++];
// set the name for those browser where
// the function name is not present (mainly IE)
callback.name = name;
// set the useful toString method
callback.toString = join;
// return the FunctionObject
return callback;
};
})("StaticCollection", Array.prototype.join);

Due to fixed length behavior, the evaluation is absolutely necessary but not scary at all, since the string does not contain anything important, it is a simple wrap.
For those in Rhino or with some arguable rules about eval, here there is the intermediate step via Function:

...
i = 0,
callback= Function(
"args",
"return function ".concat(
name, "(", new Array(length + 1).join(",$").substring(1),
"){return args[arguments[0]];}"
)
).call(this, args);
...

which result is exactly the same but with a little bit of overhead caused by useless runtime Function execution.

StaticCollection Goals


  • one variable with static properties access plus indexed

  • indexed and called properties are comparable

  • indexes are mutable, perfectly suitable for relations between different objects/nodes/values

  • is the only quick and dirty way I know to make a collection immutable

  • something else, you'll find out :D



The StaticCollection Weirdness In Action


// Creation: same result
var sc1 = new StaticCollection("a", "b", "c"),
sc2 = StaticCollection("a", "b", "c"),
sc3 = StaticCollection.call(this, "a", "b", "c"),
sc4 = StaticCollection.apply(this, "abc".split(""))
;
/** [sc1, sc2, sc3, sc4].join("\n");
a,b,c
a,b,c
a,b,c
a,b,c
*/


// Properties Access
var sc = new StaticCollection("a", "b", "c")
sc(0); // "a"
sc[0]; // "a"
for(var key in sc){
key; // "a"
break;
};


// Immutable Properties: length + access via call
var sc = StaticCollection("a", "b", "c");
sc.length = 0;
sc.length; // 3
sc(1); // "b"
// sc(1) = 123; // error!


// Multiple access manifest
var sc = StaticCollection(456);
sc[0] === sc(0); // true
sc[0] = 123;
sc(0); // 456
sc[0]; // 123
for(var key in sc)
sc[key] !== sc(key); // true


// Type: function
typeof StaticCollection(1,2,3);


// Native toString: [object Function]
Object.prototype.toString.call(StaticCollection());


// Array Convertion:
var sc = StaticCollection(1,2,3);
sc.slice = Array.prototype.slice;
var a = sc.slice();
var b = Array.prototype.slice.call(
StaticCollection(4, 5, 6)
);


// Index Sort
var sc = StaticCollection(2, 1, 3);
sc; // 2, 1, 3
sc[0]; // 2
Array.prototype.sort.call(sc, function(a, b){
return a < b ? -1 : 1;
});
sc; // 1, 2, 3
sc[0]; // 1
sc(0); // 2


// Double indexOf
StaticCollectionSearch = function(value){
for(var
result = [-1, -1],
length = this.length,
i = 0;
i < length;
++i
){
if(this(i) === value){
result[0] = i;
break;
}
};
for(i in this){
if(/^\d+$/.test(i) && this[i] === value){
result[1] = i >> 0;
break;
}
};
return result;
};
var sc = StaticCollection(2, 1, 3);
Array.prototype.sort.call(sc, function(a, b){
return a < b ? -1 : 1;
});
StaticCollectionSearch.call(sc, 1); // 1, 0


// Array prototypes behaviour example
var sc = StaticCollection(1,2,3);
Array.prototype.shift.call(sc);
sc; // 2,3,
sc[0]; // 2
sc(0); // 1
sc.length; // 3


Crazy enough? The manually minified version is under 300 bytes, so let's start to play with ;)

/*WebReflection*/(function(n,j){this[n]=function(){var a=arguments,l=a.length,i=0,f;eval("f=function "+n+"("+new Array(l+1).join(",$").substring(1)+"){return a[arguments[0]]}");while(i<l)f[i]=a[i++];f.name=n;f.toString=j;return f}})("StaticCollection",Array.prototype.join);

Have fun!

Thursday, March 26, 2009

[PHP] Strict error on static call? Solved!

Just a quick post about Strict standard error when we have a class method which would like to behave differently if called statically.
Apparently, and this is a truly old bogus I opened ages ago, the solution was to supress Strict errors (lol, thanks developers) even if in every other programming language, via overload, this kind of situation could be solved in a bit.

How to solve the problem?

While last post I suggested a couple of runtime solutions, this time I suggest to simply avoid the method definition and use a different one with a meaningful name. In this example I created a String class:

class String {

// choose a recognizable name for protected method
static protected function _concat(array $arguments){
return new self(implode('', $arguments));
}

// use magic __callStatic function
static public function __callStatic($name, array $arguments){
// check the recognizable name
switch($name = '_'.$name){
case '_concat':
// return its call
return self::$name($arguments);
}
}

protected $__value__; // save the string somewhere

// assign initial string, if any
public function __construct($__value__ = ''){
$this->__value__ = $__value__;
}

// use magic __call method
public function __call($name, array $arguments){
// check the recognizable name
switch($name = '_'.$name){
case '_concat':
// normalize expected arguments
array_unshift($arguments, $this->__value__);
// return its call
return self::$name($arguments);
}
}

// this is a String class ...
public function __toString(){
return $this->__value__;
}

}


// test the alchemy
$str = new String('Hello');
var_dump(
String::concat('Hello', ' ', 'World', '!') == $str->concat(' ', 'World', '!')
// true, both are Hello World!
);

As we can see, errors are gone and the code is much easier to maintain. Hope this will help (performances? ... oh, come on!)

Monday, February 02, 2009

PHP static as virtual self, what else for parent?

I find the static keyword in PHP 5.3 absolutely useful, but I instantly felt into a dilemma: what about parent?

With static it is possible to refer to a generic class static property, without referring the class where the method has been declared.
Here there is a simple example:

class Numbers {
public static $value = 0;
public static function getValue(){
return static::$value;
}
}

class One extends Number {
public static $value = 1;
}

class Two extends Number {
public static $value = 2;
}

$one = new One;
$two = new Two;
$one->getValue(); // 1
$two->getValue(); // 2

Above example shows how static behaves when an instance calls a method which uses static keyword.
Whatever subclass it is, we will always obtain the defined value (if any, otherwise the inherited one) as expected.

But what about parent behavior?

If we use parent inside a method it is like using self, the parent keyword will always refers to the parent class, if any, of the method which contains the parent keyword. If we add a function like this in the Numbers class:

public static function getParentValue(){
return parent::$value;
}

every subclass wont be able to show the Numbers $value and an error will be generated instead.

To obtain the desired result we have to use the ReflectionClass:

// class Numbers ...
public static function getParentValue(){
$class = new ReflectionClass($this);
return $class->getParentClass()->getStaticPropertyValue('$value');
}

Above code is much slower than parent::$value because of the instance creation plus its method call for each ReflectionClass instance ($this plus the one returned by getParentClass)

Now, the question is: is it truly necessary? Will we have other ways to retrieve a "static parent" from a method?