jQuery vs Prototype - part I

Prototype 1.6.0 was released to the public 4 days ago, at first I decided to check its performance and new features in comparison to the previous version, but being interested in other JavaScript libraries, I’ve changed my mind. Lets see how you can accomplish same tasks with the latest Prototype and jQuery libraries and simply see which one is faster. In this part I’m going to show the results of running single operations, in next part(s) I will prepare a sample website and write more complex test cases and, again, check how fast jQuery and Prototype can be (or how slow…).

Test environment setup

The following software was used:

  • Prototype 1.6.0

  • jQuery 1.2.1

  • Firefox 2.0.0.9

  • Firebug 1.05

  • Webdeveloper 1.1.4

Test page contains only one table with 500 rows, it’s generated using the following RHTML template:

<table>
<% (1..500).each do |i| %>
  <tr>
    <td class="first">
       i %>
    </td>
    <td class="second">
       "hello from #{i}" %>
    </td>
  </tr>
<% end %>
</table>

Running the tests

Each operation was executed using Firebug’s console with Profiler turned on and repeated 3 times,
between each execution the page was reloaded. Cache in Firefox was disabled using Webdeveloper plugin.
Here are the results of 7 test operations showing average times and number of method calls in each operation:

1. Adding ‘marked’ CSS class to every cell having ‘first’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb $(‘td.first’).addClass(‘marked’) ”`102.4953032
Prototype #1“` erb $$(‘td.first’).each(function(cell) { cell.addClassName(‘marked’) }) ”`117.1627056
Prototype #2“` erb $$(‘td.first’).invoke(‘addClassName’, ‘marked’) ”`129.9728062

Comment: no practical difference, although jQuery is a little faster.

2. Removing CSS class from every table cell having “second” CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb $(‘td.second’).removeClass(‘second’) ”`109.8553032
Prototype #1“` erb $$(‘td.second’).each(function(cell) { cell.removeClassName(‘second’) }) ”`87.4454551
Prototype #2“` erb $$(‘td.second’).invoke(‘removeClassName’, ‘second’) ”`100.645557

Comment: No big difference, especially when comparing Prototype #2 option with jQuery.

3. Setting ‘color’ CSS property in every div element which is inside a cell having ‘second’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb$(‘td.second div’).css(‘color’, ‘red’)”`173.9063536
Prototype #1“` erb$$(‘td.second div’).each(function(el) { el.setStyle({ color : ‘red’ }) });”`87.5854563
Prototype #2“` erb$$(‘td.second div’).each(function(el) { el.setStyle(‘color : red’) });”`98.2835064
Prototype #3“` erb$$(‘td.second div’).invoke(‘setStyle’, ‘color : red’);”`107.816070

Comment: Same here, Prototype 2 x faster

4. Adding new elements before every div element which is inside a cell having ‘second’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb $(‘td.second div’).before(‘

text

’) ”` | 368.611 | 15066 | | Prototype #1 | “` erb$$(‘td.second div’).each(function(el) { el.insert({ before: ‘

text

text

Comment: Wow…jQuery is almost 4 times faster, I should point out that Element#insert is a new method introduced in Prototype 1.6.0.

5. Removing all div elements which are inside cells having ‘second’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb$(‘td.second div’).remove()”`151.9552032
Prototype #1“` erb$$(‘td.second div’).each(Element.remove);”`65.7853060
Prototype #2“` erb$$(‘td.second div’).invoke(‘remove’);”`94,1055068
Prototype #3“` erb$$(‘td.second div’).each(function(el) { el.remove() });”`83.5914062

Comment: Prototype more then 2 times faster.

6. Hiding and un-hiding all div elements which are inside cells having ‘second’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb$(‘td.second div’).toggle();$(‘td.second div’).toggle();”`1948.82547653
Prototype #1“` erb$$(‘td.second div’).each(Element.toggle);$$(‘td.second div’).each(Element.toggle);”`158.98714106
Prototype #2“` erb$$(‘td.second div’).each(function(el) { el.toggle() }); $$(‘td.second div’).each(function(el) { el.toggle() });”`191.09616110

Comment: jQuery tragedy, Prototype toggles visibility of 500 divs 10 times faster!

7. Attaching event listeners to all div elements which are inside cells having ‘second’ CSS class:

LibraryOperationTime (ms)Method Calls
jQuery“` erb$(‘td.second div’).bind(‘click’, function(){ alert(this.innerHTML) })”`146.193535
Prototype #1“` erb$$(‘td.second div’).invoke(‘observe’, ‘click’, function(){ alert(this.innerHTML) });”`169,88911581
Prototype #2“` erb$$(‘td.second div’).each(function(el) { el.observe(‘click’, function(){ alert(this.innerHTML) }) });”`164.45610575

Comment: no practical difference.

General conclusion and impression

Executed tests show that Prototype seems to be faster then jQuery, with the exception of the new insertion method, which performance should be improved. Although I like jQuery syntax more then Prototype, the performance is way more important then saving few lines of code. Of course tests that I made don’t show how these libraries act in a real application, which is my task for the next part(s) of this article. Despite the results I must admit that I’m very excited about jQuery, my general impression is that this library is more mature then Prototype.

You may want to check out part II