Is there any difference in performance between the conditional operator ===
and the assignment operator =
? I am writing some pre-save hook middleware in mongoose and I am wondering if there is much of a speed difference between:
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
this.crm.isUpToDate = false;
next();
});
and
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
if (this.crm.update === true) {
this.crm.isUpToDate = false;
}
next();
});
Here is what I am doing:
I have a mongoose pre-save middleware hook (for a mongo database) where the hook gets run every time a document is saved. At the point of save I check if the document was updated. If it was I set the crmIsUpToDate
to false. The crmIsUpToDate
will get set to true when a cron job gets. This hook can be run many times before the cron job gets to the document.
When you have a non-refcounting language (which JavaScript isn't) and doing an assignment ('=', resulting in a copy operation) of a big object it can be "slow". So a check if that copy operation is really necessary can save you a significant amount of time.
But JavaScript is a native refcounting language:
object1 = {a: 1, b: 2};
object2 = object1; // refcounting copy?
object1.a = 3; // test by modifying the first object
console.log( object2.a ); // will return 3 => refcounting
=> so all assignment operations ('=') are quite cheap.
And, even more, you are working with a native data type (bool, numbers would be the same) that might be even faster or at least as quick as objects.
NOTE: strings are not refcounted in JavaScript, they are an exception in this case.
So, right now we have learned that the assignment is cheap. But what about the identity check (the '===')?
In your code you must wind your way down through the object this
-> crm
-> update
- this takes some additional time. And then the identicality of the type (bool) must be checked and then if the content (false) is the same.
All of this are adding conditions in the program flow where modern CPUs with their long pipelines might guess the branch wrongly creating a stall and a reload of the full pipeline. This also wastes quite a lot of CPU cycles (although the modern CPUs are quite good at this now).
=> This comparison ('===') is quite expensive.
Conclusion #1:
You shouldn't protect a cheap code by an expensive test that can be easily avoided.
When the code gets more expensive a point will come where the test will save time at the end. This leads to:
Conclusion #2:
Premature optimisation is evil! It can make code harder to read, introduce new bugs, makes code bigger (also bad for cache efficiency), ...
=> Only optimize those parts of the code where you are sure you are running in a performance problem - and then only based on profiling informations. Humans are quite bad at guessing the effects here...