Object.constructor() vs Presence of Join in terms of performance - javascript

I've been reading this thread to check if argument is Array or String
Check if object is array?
The solution mentioned is:
function isArray(obj){
return !!obj && Array === obj.constructor;
}
But I've written the following function
function isArray(obj) {
return obj.join;
}
I've done some sample test. I'm finding array.join() returns faster result than object.constructor(). Am I missing something?
I thought Object.constructor() is the parent class hence faster, but I'm able to return faster results using obj.split. Does it mean the answer in the other SO post was incorrect?
Jsfiddle:
https://jsfiddle.net/vdpseotp/6/
Please explain.

The approach of using obj.join is sometimes called "duck-typing". Using join as you propose will fail miserably if you use it on an object which happens to contain a join property.
Just use the APIs which are designed for the task, such as Array.isArray, or a routine from a utility library. They have already thought through all of the issues. For example, Underscore uses Object.prototype.toString.call(obj) === '[object Array]'. There is also an extensive literature right here on SO on the topic, starting with the one you mention.
The more basic question is, why do you have things and don't know whether they are arrays or not? Perhaps some utility routines for traversing arbitrary objects might need to check for array-ness, or a server might send down something that might or might not be an array, but a well designed user-program should already know which objects are what. To put it a different way, if you were ever to move to a typed approach such as TypeScript, what type would you propose to assign to these maybe-an-array-maybe-not objects? Would you use any, which sort of defeats the whole purpose?
The second question is, why are you obsessing over a few microseconds? Do you have a game which is recalculating the position of hundreds of thousands of objects, sixty times per second? If not, it doesn't matter. If it does matter, see previous paragraph, and refactor your code so as not to have to check for something being an array all the time.
By the way, a meaningful benchmark should be run a million times. FWIW, console.time[End] often comes in handy for quick-and-dirty benchmarks. Anyway, according to your fiddle, the time difference is nothing more than a factor 1.5 or so at worst.
Minor note: Array === obj.constructor is not going to play well with subclasses of Array.

Related

Performance difference between lodash "get" and "if else" clauses

Let's say you have a typescript object, where any element can be undefined. If you want to access a heavily nested component, you have to do a lot of comparisons against undefined.
I wanted to compare two ways of doing this in terms of performance: regular if-else comparisons and the lodash function get.
I have found this beautiful tool called jsben were you can benchmark different pieces of js code. However, I fail to interpret the results correctly.
In this test, lodash get seems to be slightly faster. However, if I define my variable in the Setup block (as opposed to the Boilerplate code), the if-else code is faster by a wide margin.
What is the proper way of benchmarking all this?
How should I interpret the results?
Is get so much slower that you can make argument in favour of if-else clauses, in spite of the very poor readability?
I think you're asking the wrong question.
First of all, if you're going to do performance micro-optimization (as opposed to, say, algorithmic optimization), you should really know whether the code in question is a bottleneck in your system. Fix the worst bottlenecks until your performance is fine, then stop worrying overmuch about it. I'd be quite surprised if variation between these ever amounted to more than a rounding error in a serious application. But I've been surprised before; hence the need to test.
Then, when it comes to the actual optimization, the two implementations are only slightly different in speed, in either configuration. But if you want to test the deep access to your object, it looks as though the second one is the correct way to think about it. It doesn't seem as though it should make much difference in relative speeds, but the first one puts the initialization code where it will be "executed before every block and is part of the benchmark." The second one puts it where "it will be run before every test, and is not part of the benchmark." Since you want to compare data access and not data initialization, this seems more appropriate.
Given this, there seems to be a very slight performance advantage to the families && families.Trump && families.Trump.members && ... technique. (Note: no ifs or elses in sight here!)
But is it worth it? I would say not. The code is much, much uglier. I would not add a library such as lodash (or my favorite, Ramda) just to use a function as simple as this, but if I was already using lodash I wouldn't hesitate to use the simpler code here. And I might import one from lodash or Ramda, or simply write my own otherwise, as it's fairly simple code.
That native code is going to be faster than more generic library code shouldn't be a surprise. It doesn't always happen, as sometimes libraries get to take shortcuts that the native engine cannot, but it's likely the norm. The reason to use these libraries rarely has to do with performance, but with writing more expressive code. Here the lodash version wins, hands-down.
What is the proper way of benchmarking all this?
Only benchmark the actual code you are comparing, move as much as possible outside of the tested block. Run every of the two pieces a few (hundred) thousand times, to average out the influence of other parts.
How should I interpret the results?
1) check if they are valid:
Do the results fit your expectation?
If not, could there be a cause for that?
Does the testcase replicate your actual usecase?
2) check if the result is relevant:
How does the time it takes compare to the actual time in your usecase? If your code takes 200ms to load, and both tests run in under ~1ms, your result doesnt matter. If you however try to optimize code that runs 60 times per second, 1ms is already a lot.
3) check if the result is worth the work
Often you have to do a lot of refactoring, or you have to type a lot, does the performance gain outweight the time you invest?
Is get so much slower that you can make argument in favour of if-else clauses, in spite of the very poor readability?
I'd say no. use _.get (unless you are planning to run that a few hundred times per second).

Javascript forcing array to behave like array

Javascript arrays used to be just objects with some special syntax, but JIT engines can optimize the array to behave like a true array with O(1) access rather than O(log n) access. I am currently writing a cpu intensive loop where I need to a certain I get O(1) access rather than O(log n). But the problem is that I may need to do array [5231] = obj1 right after its created but the array will eventually be filled. I am worried that such behaviour may trick the JIT to thinking that I am using it as a sparse array and thus I wouldnt get O(1) access time I require. My question is that is there ways I can tell or at least hint the javascript engine that I want a true array?
In particular, do I need to initialize the array with values first? Like fill all of it with reference to a dummy object (my array will only contain references to objects of same prototype or undefined). Would just set the array.length = 6000 be enough?
EDIT: based on http://jsperf.com/sparse-array-v-true-array, it seems filling the array beforehand is a good idea.
I realized I have made a big derp on my profiling test because it is an animation program with varying frame rate and my profiling was focused on detecting where the cpu intensive parts are. It was not suitable in comparing between the two methods as one method would simply run slower but the relative cpu time between different function calls would be the same.
Anyhow, I wrote a test on jspref: http://jsperf.com/sparse-array-v-true-array and (unless I made an error , which so, please do correct me!) A randomly accessed array without filling it first runs twice slower in Chrome and Firefox compared to filled version. So it seems that it is a good idea to fill it in first if you are writing things like a spatial hashmap.

Detecting changes in a complex object

I'm writing a compiler in JavaScript, and for the optimizer I'm following the usual pattern where a list of optimizations is run repeatedly until nothing happens. The obvious way to detect the 'nothing happens' condition is to have each optimization set a flag if it successfully does something. I'm wondering if there's a more elegant way to go about it.
In the abstract, the problem can be phrased like this: given a complex object (with many levels of subobjects including arrays with circular references etc.), run it through a possible transformation then detect whether anything has changed. So the question is whether there is a simple way to detect changes in a complex object.
Watch.js provides ways to detect changes in an object, but only at top level, and will trigger if a field is changed even if it is subsequently returned to its original value.
Another approach would be to make a deep copy of the object and then deep compare with the original. However, from other questions here, deep copy looks like a nontrivial operation and deep compare has challenges of its own.
Is there an elegant trick I'm missing, or should I just stick to letting each optimization pass do its own bit of bookkeeping?
I would just post this as a comment, but I don't have the required rep.
I don't know if this would work in your situation, but what you could do is convert to JSON, then compare the strings:
JSON.stringify(firstObject) === JSON.stringify(secondObject)
Was looking around a bit more, and found another stackoverflow post with a similar question. There is a solution similar to mine, but what I found most interesting was the second solution, not chosen as the answer, I think it has what you need: Object comparison in JavaScript

Why check against a prototype rather than the instance?

I was just reading this answer regarding hashing in Javascript, and, while it was definitely faster than the accepted answer, it requires the reduce function on the Array prototype.
Checking the existence of the reduce function is easy enough; but while most checks I do (and have seen) check against the prototype, it just made me wonder: what are the implications of checking against an instance itself? Why does the prototype check seem to be preferred?
// i.e.
if (!!Array.prototype.reduce) { }
// vs
if (!![].reduce)
The instance will definitely need an instance, so that's one thing, but is that it?
Just ran a benchmark: http://jsperf.com/prototype-vs-instance-property-check
Array.prototype.reduce is 3x faster due to the instantiation of an empty array, but realistically, there is absolutely no difference since these checks are almost always one-time checks, and not in code that runs all the time.
I personally have reduced this to [].method for years. I do the same for things like Array.prototype.slice.call( .. ) vs [].slice.call( ... ), and those are called far more often than once.
But note that this is only valid on Array, so you're really not saving a lot.
The second version involves needlessly instantiating an empty array. Why do so, when you can just ask the prototype itself and not instantiate anything?

Under what conditions do chained jQuery objects offer performance gains?

I'm working with some code that adds and removes various CSS classes on the same object. The code looks something like:
function switch_states(object_to_change) {
if(object_to_change.hasClass('ready') {
object_to_change.removeClass('ready');
object_to_change.addClass('not_ready');
} else {
object_to_change.removeClass('not_ready');
object_to_change.addClass('ready');
}
}
I suspect I might be able get away with chaining these two snippits into something like object_to_change.removeClass('ready').addClass('not_ready'); But I have to wonder: besides legibility and the neato factor, does this give me any performance gains?
My question: Would a chained objects do their work any faster than two non-chained ones? If so, why? If not, at what point does using chained objects become more efficient than disparate ones -- i.e. under what conditions do chained jQuery objects offer performance gains?
Would a chained objects do their work any faster than two non-chained ones? If so, why?
Chained objects are faster when they start with a selector, and chaining prevents the selector being run against the DOM multiple times (a comparatively expensive operation).
Slower:
$(".myClass").val(123);
$(".myClass").addClass("newClass");
Faster:
$(".myClass")
.val(123)
.addClass("newClass");
Caching the selector in a variable has the same benefits as chaining (i.e. preventing expensive DOM lookups):
var $selctor = $(".myClass");
$selector.val(123);
$selector.addClass("newClass");
In your example, the answer is no. However what chaining does is give you the ability to not declare variables in places where you can just use the chain (and current stack of elements) to perform various tasks.
I would recommend using chaining with newlines - this has become somewhat of a jQuery convention.
Well, you can't really chain an if() statement, but jQuery has a toggleClass() method that would seem appropriate here:
object_to_change.toggleClass('ready not_ready');
This removes the need for chaining vs separate calls in the first place. I don't know how it compares in terms of performance. Would need to test.
EDIT: I should note that the solution above implies that the object already has one or the other. If not, another approach would be to pass a function to toggleClass.
object_to_remove.toggleClass(function( i, cls ) {
return cls.indexOf( 'ready' ) == -1 ? 'ready' : 'ready not_ready';
});
No performance gains here: it's the same object. Just the neato factor, which should not be underestimated.
The most obvious performance gain is in development and maintenance. If the code is clean, readable, and intent is apparent -- developer time should be reduced.
While this needs to be balanced against code performance, if there is a tested, measurable difference, then optimize for speed. If at all possible, without reducing the readability of the code.
If readability/maintainability of the code will be impacted, look to see if the optimizations can be automated as part of the build process, to keep the maintainable code for further development.

Categories