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