Optimizing DOMNode _nodeWith
I have some Obj-c code which steps through all of the nodes in the DOM. For a medium sized DOM (e.g news.google.com - just over 4000 nodes) this code takes over one tenth of a second on an 867MHz G4. A third of that time is down to the calls to hasLocalName inside of: +(DOMNode *) _nodeWith:(Node* *) e.g. HTMLElement* htmlElt = static_cast<HTMLElement*>(impl); if (htmlElt->hasLocalName(htmlTag)) wrapperClass = [DOMHTMLHtmlElement class]; else if (htmlElt->hasLocalName(headTag)) etc etc Now there is already a comment there that says: // FIXME: We could make the HTML classes hand back their class names and then use that to make // the appropriate Obj-C class from the string. I am guessing that this would go something like this, but before I go to the trouble of doing this for every class could someone make sure I am pondering the right thing. e.g For each element type: String HTMLElement::objcClassName() const { return String("DOMHTMLElement"); } String HTMLDivElement::objcClassName() const { return String("DOMHTMLDivElement"); } etc.. and then replace the all those tests in _nodeWith with: if (impl->isHTMLElement()) { // FIXME: Reflect marquee once the API has been determined. HTMLElement* htmlElt = static_cast<HTMLElement*>(impl); String className(htmlElt->objcClassName()); NSString* asNSString = ?? How do I convert a String to an NSString? wrapperClass = NSClassFromString(asNSString); } Does this all make sense? Matt Gough
On Apr 24, 2006, at 8:19 AM, Matt Gough wrote:
Now there is already a comment there that says:
// FIXME: We could make the HTML classes hand back their class names and then use that to make // the appropriate Obj-C class from the string.
I am guessing that this would go something like this, but before I go to the trouble of doing this for every class could someone make sure I am pondering the right thing.
Yes, this is the approach mentioned in the comment.
if (impl->isHTMLElement()) { HTMLElement* htmlElt = static_cast<HTMLElement*> (impl); wrapperClass = NSClassFromString(htmlElt->objcClassName()); }
You do not need to do any explicit conversion to NSString, you can simply pass it around as if it was a NSString. You can due this because String has a cast operator for NSString (operator NSString*()) —C++ will do the conversion behind the scenes.
Does this all make sense?
Yes, this makes sense to me. Others, like Maciej, might have a new opinion since that comment was written a long time ago. I would like to see before and after numbers when you have everything changed over. — Timothy Hatcher
To me it seems wrong that the internal DOM would have to know about the class naming scheme in a particular binding. A better approach might be just to grab the tag name and swizzle it according to the binding's class naming convention. Something like this: HTMLElement* htmlElt = static_cast<HTMLElement*>(impl); String tagName = htmlElt->tagName(); String className = "DOMHTML" + tagName + "Element"; That wouldn't be exactly right because of capitalization, but it illustrates the general idea. Geoff
On 24 Apr 2006, at 19:39, Geoffrey Garen wrote:
To me it seems wrong that the internal DOM would have to know about the class naming scheme in a particular binding. A better approach might be just to grab the tag name and swizzle it according to the binding's class naming convention. Something like this:
HTMLElement* htmlElt = static_cast<HTMLElement*>(impl); String tagName = htmlElt->tagName(); String className = "DOMHTML" + tagName + "Element";
That wouldn't be exactly right because of capitalization, but it illustrates the general idea.
I thought of that too, but as you say, the Capitalisation is not consistent enough for a generic tagName to Obj-c class name. It would also require the className to be built up for each node. Not a great hit I know, but still slower than getting a constant string from my objcClassName proposal. Also, (AFAIK) some tags do not have an equivalent class in the internal DOM (e.g H1 - H6) and TBODY, THEAD and TFOOT. These would need special casing. Other solutions I have been thinking about are: 1. Have an enum for all the HTML tags and have a method that returns this enum for each element kind. Then have a simple switch statement to map the enum to ClassName. This enum might then have other uses for when the element type needs knowing 'quickly'. 2. Have a HashMap (or NSDictionary) that maps the tagName to the ClassName. Any other suggestions would be welcome Matt
On Apr 24, 2006, at 11:24 AM, Timothy Hatcher wrote:
Does this all make sense?
Yes, this makes sense to me. Others, like Maciej, might have a new opinion since that comment was written a long time ago. I would like to see before and after numbers when you have everything changed over.
I think a better approach would be to make a hash table of function pointers, that will be faster than the log chain of if's. This is what is used to generate the elements in the first place. Regards, Maciej
participants (4)
-
Geoffrey Garen
-
Maciej Stachowiak
-
Matt Gough
-
Timothy Hatcher