JS document.xxx is really slow

Koos Vriezen koos.vriezen at xs4all.nl
Fri Nov 15 23:35:19 GMT 2002


Hi,

When I inject some JS in a page like slashdot.org, like

dcop konqueror-21436 html-widget1 evalJS '
var startTime,endTime;
startTime=new Date().getTime();
document.myvar = 0;
for(n=0;n<8000;n++)
  document.myvar++;
endTime=new Date().getTime();
alert("Elapsed time using "+((endTime-startTime)/1000)+" seconds.");'

I get a time of 3.7 on a P4 2.4 GHz. One of the causes is that the DOM
tree is search three times for each document.xxx,
document.images/forms/applets (used to be document.all which was three
times faster).
I've attached a patch that makes it an one times scan again. It also
caches the node in case one is found. With it the time is 1.8 seconds,
that's about twice as fast.
Note, this patch does change preference for applets before frames (which
was the other way around) but can be changed easily if needed.

Regards,

Koos
-------------- next part --------------
Index: ecma/kjs_html.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/ecma/kjs_html.cpp,v
retrieving revision 1.217
diff -u -3 -p -r1.217 kjs_html.cpp
--- ecma/kjs_html.cpp	2002/11/14 15:44:12	1.217
+++ ecma/kjs_html.cpp	2002/11/15 23:13:08
@@ -188,6 +188,37 @@ bool KJS::HTMLDocument::hasProperty(Exec
   return DOMDocument::hasProperty(exec, propertyName);
 }
 
+class NamedTagLengthDeterminer {
+public:
+  struct TagLength {
+    NodeImpl::Id id; unsigned long length; NodeImpl *last;
+  };
+  NamedTagLengthDeterminer(NodeImpl *s, const DOMString& n, TagLength *t, int l)
+    : name(n), tags(t), length(l) {
+      determineNamedTagLength(s);
+  }
+private:
+  const DOMString& name;
+  TagLength *tags;
+  int length;
+  void determineNamedTagLength(NodeImpl *start);
+
+};
+
+void NamedTagLengthDeterminer::determineNamedTagLength(NodeImpl *start) {
+  for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling())
+    if ( n->nodeType() == Node::ELEMENT_NODE ) {
+      for (int i = 0; i < length; i++)
+        if (n->id() == tags[i].id &&
+            static_cast<ElementImpl *>(n)->getAttribute(ATTR_NAME) == name) {
+          tags[i].length++;
+          tags[i].last = n;
+          break;
+        }
+      determineNamedTagLength(n);
+    }
+}
+
 Value KJS::HTMLDocument::tryGet(ExecState *exec, const UString &propertyName) const
 {
 #ifdef KJS_VERBOSE
@@ -201,6 +232,18 @@ Value KJS::HTMLDocument::tryGet(ExecStat
   if ( !win || !win->isSafeScript(exec) )
     return Undefined();
 
+
+  NamedTagLengthDeterminer::TagLength tags[3] = {
+    {ID_IMG, 0, 0L}, {ID_FORM, 0, 0L}, {ID_APPLET, 0, 0L} 
+  };
+  NamedTagLengthDeterminer(doc.handle(), propertyName.string(), tags, 3);
+  for (int i = 0; i < 3; i++)
+    if (tags[i].length > 0) {
+      if (tags[i].length == 1)
+        return getDOMNode(exec, tags[i].last);
+      return getDOMNodeList(exec, DOM::NodeList(new DOM::NamedTagNodeListImpl(doc.handle(), tags[i].id, propertyName.string())));
+    }
+/* 
   // Check for images with name==propertyName, return item or list if found
   // We don't use the images collection because it looks for id=p and name=p, we only want name=p
   DOM::NodeList list( new DOM::NamedTagNodeListImpl( doc.handle(), ID_IMG, propertyName.string() ) );
@@ -238,7 +281,7 @@ Value KJS::HTMLDocument::tryGet(ExecStat
     // Get all the items with the same name
     return getDOMNodeList( exec, list );
   }
-
+*/
   // Check for frames/iframes with name==propertyName
   if ( view && view->part() )
   {
@@ -248,7 +291,7 @@ Value KJS::HTMLDocument::tryGet(ExecStat
     if (kp)
       return Value(Window::retrieve(kp));
   }
-
+/*
   // Check for applets with name==propertyName, return item or list if found
   list = new DOM::NamedTagNodeListImpl( doc.handle(), ID_APPLET, propertyName.string() );
   len = list.length();
@@ -256,8 +299,8 @@ Value KJS::HTMLDocument::tryGet(ExecStat
     return getDOMNode( exec, list.item( 0 ) );
   else if ( len > 1 )
     return getDOMNodeList( exec, list );
-
 
+*/
   const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
   if (entry) {
     switch (entry->value) {


More information about the kfm-devel mailing list