nam: Javascript Performanz in Opera

Hallo

Beim Vergleich der Ausführungsgeschwindigkeit einer Funktion ist mir aufgefallen, dass Opera (Version 9.25, sowohl auf OS X, als auch auf XP) bei dieser Funktion um ein Vielfaches langsamer ist, als die anderen Browser.

Hier die Zahlen:
OS X Webkit(Nightly): 108ms
OS X Safari: 250ms
XP IE 6: 400ms
XP IE 7: 290ms
OS X Firefox 3b: 400ms
OS X Firefox 2: 500ms
OS X/XP Opera: mehrere Sekunden, sehr unregelmässig

Mein Testsystem ist ein MacBook Pro (10.5.2, 2.2 GHz Intel Core 2 Duo, 4GB RAM, XP läuft unter VMware Fusion)

Hier ist das Testcase: http://www.mnn.ch/SpeedTest.html
Es ist ein Teil von http://code.google.com/p/hyphenator/

Könnt ihr das nachvollziehen?
Woran liegt das? Mach ich was falsch?
Hat jemand Erfahrungen/Ideen, wie ich den Code für Opera beschleunigen kann?

Das ganze macht mich stutzig, weil Opera sonst für seine schnelle JS-Engine bekannt ist...

Danke und Gruss,
Mathias

  1. echo ($light == true) ? 'Guten Tag,' : 'Guten Abend,';

    also deine Zahlen kann ich Bestätigen. Also Ursache kannst du diese Zeile ansehen:

    patterns[key]=value;

    Der Rest des Scriptes läuft (zumindest bei mir) in ca 400 ms durch wenn man diese Zeile entfernt. Nun eine Lösung habe ich direkt nicht zur Hand, ich würde aber in diesen Fall versuchen patterns[] anders zu speichern. Vielleicht als ein Mehrdimensionaler Array.

    Grüße

    Markus

    --
    Langeweile? Sudoku online spielen ;)
    1. Hi

      also deine Zahlen kann ich Bestätigen. Also Ursache kannst du diese Zeile ansehen:
      patterns[key]=value;

      Tatsächlich! Ich hatte isFinite(c) im Verdacht. Ein Microbench zeigt, dass die Zuweisung einer neuen Property in Opera ziemlich viel Zeit braucht.

        
      var i=13000; //so viele Muster muss ich etwa verarbeiten  
      var c={};  
      var start=new Date().getTime();  
      do {  
       c[i]=i;  
      } while (i--);  
      var end=new Date().getTime();  
      document.write(c+'\r'+(end-start));  
      
      

      Der Rest des Scriptes läuft (zumindest bei mir) in ca 400 ms durch wenn man diese Zeile entfernt.

      Auch wenn ich die Zeile auskommentiere, läuft das Script immer noch viel zu langsam in Opera.
      Gibt es einen Debugger/Benchmarker für Opera so wie Venkman für Firefox?

      »»Nun eine Lösung habe ich direkt nicht zur Hand, ich würde aber in diesen Fall versuchen patterns[] anders zu speichern. Vielleicht als ein Mehrdimensionaler Array.
      Das geht nicht. Ich muss später extrem schnell drauf zugreifen können und da ist die Hash-Tabelle des Object() genau richtig.

      Danke und Gruss,
      Mathias

      1. Hi,

        Also Ursache kannst du diese Zeile ansehen:

        patterns[key]=value;

        Wenn ich mir das Objekt im Firefox per Firebug anschaue, verabschiedet sich der FF uebrigens auch mal eben in die Ewigen Jagdgruende ...

        Tatsächlich! Ich hatte isFinite(c) im Verdacht. Ein Microbench zeigt, dass die Zuweisung einer neuen Property in Opera ziemlich viel Zeit braucht.

        Der Vorschlag, das ganze gleich in der "richtigen" Form im Javascript-Code abzulegen, kam glaube ich den letzten Diskussionen zu deinem Script schon oefters.

        Kann man dadurch, wenn man das Script gzip-komprimiert ausliefert, nicht letztendlich vielleicht mehr Performance herausholen, als wenn man bei der Notation der Daten ein paar KB spart, und dafuer bei jedem neuen Seitenaufruf erneut die Datenstruktur aufwendig umformen muss ...?

        Ich muss später extrem schnell drauf zugreifen können und da ist die Hash-Tabelle des Object() genau richtig.

        Dann wuerde ich es wirklich gleich in dieser Notation ausliefern.
        Die paar KB, die du andernfalls einmalig (den gecached wird dein Script ja wohl) sparen kannst, machen den Aufwand der Umwandlung bei *jedem* Seitenaufruf offenbar nicht wett.

        MfG ChrisB

        1. Hi

          Kann man dadurch, wenn man das Script gzip-komprimiert ausliefert, nicht letztendlich vielleicht mehr Performance herausholen, als wenn man bei der Notation der Daten ein paar KB spart, und dafuer bei jedem neuen Seitenaufruf erneut die Datenstruktur aufwendig umformen muss ...?
          […]
          Die paar KB, die du andernfalls einmalig (den gecached wird dein Script ja wohl) sparen kannst, machen den Aufwand der Umwandlung bei *jedem* Seitenaufruf offenbar nicht wett.

          Meine Idee war, die Muster in der kompakten Form auszuliefern (spart immerhin 50%), sie dann vom Script konvertieren zu lassen und schliesslich (♫Zukunftsmusik♪) per DOM:Storage zu speichern.
          In älteren Versionen hatte ich die Auslieferung der kompakten Form schon mal drin, der Code war aber so schlecht, dass es langsamer war.
          Die neue Funktion (s.o.) wäre schnell genug.

          Ein weiterer Vorteil der kompakten Form ist, dass die Erzeugung und der Unterhalt der Trennmuster, die ja aus der LaTeX-Welt kommen, einfacher ist.

          Aber Opera scheint sich da zu sperren…

          Wünsche ein schönes Wochenende gehabt zu haben,
          Mathias

  2. Moin.

    Anscheinend braucht man ein Google-Konto, um neue 'Issues' zu Google-Code-Projekten hinzufügen zu können. Ich hoffe mal, es stört nicht allzu sehr, wenn ich also statt dessen hier poste...

    Die Funktion Hyphenator.addExceptions erwartet einen String mit Komma-separierten Werten, der dann ge-'split'-tet wird.

    Meiner Meinung nach eine elegantere und (weniger fehleranfällige) Alternative ist die Nutzung von des arguments-Objekts, d.h. (ungetestet):

      
    addExceptions: function() { //each word a new argument  
        for(var i=0, l=arguments.length; i<l; i++) {  
         var key=arguments[i].replace(/-/g,'');  
        if(!HYPHENATION[key]) {  
         HYPHENATION[key]=arguments[i];  
        }  
       }  
      }  
    
    

    Christoph

    1. Hai

      Anscheinend braucht man ein Google-Konto, um neue 'Issues' zu Google-Code-Projekten hinzufügen zu können. Ich hoffe mal, es stört nicht allzu sehr, wenn ich also statt dessen hier poste...

      Kein Problem ich trag's selber ein (http://code.google.com/p/hyphenator/issues/detail?id=16). Danke für dein Interesse!

      Meiner Meinung nach eine elegantere und (weniger fehleranfällige) Alternative ist die Nutzung von des arguments-Objekts

      Grundsätzlich hast du recht, weil dann auf das split(',') verzichtet werden kann. Aber:
      1. Gibt es eine Obergrenze für die Anzahl der Argumente? Das könnte allenfalls einschränken!
      2. Die Notation
      Hyphenator.addExceptions('An-alpha-be-ten','Gelb-rand','Ur-instinkt','Haus-esel','Kirsch-wein','Blu-men-topf-er-de');
      ist viel aufwändiger und somit auch wieder fehleranfällig als ein CSV (IMHO)
      Hyphenator.addExceptions('An-alpha-be-ten,Gelb-rand,Ur-instinkt,Haus-esel,Kirsch-wein,Blu-men-topf-er-de');

      Ich denke mal drüber nach!