debuggable

 
Contact Us
 
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12

JavaScript Meetup Berlin + Slides

Posted on 13/1/10 by Felix Geisendörfer

Last night I had the opportunity to speak about node.js at the first Berlin JavaScript user group meeting. I'm really thankful to Robin Mehner, Jan Lehnardt and the awesome people at upstream and co-up for organizing the event and hopefully many to follow.

Anyway, here are the slides:

You can also download them as PDF (344 kb).

The meetup itself was rather awesome. ~35 people showed up with many coming from different backgrounds (Rails, Symfony, Zend, Python, ...) united by their interest in JavaScript.

-- fg

 

CakePHP Authsome - Debuggable's Xmas Gift

Posted on 25/12/09 by Felix Geisendörfer

Merry Xmas everybody. We hope you are having a lovely time and get to renew the batteries for an awesome 2010 over the holidays.

To ease the withdrawal symptoms, Tim and I decided to do some light development over the holidays in order to create a little Xmas gift for the CakePHP community:

The Authsome plugin: Authentication for people who hate the AuthComponent.

We have been using a system very similar to Authsome for all our CakePHP projects over the years, but it wasn't until now that we had a chance to properly decouple it from the individual projects we used it in. A big thanks for that goes to ThreeLeaf Creative, the makers of a fantastic CakePHP CMS system who paid for the refactoring.

Next on the radar is Righteful: Acl for people who hate the Acl component. We hope to have it ready at some point early next year.

Alright, so go ahead and read the authsome docs over at Github and let us know what you think.

Merry Xmas,

-- Tim & Felix

 

RightJS 1.5: 6-8 times faster than jQuery

Posted on 9/12/09 by Felix Geisendörfer

My journey of mastering procrastination has led me to an interesting article on Hacker News today:

RightJS 1.5: 6-8 times faster than jQuery

(The title has been updated to "RightJS Version 1.5.0 Is Out" since I started writing this.)

Wow, I thought! This sounds like an excellent example of cargo cult science, one of my favourite subjects.

I mean I love innovation in this field just like everybody else. But seriously, jQuery is not exactly know for being slow & heavy. So anybody claiming a 6-8x speed improvement must have achieved an unbelievable breakthrough. Either that, or he must be using using the cargo cult method.

Applying the cargo cult method to performance testing is rather simple, which probably explains its popularity. You pick a random series of tests that can be run against the various implementations you want to compete with. Then you spend a few hours hacking away at your implementation until it is the clear winner. Don't give up if it becomes too hard, just tweak the test cases to slightly favor your implementation. It's really as easy as that.

I can totally understand why people are doing that. The opposite would mean that you have to apply the scientific method, which is really cumbersome. First you have to collect data, lots of it. In our case that means performing very detailed analysis and profiling of a large enough set of real world JavaScript applications. Using this data set, you should be able to answer questions like: What are the most common selectors people use? What DOM operations are popular? Which of those are actually relevant to the performance of the analyzed applications? With those answers you can attempt to come up with a series of tests that will rank the various implementations according to their performance. But actually writing those tests will be very hard. Should you use the most distinct and sexy way in each implementation? Or should you use the most effective techniques people have come up with?

Luckily there is a third option. It is called specialized benchmarking. You start by admitting that the things you are going to test are purely based on your curiosity about them, possibly because they are related to the particular problem YOU care about. Make it very clear that the outcome of those tests should in no way be seen as an indicator for overall performance and try to hide them from people who don't know what that means.

Specialized benchmarking will possibly not answer anybodies questions other than your own, but it beats the hell out of the cargo cult method.

Let's examine why the RightJS performance tests get it wrong and what they could do about it. From this point on I will only refer to material on their page, the post on Hacker News was just how I heard about them.

First of all, they claim that their performance benchmarks are there "To give you some ideas about the project quality and abilities". I think that should be changed to: "We are especially fast for the following operations (...), those however are not proofen to be good indicators for general performance in JS projects.". It's kind of like weight loss advertisement. You can show pictures of people who lost 50 pound, but you gotta put that "* Results are not typical" note there. This way people can pause for a second, and remember that there are no magic bullets to weight loss and consider their purchase with that in mind.

After that, they could start to decide whether some of their tests are worth keeping, and if so, make sure that they are as scientific as possible. I'll just use their test #1 as an example, but check the test suite for yourself, to see that this pattern is repeated throughout the entire thing.

Testing jQuery DOM building (343ms*):

"make": function(){
  for(var i = 0; i<250; i++){
    $("<ul id='setid" + i + "' class='fromcode'></ul>")
      .append("<li>one</li>")
      .append("<li>two</li>")
      .append("<li>three</li>")
      .appendTo("body");
  }
  return $("ul.fromcode").length;
}

Testing RightJS DOM building (80ms*):

"make" : function(){
  for (var i = 0; i < 250; i++) {
    document.body.appendChild(
      new Element('ul', {
        'class': 'fromcode', id: 'setid'+i
      }).insert([
        new Element('li', {html: 'one'}),
        new Element('li', {html: 'two'}),
        new Element('li', {html: 'three'})
      ])
    );
  }

  return $$('ul.fromcode').length;
}

I smell cargo! First of all, why is RightJS using a native DOM method, document.body.appendChild, and jQuery has to use .appendTo('body')? Those are two radically different operations, and just to see how radical lets make the following change:

Optimized jQuery DOM building I (194ms*):

"make": function(){
  for(var i = 0; i<250; i++){
    document.body.appendChild(
      $("<ul id='setid" + i + "' class='fromcode'></ul>")
        .append("<li>one</li>")
        .append("<li>two</li>")
        .append("<li>three</li>")[0]
    );
  }
  return $("ul.fromcode").length;
}

Ouch, an error rate of 43% against jQuery. Let's try harder:

Optimized jQuery DOM building II (72ms*):

"make": function(){
  for(var i = 0; i<250; i++){
    document.body.appendChild(
      $(
        "<ul id='setid" + i + "' class='fromcode'>"+
        "<li>one</li>"+
        "<li>two</li>"+
        "<li>three</li>"+
        "</ul>"
      )[0]
    );
  }
  return $("ul.fromcode").length;
}

If this was a presentation I would have an LOLCat saying "jQuery rulez" right now. But luckily this isn't and I'll try to reason scientifically about this.

jQuery is NOT faster in this example. Don't believe the numbers you see. They have been meaningless all along. The reason for that is simple: While initially it looked like we were performing the same test with jQuery as we were with RightJS, we never actually did! The jQuery example, from the beginning, was creating DOM elements from HTML strings, while RightJS was wrapping the document.createElement API. This is not the same thing and you cannot learn anything from comparing apples to oranges.

The truth as far as this test case is concerned? Well, jQuery simply does not have a document.createElement wrapper. Thus you cannot compare it to implementations that do. And why should you? DOM building like this is largely useless, given excellent alternatives such as John' Micro -Templating engine.

Just to show how useless this test was from the beginning, here is my not so paradox implementation that outperforms the pure DOM test:

Testing Pure DOM building (37ms*):

"make": function(){
    for(var
        body = document.body,
        ul = document.createElement("ul"),
        li = document.createElement("li"),
        i = 0,
        fromcode;
        i < 250; ++i
    ){
        fromcode    = ul.cloneNode(true);
        fromcode.id = "setid" + i;
        fromcode.className = "fromcode";
        fromcode.appendChild(li.cloneNode(true)).appendChild(document.createTextNode("one"));
        fromcode.appendChild(li.cloneNode(true)).appendChild(document.createTextNode("two"));
        fromcode.appendChild(li.cloneNode(true)).appendChild(document.createTextNode("three"));
        body.appendChild(fromcode);
    };
    return  utility.getSimple.call(body, "ul.fromcode").length;
}

Optimized jQuery DOM building III (36ms*):

"make": function(){
  var elements = '<div>';
  for(var i = 0; i<250; i++){
    elements = elements+
        "<ul id='setid" + i + "' class='fromcode'>"+
        "<li>one</li>"+
        "<li>two</li>"+
        "<li>three</li>"+
        "</ul>";
  }
  $(elements+'</div>')
    .children()
    .each(function() {
      document.body.appendChild(this);
    });

  return $("ul.fromcode").length;
}

As you can see, the cargo cult method is quite powerful : ).

Anyway, I don't want to discourage the development of RightJS in any way. I think it's awesome that there are libraries that are trying to compete with jQuery.

It is really hard to do meaningful performance testing and infinitely easy for some random punk like me to come along and point out all the flaws. To me, even trying to do a general purpose performance test against 6 (!) implementations, that is pure bravery. So in case you decide to do something similar, just admit the odds you are up against and people will be very forgiving and engaged.

Comments, hate mail & suggestions are welcome!

-- Felix Geisendörfer aka the_undefined

* Results not typical - Some recent version of Firefox on my Laptop, picking random samples from runs that looked good!

 

Parsing form data with node.js

Posted on 24/11/09 by Felix Geisendörfer

Many people asked about form parsing in #node.js after the initial buzz-wave yesterday.

Right now node does not include a parser for regular form data (application/x-www-form-urlencoded). However, you can use the http multipart parser to achieve the same thing.

Here is a bare-bone example for that:

var http = require('http');
var multipart = require('multipart');
var sys = require('sys');

var server = http.createServer(function(req, res) {
  switch (req.uri.path) {
    case '/':
      res.sendHeader(200, {'Content-Type': 'text/html'});
      res.sendBody(
        '<form action="/myaction" method="post" enctype="multipart/form-data">'+
        '<input type="text" name="field1">'+
        '<input type="text" name="field2">'+
        '<input type="submit" value="Submit">'+
        '</form>'
      );
      res.finish();
      break;
    case '/myaction':
      multipart.parse(req).addCallback(function(parts) {
        res.sendHeader(200, {'Content-Type': 'text/plain'});
        res.sendBody(sys.inspect(parts));
        res.finish();
      });
      break;
  }
});
server.listen(8000);

Run this code and point your browser to http://localhost:8000/. You will be presented with a form, and when you submit it, you will see the contents of the POST as JSON. For more information check:

The important part is specifying the enctype of your form as "multipart/form-data".

If you need to parse regular form data, have a look at sixtus www-forms module. Chances are good a module like this, with a similar API to the multipart parser, will make it into the core at some point (patches are welcome).

HTH,
-- Felix Geisendörfer aka the_undefined

 

Simon Willson: Node.js is genuinely exciting

Posted on 23/11/09 by Felix Geisendörfer

Simon Willson of Django fame has just published an awesome introduction to node.js: Node.js is genuinely exciting. Enjoy!

-- Felix Geisendörfer aka the_undefined

 
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12