Thursday, March 29, 2012

Two methods for optimize performance for finding comments for template usage in html-documents

Ok, so we are using comments in our project as placeholders for our templating system. We want to do that, since we don’t want to add unnecessary elements to our DOM-tree.
However, finding comments is not as easy as finding for example a div with an ID, since they aren’t a part of the DOM model. And that was exactly why we want to use them in the first place, remember!? J
So how do we find comment elements? Well, one way as we found was to traverse the document using jQuery, but instead of using children() we use contents(). Contents return all content, including comments, making it possible to find them.
However, finding an object in a document-tree manually, by traversing the elements one by one, is a very expensive operation that scales badly. That’s not good, since we need our site and code to be fast no matter how large our page is.

XPath

So what can be done? Well, it turns out that Firefox and Chrome supports xpath lookups, making the comment finding extremely easy. All you have to do is to use document.evaluate together with comment(): 

But this doesn’t work on IE. Too bad, since it’s extremely fast.
However, we know something about our problem. We aren’t interested in just any comments, but comments to be used with our template system. That means that the comments that we are looking for are more likely to be found close to the root of the document tree. In our first implementation we did a traditional, recursive traverse of the document tree, going from root to branch and leaf, one at a time, finishing the previous branch before starting in the next.
That’s not optimal. For the footer templates that mean that we need to traverse through almost the full tree every time before we find it.

Horizontal versus vertical traversing 

The solution then is to traverse the tree one level at the time, starting with looking for the comments one level down from the document root, then two levels down, then three, etc. But however much faster that it, it still means a lot of tree traversal. And what can we do then? 
Cache

Of course, as we all know, the answer is cache. We want to make the comment easy to find. We can’t really store the comment itself, because we can’t insert DOM elements after it. But what we can do is to save the comment’s parent’s location. That way, the next time we need to find the comment, we will start looking directly at the right branch.
Of course, if the templates changes position, if a template placeholder is within another, the comments we’re after might move, or their parents being removed. That’s easy enough to solve; If that happens, we start a new, smart search.

Results

So what are the results of the smart document tree traversal and caching? A great speedup, actually, that gets better as the DOM grows. For a tiny hml-document our optimized version where 40% faster, for a small page (~600 elements in the DOM-tree) the speedup was 150%, and for a normal sized page (~1500 elements) the speedup was 700%!
That’s a good result. Also, as long as the template comments are close to the document root, the optimized version will scale perfectly no matter how large the document is.

(I did this as a part of a project here at Betsson. We do great stuff here and have a lot of fun as well, so check out Betsson's open positions!)

Tuesday, March 27, 2012

A quick comparisson of performance when creating DOM elements using Javascript

Over lunch we discussed the difference in performance when creating DOM elements with native javascript as compared to using jQuery, and the difference in execution time for creating elements to simply reusing old ones.

To test this, we created a short snippet where we added and removed div elements to the body 10,000 times. We created four different cases.

  1. Create everything with jQuery, lookup for elements to be removed using jQuery.
  2. Create everything with jQuery, but cache the elements so that the extra lookup is avoided.
  3. Create everything with jQuery, but instead of deleting objects, save them and reuse them.
  4. Do everything with native xml functions (createElement, removeElement etc), use cache and reuse elements.

I would have expected that the biggest difference would be between case 1 and 3, since object creation is an "expensive" operation.

The results looked like this:

BrowserCase 1Case 2Case 3Case 4
Firefox 111569ms1359ms1105ms496ms
Chrome 17837ms548ms366ms78ms

The results were kind of surprising. Reusing elements are efficient, but not the kind of performance booster as it is in Flash or Cocoa. But what are very clear are two things: jQuery's DOM append is very expensive, and Chrome are a lot faster than Firefox. On Chrome the difference between the original script and the "optimized" case was especially large, with a performance boost of 10 times!

(I did this as a part of a project here at Betsson. We do great stuff here and have a lot of fun as well, so check out Betsson's open positions!)

Monday, March 19, 2012

The All Mighty Johan Ripås-plugin

Jag funderar på om man skulle ta sig an det här med att länka till Johan Ripås på ett lite mer effektivt sätt. Kanske rent av skriva ett plugin till Wordpress. Med några enkla knapptryckningar skulle man kunna få in en länk till Johan Ripås hemsida på alla hemsidor som installerade pluginet.

Hur utvecklar man då ett sånt plugin? Jo, det första man gör är att skapa ett bibliotek i sin wordpress-installation (givetvis utvecklingsvarianten) under wp-content/plugins med namnet johan_ripas.
I denna placerar vi två filer: readme.txt och johan_ripas.php.
I readme.txt skriver vi det vanliga:

=== Johan Ripås ===
Contributors: Aspelund
Tags: Johan Ripås
Requires at least: 3
Tested up to: 3
Stable tag: 3

This plugin adds links to support the cause of Johan Ripås. Nothing more, nothing less.

== Description ==

This is a simple plugin that adds two links to your blogs footer.
One link to [Johan Ripås](http://www.lindqvist.com/tag/johan-ripas/) and on link to [Johan Ripås](http://johanripas.wordpress.com/).
It is not likely that this plugin will ever be updated.

== Installation ==

Use Wordpress' own installation process in the admin guide.

== Changelog ==



I filen johan_ripas.php skapar vi sedan koden som lägger till länkarna till Johan Ripås och Johan Ripås. Vi hookar upp dem mot actionen wp_footer.

class johanripas {
    function add_johan_ripas_link()  {

        echo '
Jag länkar glatt till Johan Ripås och Johan Ripås.
';     } } add_action('wp_footer',array('johanripas','add_johan_ripas_link')); ?>

Notera att vi lägger koden inuti klassen johanripas. Det innebär att vi undviker namnkonflikter. :)
När detta är gjort har vi vår plugin, och det är bara att aktivera den från admin-sidan.

För att göra det lite lättare så har jag sparat det hela som en färdig fil: Johan Ripås - The plugin.

Sunday, September 11, 2011

Tre steg för att lära sig ny teknik



Att ta sig an ett nytt programmeringsspråk, en ny plattform eller kanske ett nytt ramverk kan ibland kännas som en stor och tuff utmaning. Jag tänkte här dela med mig av en snabbvariant av hur jag gör för att snabbt och enkelt lära mig något nytt.

Jag börjar med några ord om min bakgrund. Jag är 34 år, fick min första dator som åttaåring, är civilingenjör och har arbetat professionellt med bland annat ASP, PHP, MySQL, C#, ASP.Net, Actionscript, Perl, Javascript och Zend Framework. Det är när jag har lärt mig dessa tekniker som jag har tagit fram min ödmjuka, och knappast speciellt revolutionerande inlärningsteknik.


  1. Läs mycket och snabbt
    I det här steget handlar det om att få en översikt över den teknik man ska lära sig. Här vill vi inte lära oss detaljer, utan läser mycket och snabbt. Tjocka datorböcker väldigt bra, typ ”Teach yourself C# in 24 hours”, ”Zend Framework bible”. Långa introduktioner på teknikens webbplats kan också vara en bra start, som hela ”Zend Reference Guide” eller hela iOS Developer Library’s ”Getting Started”. Nyckelordet är att man vill läsa mycket. Läs dock snabbt, lägger man två timmar koncentrerat kan man ta sig igenom nästan vilken datorbok som helst medelst skumläsning.
  2. Nu genomför vi ett antal tutorials. Om det inte är helt ny teknik så finns det alltid en stor mängd tutorials att följa. Följ 2-4 tutorials, och genomför själv i din egen utvecklingsmiljö varenda steg och skapa projekt och program/webbplats/app. Se till att allt fungerar. Här slarvläser vi inte längre. När vi stöter på saker vi inte riktigt förstår så slår vi upp det i den digra litteraturlistan vi plöjde i steg 1. Om vi fortfarande inte förstår det så släpper vi det efter en kort stunds fördjupning. Nyckelordet här är att vi försöker förstå. Vissa saker kanske inte klarnar förrän efter flera veckor, och det är helt ok, men det klarnar inte om vi inte försöker.
  3. Nu är det dags att prova vingarna, och vi skapar helt egna projekt med en tydlig målbild för projektet. I den här fasen är det viktigt att försöka göra så mycket som möjligt själv, utan hjälpmedel. Arbeta koncentrerat.
    Givetvis så tar man hjälp av tutorials och texter när man fastnar, allt annat vore dumt.
    Ibland råkar man göra saker som är helt fel för tekniken. Då är det bara att börja om med ett nytt projekt, skapa, pula och dona. För mig är det ofta i det här steget som saker och ting klarnar, och saker som framstod som obegripliga i steg 1 och 2 ger riktiga aha-upplevelser. 


Efter dessa tre steg är vi redo för skarpa projekt. Vi har en relativt bred, men tunn, teoretisk bas att stå på från steg 1, så vi vet ungefär vad man kan göra med tekniken, och var man kan läsa mer. Genom att följa tutorials i steg två så har vi fått se hur erfarna utvecklare hanterar tekniken, och i steg tre har vi fått viss egen praktisk erfarhet.

Sen återstår bara 5000 timmars arbete med tekniken innan man kan kalla sig expert.

(Foto: itzpapalotl's)

Sunday, September 4, 2011

Testning av en klusteralgoritm

Jag pratade med @mattiasostmar igår om olika metoder för att skapa klustrande algoritmer. Här kommer en något text med något högre detaljnivå på temat:
Något som är viktigt om man gör det, är givetvis att inte överoptimera algoritmen för ett visst resultat som man själv ”vill ha”, utan att ha en metodik som minimerar risken för detta.

Ett enkelt sätt som man kan göra det på är att dela upp sina testdata i tre grupper, grupp A, grupp B och grupp C. Viktigt där är att grupp C ska vara stor, så att man kan få resultat som är signifikant.

Den första gruppen, den använder jag aktivt i min testning. När jag ser utfall, då skruvar jag på min algoritm hur mycket jag vill. Jag testar, skruvar, testar, skruvar, tills jag är nöjd med mitt resultat. Grupp A kan vi kalla experimentdata.
När jag går till grupp B däremot, då ska jag egentligen vara rätt så klar med min algoritm. I den gruppen kanske jag kan skruva något litet, för att få bort en överoptimering, men inte mer än så.

Grupp C, det är den gruppen med data som avgör vad jag presenterar för pricksäkerhet för kunden. Om jag har ett stort antal klassificeringar, där min data klassificeras i olika grupper, så kikar jag på varje grupp och och ser hur ofta min algoritm gjorde rätt. Om vi har n tester för grupp n, där jag har 80% rätt, så hämtar jag min gamla Mathematics handbook och slår upp vad det blir för signifikans på det hela. Målet där är ju att kunna skriva ”80%+-4%” eller något liknande.
:-)

Friday, August 26, 2011

Appar & Collage

En snabb uppdatering om vad som händer på Shoppinggatan - Vi håller som bäst på att färdigställa vår första Shoppinggatan-app. Den blir väldigt bra, och jag tror att många kommer att ha stor nytta av den när den är färdig.

I övrigt så arbetar vi på att göra lite PR för vår collageeditor, där man kan göra fina collage som den nedan:

Sunday, April 3, 2011

Att 301:a-redirecta en hel sajt

För en tid sedan hittade vi en av våra utvecklingssajter på Google. Av någon anledning hade vi glömt robots.txt. Givetvis vill man då inte ha kvar sajten, då det kan bli problem med duplicate content och en mängd annat, samtidigt var vi lite osäkra på exakt hur Google skulle reagera på att ett antal tusen hårdkodade länkar till vår sajt plötsligt försvann; För på vår sajt är vissa länkar kodade relativt, medan andra är hårdkodade.
Det enda riktiga att göra i den situationen tyckte vi var att 301:a alla sidor till den skarpa sajten. På det sättet borde problemen minimeras, även om det inte är helt sjävklart vad som händer när man hanterar problemet.
Sagt och gjort. Att 301:a en hel sajt i Lamp-miljö är ingen stor sak. Tre rader kod i .htaccess för den givna sajten var allt som behövdes:


RewriteEngine on
RewriteBase /
RewriteRule ^(.*)$ http://www.shoppinggatan.se/$1 [R=301,L]


Redirecten slår igenom momentant och Googles robotar kommer att förstå vad som har hänt.