Hello,

When working with RC under IE, I've noticed that displaying messages
obtained through HttpRequest (for example when doing sort by column),
It takes quite long time in comparison to other browsers to generate
the output. It's also pretty hard on resources.

After doing some investigation, I've found out that most resource
consuming operation is appendChild to tbody of message list in
message_list.insert_row.

When I looked up the issue and asked here and there, It came out
that appending elements to other element first and then doing
single append of that element to document DOM gives quite
a performance advantage under IE (not so noticeable in other
browsers). Here's a test that somebody pointed me to:

http://m8y.org/tmp/table.xhtml

I did a few alterations to message list generation code
and It actually gave positive results.

Unfortunately when doing row appends off DOM, there are
problems with accessing certain nodes (IE stops parsing
js on these attempts). So I had to use getElementsByTagName
in a certain situation which is visible in patch below.

The patch below is only for purpose of showing the problem and 
possible solution and it surely requires more work.
First part in php code contains also profiling code to show 
the difference.

The same method could be applied to other lists (contact list
for example).

You can comment out contents of prepare_message_list and
flush_message_list to see how long it takes in case of
former code.

In my case it came from above 7 seconds down to 1.2 second.

I'm interested in Your opinions on this.

There are still other significant performance problems under IE,
like hangups when unloading page. I will try to investigate that issue
too...

diff -ur roundcube/program/include/rcube_json_output.php 
roundcube_test/program/include/rcube_json_output.php
--- roundcube/program/include/rcube_json_output.php     2008-05-19 
13:19:16.000000000 +0200
+++ roundcube_test/program/include/rcube_json_output.php        2008-05-20 
17:53:28.427890048 +0200
@@ -213,14 +213,18 @@
     private function get_js_commands()
     {
         $out = '';
+       $out .= "timeslist = new Array();";        
        
+       $out .= "time1 = new Date();\n";        
        if (sizeof($this->env))
            $out .= 'this.set_env('.json_serialize($this->env).");\n";
-        
+       $out .= "time2 = new Date();\ntimeslist[timeslist.length] = (time2 - 
time1);\n";
+       $out .= "time1 = new Date();\n";        
         foreach($this->texts as $name => $text) {
             $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text));
         }
-
+       $out .= "time2 = new Date();\ntimeslist[timeslist.length] = (time2 - 
time1);\n";
+        $out .= "time1 = new Date();\n";       
         foreach ($this->commands as $i => $args) {
             $method = array_shift($args);
             foreach ($args as $i => $arg) {
@@ -232,8 +236,11 @@
                 preg_replace('/^parent\./', '', $method),
                 implode(',', $args)
             );
-        }
 
+        }
+       $out .= "time2 = new Date();\ntimeslist[timeslist.length] = (time2 - 
time1);\n";
+       
+       $out .= "times = '';\nfor (i=0; i < timeslist.length; i++) times = 
times+', '+timeslist[i];\nalert(times);\n";
         return $out;
     }
 }
diff -ur roundcube/program/js/app.js roundcube_test/program/js/app.js
--- roundcube/program/js/app.js 2008-05-19 13:19:53.000000000 +0200
+++ roundcube_test/program/js/app.js    2008-05-20 18:05:14.679523480 +0200
@@ -373,7 +373,7 @@
       }
 
     // set eventhandler to message icon
-    if ((row.icon = row.obj.cells[0].childNodes[0]) && 
row.icon.nodeName=='IMG')
+    if ((row.icon = 
row.obj.getElementsByTagName('TD')[0].getElementsByTagName('IMG')[0]))
       {
       var p = this;
       row.icon.id = 'msgicn_'+row.uid;
@@ -3227,13 +3227,31 @@
       }
   };
 
+  this.prepare_message_list = function()
+    {
+    this.message_list.init_off_list();
+    };
+
+  this.flush_message_list = function()
+    {
+    this.message_list.flush_off_list();
+    };
+
   // create a table row in the message list
   this.add_message_row = function(uid, cols, flags, attachment, attop)
     {
     if (!this.gui_objects.messagelist || !this.message_list)
       return false;
 
-    var tbody = this.gui_objects.messagelist.tBodies[0];
+    if (this.message_list.off_list)
+    {
+       var tbody = this.message_list.off_list;
+    }
+    else
+    {
+       var tbody = this.gui_objects.messagelist.tBodies[0];
+    }
+
     var rowcount = tbody.rows.length;
     var even = rowcount%2;
     
diff -ur roundcube/program/js/list.js roundcube_test/program/js/list.js
--- roundcube/program/js/list.js        2008-05-19 13:19:53.000000000 +0200
+++ roundcube_test/program/js/list.js   2008-05-20 17:02:33.975237432 +0200
@@ -28,6 +28,7 @@
   this.DELETE_KEY = 46;
   
   this.list = list ? list : null;
+  this.off_list = null
   this.frame = null;
   this.rows = [];
   this.selection = [];
@@ -145,13 +146,30 @@
   this.rows[uid] = null;
 },
 
+init_off_list: function()
+{
+  this.off_list = document.createElement('TBODY');
+},
+
+flush_off_list: function()
+{
+  this.list.replaceChild(this.off_list, this.list.tBodies[0]);
+  this.off_list = null;
+},
 
 /**
  *
  */
 insert_row: function(row, attop)
 {
-  var tbody = this.list.tBodies[0];
+  if (this.off_list)
+  {
+    var tbody = this.off_list;
+  }
+  else
+  {
+    var tbody = this.list.tBodies[0];
+  }
 
   if (attop && tbody.rows.length)
     tbody.insertBefore(row, tbody.firstChild);
diff -ur roundcube/program/steps/mail/func.inc 
roundcube_test/program/steps/mail/func.inc
--- roundcube/program/steps/mail/func.inc       2008-05-19 13:19:56.000000000 
+0200
+++ roundcube_test/program/steps/mail/func.inc  2008-05-20 16:46:58.855397256 
+0200
@@ -310,6 +310,8 @@
 
   $OUTPUT->command('set_message_coltypes', $a_show_cols);
 
+  $OUTPUT->command('prepare_message_list');
+  
   // loop through message headers
   foreach ($a_headers as $n => $header)
     {
@@ -355,6 +357,8 @@
       preg_match("/multipart\/m/i", $header->ctype),
       $insert_top);
     }
+    
+    $OUTPUT->command('flush_message_list');
   }
 
 


_______________________________________________
List info: http://lists.roundcube.net/dev/

Reply via email to