Is writing your own parser worth the extra runtime it causes? - javascript

I am doing work involving a lot of DOM manipulation. I wrote a function to more efficiently change common styles on objects using "hotkeys". It simply interprets this:
styles = parseStyles({p:"absolute",l:"100px",t:"20px",bg:"#CC0000"});
as this:
styles = {position:"absolute",left:"100px",top:"20px",background:"#CC0000"};
This came about mainly to save me from having to read so much, and because I wanted to see if I could do it :) (as well as file sizes). I find these hotkeys easier to look at; I am setting and resetting styles dozens of times for different custom DOM objects.
But, is having a bottleneck like this going to be a significant burden on performance and runtime if my page is using it up to 5,000 times in a session, about 10-25 executions at a time?
function parseStyles(toParse){
var stylesKey =
{h:"height",p:"position",l:"left",t:"top",r:"right",b:"bottom",bg:"background"},
parsedStyles = {};
for (entry in toParse){
if (entry in stylesKey){
parsedStyles[stylesKey[entry]] = toParse[entry];
} else {
parsedStyles[entry] = toParse[entry];
}
}
return parsedStyles;
}

I find that setting non-computed styles is rarely ever needed any more. If you know the styles ahead of time, define a class for that in your CSS and addClass or removeClass from the necessary objects. Your code is a lot more maintainable and all style-specific info is in your CSS files rather than your Javascript files. Pretty much, the only time I set formatting-style info directly on an object anymore is when I'm using computed positions with absolute positioning and even then, if I rack my brain hard enough, the positioning problem can usually be solved with plain CSS/HTML.
The examples you cite in your question look like static styles which could all be done with a CSS rule and simply doing addClass to an object. Besides being cleaner, it should be a lot faster to execute too.
It looks like what you're doing is using run-time parsing in order to save development-time typing. That's fine if you don't notice the performance difference. Only you can know that for sure because only you can test your app in the environments that you need it to run (old browser, old CPU, stress usage). We can't answer that for you. It would certainly be faster not to be doing run-time conversion for something that is known at development time. Whether that speed difference is relevant depends upon a lot of details and app requirements you haven't disclosed (and may not have even seriously thought about) and could only be figured out with configuration testing.
If it were me and I had any thoughts that maybe I was calling this so much that it might impact performance, I'd find it a lot less work to do a little extra typing (or search and replace) and not have to test the potential performance issues.

Memoize your parsing function.
The simple fact is, that over some finite area of time, the number of actual styles, or full style strings that you will process will likely be quite small, and will also, likely, have a reasonable amount of duplication.
So, when you go to parse a style expression, you can do something simple like store the expression in a map, and check if you've seen it before. If you have, return the result that you got before.
This will save you quite a bit of time when reuse is involved, and likely not cost you much time when it's not.

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).

Any linter to warn about side-effects in JavaScript?

With the flexibility of JavaScript, we can write code full of side-effects, or just purely functional.
I have been interested in functional JavaScript, and wanting to start a project in this paradigm. And a linter about that can surely help me gathering good practices. Is there any linter to enforce pure functional and side-effect free style?
Purity Analysis is equivalent to Solving the Halting Problem, so any kind of static analysis that can determine whether code is pure or impure is impossible in the general case. There will always be infinitely many programs for which it is undecidable whether or not they are pure; some of those programs will be pure, some impure.
Now, you deliberately used the term "linter" instead of static analyzer (although of course a linter is just a static analyzer), which seems to imply that you are fine with an approximate heuristic result. You can have a linter that will sometimes tell you that your code is pure, sometimes tell you that your code is impure, and most times tell you that it cannot decide whether your code is pure or impure. And you can have a whitelist of operations that are known to be pure (e.g. adding two Numbers using the + operator), and a blacklist of operations that are known to be impure (e.g. anything that can throw an exception, any sort of loops, if statements, Array.prototype.forEach) and do a heuristic scan for those.
But in the end, the results will be too unreliable to do anything serious with them.
I haven't used this myself but I found this plugin for ESLint: https://github.com/jfmengels/eslint-plugin-fp
You cannot use JS commpletely without side effects. Every DOM-access is a side effect, and we could have an argument wether the whole global namespace may also fall under that definition.
The best you can do is, stay reasonable. I'm splitting this logically into two groups:
the work horses (utilities): their purpose is to take some data and to process it somehow. These are (mostly) side effects free. mostly, because somethimes these functions need some state, like a counter or a cache, wich could be argued to be a side effect, but since this is isolated/enclosed into these functions I don't really care. like the functions that you pass to Array#map() or to a promises then(), and similar places.
and the management: these functions rarely do some data-processing on their own, they mostly orchestrate the data flow, from whereever it is created, to whatever processing(-utilities) it has to be run, up to where it ends, like modifying the DOM, or mutating an object.
var theOnesINeed = compose(...);
var theOtherOnesINeed = compose(...);
var intoADifferentFormat = function(value){ return ... }
function(event){
var a = someList.filter(theOnesINeed).map(intoADifferentFormat);
var b = someOtherList.filter(theOtherOnesINeed);
var rows = a.concat(b).map(wrap('<li>', '</li>'));
document.querySelector('#youYesYou').innerHTML = rows.join('\n');
}
so that all functions stay as short and simple as possible. And don't be afraid of descriptive names (not like these way to general ones :))

Validate JavaScript code without enforcing a specific style

I would like to validate some JavaScript code for syntactic correctness, but without enforcing a specific coding-style to the user.
My first approach was to use esvalidate that comes included with esprima. This does the job partially, as it detects unexpected tokens, such as:
constx foo = {};
What it does not detect is among other things usage of variables that have never been declared, such as:
const foox = {
bar() {}
};
foo.bar();
A tool such as eslint would detect this, but it's very difficult to configure ESLint in a way that no specific style is enforced to the user (I don't say it's not possible, I just say it's a huge amount of work since you need to check every single rule and decide whether to enable or disable it, and with hundreds of rules this is… yes, well, a huge amount of work).
What other options do I have? How could I validate the code without this effort?
By the way: What is it that I want to validate here? It's not the syntax (I mean, syntactically, everything is fine, it just does not make sense), but it's also not the semantics. What would be the correct term for this type of checks?
Years ago Linters were only there to check the style of your code. Nowadays they do more, a lot more. Even static analysis. ESLint is such a powerful tool and IMHO it is exactly what you're looking for.
You may think the initial configuration may be costly, but as the ESLint page says:
No rules are enabled by default.
Besides, having a consistent coding style across your time is very beneficial and if you and your team found a common basline you can share the .eslintrc between projects.
Enabling the no-undef rule and using a plugin for your IDE, like one of those should solve your issue -> static code analysis at development time :)
To answer your last question, I think that what you want is static analysis. This will be harder with JavaScript in general because of its dynamic nature and lack of types, and relative lack of maturity in tooling. Decades of work have gone into writing static analyzers for C, for example, and that work won't immediately carry over into others languages.
Something like jshint may be what you want because its goal is to help developers "write complex programs without worrying about typos and language gotchas".
Hope this helps!
ESLint Recommended set: Recommended rules have checkmark next to them do not include any stylistic rules. You can use that to verify validity of the script without enforcing any specific style. At the very least it's a good starting point, and you can always turn off the rules you don't like.

Javascript single use variable declaration

This may be a obvious question, but I was wondering if there was an efficiency difference between declaring something in a one time use variable or simply executing the code once (rather then storing it then using it). For example
var rowId = 3,
updateStuff(rowId);
VS
updateStuff(3);
I think that worrying about performance in this instance is largely irrelevant. These sorts of micro-optimizations don't really buy you all that much. In my opinion, the readability of the code here is more important, since it's better to identify the 3 as rowId than leaving it as a magic number.
If you are really concerned about optimization, minimizing your code with something like Google Closure would help; it has many tools that will help you make your code more efficient.
If you were using google closure to compile and if you annotated the var as a constant (as it appears in your example), I suspect the compiler would remove the constant and replace it with the literal.
My advice is to pick the readable option and if you really need the micro-optimizations and reduction in source size, use the google closure compiler or a minifier-- a tool is more likeley to accumulate enough micro-optimizations to make something noticeably faster, although I'd guess most of the saved milliseconds would come from reduced network time from minification.
And var declarations do take time and if you added that var to the global namespace, then there is one more thing that will be searched during resolving names.
With a modern browser that compiles your code, the generated code will be exactly the same unless the variable is referenced somewhere else also.
Even with an old browser if there is a difference it won't be something to worry about.
EDIT:
delete does not apply to non-objects, therefore my initial response was wrong. Furtermore since the variable rowId is declared with the flag var it will be cleaned up by the garbage collection. Was it on the other hand defined without, it would live for the duration of the page / application.
source: http://lostechies.com/derickbailey/2012/03/19/backbone-js-and-javascript-garbage-collection/
The variable rowId will be kept in memory and will not be released by the garbage collector since it's referenced to. Unless you release it afterwards like below it will be there till the end of the programs life. Also remember it take time to create the variable (minimal, but you asked)
var rowId = 3
updateStuff(rowId);
delete rowId
With efficiency in mind, then yes there is a difference. Your second example is the quickest and doesn't spend any extra resources.
OBS. Some languages do optimize code as such and simply remove the sequence, but I strongly doubt that JavaScript does so.

JavaScript - What Level of Code Optimization can one expect?

So, I am fairly new to JavaScript coding, though not new to coding in general. When writing source code I generally have in mind the environment my code will run in (e.g. a virtual machine of some sort) - and with it the level of code optimization one can expect. (1)
In Java for example, I might write something like this,
Foo foo = FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42);
blub.doSomethingImportantWithAFooObject(foo);
even if the foo object only used at this very location (thus introducing an needless variable declaration). Firstly it is my opinion that the code above is way better readable than the inlined version
blub.doSomethingImportantWithAFooObject(FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42));
and secondly I know that Java compiler code optimization will take care of this anyway, i.e. the actual Java VM code will end up being inlined - so performance wise, there is no diffence between the two. (2)
Now to my actual Question:
What Level of Code Optimization can I expect in JavaScript in general?
I assume this depends on the JavaScript engine - but as my code will end up running in many different browsers lets just assume the worst and look at the worst case. Can I expect a moderate level of code optimization? What are some cases I still have to worry about?
(1) I do realize that finding good/the best algorithms and writing well organized code is more important and has a bigger impact on performance than a bit of code optimization. But that would be a different question.
(2) Now, I realize that the actual difference were there no optimization is small. But that is beside the point. There are easily features which are optimized quite efficiently, I was just kind of too lazy to write one down. Just imagine the above snippet inside a for loop which is called 100'000 times.
Don't expect much on the optimization, there won't be
the tail-recursive optimization,
loop unfolding,
inline function
etc
As javascript on client is not designed to do heavy CPU work, the optimization won't make a huge difference.
There are some guidelines for writing hi-performance javascript code, most are minor and technics, like:
Not use certain functions like eval(), arguments.callee and etc, which will prevent the js engine from generating hi-performance code.
Use native features over hand writing ones, like don't write your own containers, json parser etc.
Use local variable instead of global ones.
Never use for-each loop for array.
Use parseInt() rather than Math.floor.
AND stay away from jQuery.
All these technics are more like experience things, and may have some reasonable explanations behind. So you will have to spend some time search around or try jsPerf to help you decide which approach is better.
When you release the code, use closure compiler to take care of dead-branch and unnecessary-variable things, which will not boost up your performance a lot, but will make your code smaller.
Generally speaking, the final performance is highly depending on how well your code organized, how carefully your algorithm designed rather than how the optimizer performed.
Take your example above (by assuming FooFactory.getFoo() and Bar.someStaticStuff("qux","gak",42) is always returning the same result, and Bar, FooFactory are stateless, that someStaticStuff() and getFoo() won't change anything.)
for (int i = 0; i < 10000000; i++)
blub.doSomethingImportantWithAFooObject(
FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42));
Even the g++ with -O3 flag can't make that code faster, for compiler can't tell if Bar and FooFactory are stateless or not. So these kind of code should be avoided in any language.
You are right, the level of optimization is different from JS VM to VM. But! there is a way of working around that. There are several tools that will optimize/minimize your code for you. One of the most popular ones is by Google. It's called the Closure-Compiler. You can try out the web-version and there is a cmd-line version for build-script etc. Besides that there is not much I would try about optimization, because after all Javascript is sort of fast enough.
In general, I would posit that unless you're playing really dirty with your code (leaving all your vars at global scope, creating a lot of DOM objects, making expensive AJAX calls to non-optimal datasources, etc.), the real trick with optimizing performance will be in managing all the other things you're loading in at run-time.
Loading dozens on dozens of images, or animating huge background images, and pulling in large numbers of scripts and css files can all have much greater impact on performance than even moderately-complex Javascript that is written well.
That said, a quick Google search turns up several sources on Javascript performance optimization:
http://www.developer.nokia.com/Community/Wiki/JavaScript_Performance_Best_Practices
http://www.nczonline.net/blog/2009/02/03/speed-up-your-javascript-part-4/
http://mir.aculo.us/2010/08/17/when-does-javascript-trigger-reflows-and-rendering/
As two of those links point out, the most expensive operations in a browser are reflows (where the browser has to redraw the interface due to DOM manipulation), so that's where you're going to want to be the most cautious in terms of performance. Some of that can be alleviated by being smart about what you're modifying on the fly (for example, it's less expensive to apply a class than modify inline styles ad hoc,) so separating your concerns (style from data) will be really important.
Making only the modifications you have to, in order to get the job done, (ie. rather than doing the "HULK SMASH (DOM)!" method of replacing entire chunks of pages with AJAX calls to screen-scraping remote sources, instead calling for JSON data to update only the minimum number of elements needed) and other common-sense approaches will get you a lot farther than hours of minor tweaking of a for-loop (though, again, common sense will get you pretty far, there, too).
Good luck!

Categories