On Feb 6, 9:00 pm, RobG <[email protected]> wrote:
> On Feb 7, 12:21 am, kangax <[email protected]> wrote:
[snip]
> > I'm pretty sure property lookup is faster than regexp in Javascript
> > too.
>
> It doesn't take much to test. Using a set of 1,000 values and looping
> through 10,000 lookups took about 45ms in Firefox on a laptop with a
> 1GHz processor regardless of which method was used. The regular
> expression version was generally faster in Safari, however both were
> still generally less than 45ms.
That's strange. My results show that lookup is consistently faster,
although the difference obviously varies across browsers. Opera (9.61)
is almost 3(!!!) times slower with regexp than it is with a property
lookup - 153ms. vs 54ms. (for 20000 iterations)
The full test page is a bit too big to include it here (as I also
tested alternative versions - plain string comparison, property lookup
with `toUpperCase` and without it, checking tagName case at the time
of function declaration and so skipping case conversion at run time),
but I can include it if anyone finds it interesting. The 3 most
relevant tests were:
var regexp = (function(){
var re = /^(html|body)$/i;
return function(element) {
return re.test(element.tagName);
}
})();
// HTML only
var lookupHTML = (function(){
var hTable = { HTML: true, BODY: true };
return function(element) {
return hTable[element.tagName] === true;
}
})();
// with (X)HTML support
var lookupXHTML = (function(){
var hTable = { HTML: true, BODY: true };
return function(element) {
return hTable[element.tagName.toUpperCase()] === true;
}
})();
>
> The biggest hit to performance is forming the object, either a
> delimited string or JSON that can be converted to an object.
I'm not sure what you mean by "forming" an object. Are you talking
about an (likely) increased memory consumption. The creation (of a
"hash table", if we can call it that way) can only be done once
instead of every time function runs.
>
> The bottom line is that performance is an insignificant criterion in
> this case.
Perhaps, although Opera's 3x difference looks somewhat disturbing.
>
> > The only downside to this approach is that there's no reliable
> > (native) "hash" structure in Javascript.
>
> Some would argue that there is no Hash at all, but there are objects
> that can be made to behave a bit like Hashes in other languages. :-)
That's why I wrapped hash in quotes and made it lowercase - as in
"hash" : )
>
> > There also needs to be a
> > boolean type conversion in your example, so that the function
> > consistently returns either `true` or `false` (and not, say,
> > `undefined` - for missing members).
>
> A "falsey" or not true value may be sufficient, but since the value of
> the object property is only used for comparison, it may as well be
> boolean true. It could just as easily be 1 or 'hey' or any non-falsey
> value if it served some other purpose.
Somehow *just* falsy/truthy return values seem sloppy to me. It
doesn't take much effort to prepend result with `!!` and document
function's return value as that of type Boolean.
>
> Overloading of the property value might be seen as a good thing - or
> not. It isn't possible with the regular expression method (well, it
> is possible but requires more logic such as a comparison function but
> that is getting well away from the intention of the OP). That might
> be seen as a better thing.
>
> > Regular property lookup is
> > unreliable in such way that it takes object's prototype chain into
> > account; That means there could be a conflict with
> > `Object.prototype.*` properties - e.g.: `isValid('toString')` would
> > return `Object.prototype.toString` which is a Function object and just
> > like any object - type converts to `true` : )
>
> The general issue is discovery of property names on the inheritance
> chain that match tested values. Adding a "hasOwnProperty" doesn't
> slow performance much (not noticeable in either browser I tested) and
> logically may speed it up - it's an extra function call but doesn't
> search the [[prototype]] chain.
Good point. I just remember something about `call` (that we would
probably want to use in this case) being slower than a regular
function call.
>
> > In more generic method,
> > it would probably be a good idea to use
> > `Object.prototype.hasOwnProperty`, but in this case, strict equality
> > operator would do:
>
> > var isValid = (function(){
> > var hTable = { "V3000": true, "B47242": true, "V54000": true }
> > return function(value) {
> > return hTable[value] === true;
> > // return Object.prototype.hasOwnProperty.call(hTable, value);
> > }
>
> > })();
>
> Given that the difference in performance is negligible[1], a more
> important criterion is the difference between generating a delimited
> string (something most databases are very good at) compared to a JSON
> object (which only some are good at and is more complex in general).
>
> Compare generating the JSON string:
>
> '{ "V3000": true, "B47242": true, "V54000": true }'
>
> to the delimited string:
>
> "V3000 B47242 V54000"
>
> I know which one is simpler to generate and debug - of course the OP
> is free to choose.
Agreed. Regexp version is definitely clearer and more maintainable. We
can probably agree that it's only wise to apply lookup technique in
performance critical parts of an application : )
--
kangax
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---