7 ms·
Interesting article now take these suggestions and toss them out the window. Architecture, correctness, maintainability and readability of code are much more im
by macspoofing 10y ago
Interesting article now take these suggestions and toss them out the window. Architecture, correctness, maintainability and readability of code are much more important than optimizing for these extreme edge cases.
If there are performance issues, profile and refactor only the affected areas. Most of the time your code isn't going to get exercised enough to make any difference. You're also fighting JIT assumptions, since all VM devs will attempt to optimize against common patterns - so though these performance 'bottlenecks' may be true today, that may not be the case tomorrow.
Anectode: I had a co-op student preemptively apologize for using a double for-loop brute force search as non-optimal and not 'clean', during his code-review. The lists in question were guaranteed to have a size of 5, and that code was executed once per life-time of the app.
- tehlike 10y agopremature optimization is the root of all evil.
- mpweiher 10y agoThe actual quote is a bit different: "We should forget about small efficiencies, say about 97% of the time; premature optimization is the root of all evil." It goes on: "Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified." Just before that section: "The conventional wisdom shared by many of today's software engineers calls for ignoring efficiency in the small; but I believe this is simply an overreaction to the abuses they see being practiced by penny- wise-and-pound-foolish programmers, who can't debug or maintain their "optimized" programs. In established engineering disciplines a 12 % improvement, easily obtained, is never considered marginal; and I believ the same viewpoint should prevail in software engineering. Of course I wouldn't bother making such optimizations on a one-shot job, but when it's a question of preparing quality programs, I don't want to restrict myself to tools that deny me such efficiencies" From "Structured Programming with go to statements" Knuth, 1974.
- tehlike 10y agoI think my emphasis was still fair, even though it is probably a misquote. There are usually many bottlenecks in any given system, be it lack of proper parallelization, waiting on xyz while you could use that opportunity to do other tasks and so on that language tend to account for small part of these. Sure, if you are hitting the limit of that kind of optimizations, language could be the next thing you want to use to optimize further, but usually systems are far from that.
- Klathmon 10y agoRe: your last paragraph. I tend to do something similar in the form of comments. I'll use what is most likely horribly inefficient (but quick and easy to reason about) way of doing things, then i'll throw a comment in the docblock about how it's probably pretty inefficient. My reasoning is that i've had parts of a program that were very lightly used become very heavily used as the program evolves, and taking a few seconds to comment that this is a low hanging fruit if i need it has helped future-me at least once. As with most things, it's not a hard "rule", just something I'll do when it makes sense.
- mattmanser 10y agoWhy bother? The comment is a waste of time. Performance profile it and go from there. If you're doing anything other than using a performance profiling tool on real code with vaguely realistic data you're completely and utterly wasting your time taking stabs in the dark. Leaving comments that will become obsolete and misleading as the code evolves seems just as bad as pre-optimizing code. I've been working on a project at the moment where exactly what you've suggested was done, but they'd used todo comments. Last winter they'd had to up to an azure large SQL instance and it'd still max out DTU every now and again (DTU being MS's db performance measure on azure). Client was hoping I might fix a couple more problems as the volume is expected to triple or more this winter. In 6 days of simply running a local profiler I found and fixed 3 major performance problems, none in any way related to the pointless comments claiming X method needed optimising, none of which were even 1/10000th of the program's execution time. One of those problems was even caused by a previous "optimisation". I confirmed the problem spots by checking the web logs and avg page response times to confirm production was having the same problems. The site now potters along on a small SQL instance never going above 5% DTU, the worst pages are all being served 5 times faster. Done the same thing to a site with slow rendering (js problems). Chrome's profiler is good enough. If you don't know how to use your language's profiler, learn, now.
- Klathmon 10y agoDon't get me wrong, I do use the profiler a ton, and it's the first thing i reach for when i start noticing issues, but having that little comment about why i did it that way lets me relax a bit. I'd never mark it as a TODO or something that would clutter a tool up with crap, but having it there could help. A comment out of something I did recently where it's a loop that iterates over an array that's expected to be a few hundred long, and each iteration loops over the array again: // This is O(n^2) out of pure laziness. Might cause issues if the array gets really big. It's not hurting anyone, took like 10 seconds to write, and if it ever becomes a problem, the first thing i'll see is that in the function docblock which lets me (or someone else) know that there is no technical reason it needed to be O(n^2).
- dimal 10y agoThat's not a fair reading. I don't see anywhere that the article makes a any suggestion about when to optimize, it only suggests techniques that you could presumably use when you actually need to. Just as it's silly to prematurely optimize, it's silly to toss these suggestions out the window. If you hit a point where you need to optimize, these suggestions can be very useful. > You're also fighting JIT assumptions, since all VM devs will attempt to optimize against common patterns Optimization nearly always means that you're optimizing against a particular implementation, which may not be the same in the future. But your app lives today, in today's world. If you actually do hit a bottleneck, should you throw up your hands and say, "Don't worry, I'm sure it won't matter in a few years?" Of course not. Just as you shouldn't prematurely optimize, you should be willing to do it when necessary. Having some knowledge about what might work is definitely helpful.
- bastawhiz 10y agoIn fairness, unless you only care about Chrome, there are many implementations already. Many of these types of optimizations do not necessarily have a net positive effect on performance across the board.
- Rapzid 10y agoOr node.js running V8...
- macspoofing 10y ago>That's not a fair reading. I don't see anywhere that the article makes a any suggestion about when to optimize, it only suggests techniques that you could presumably use when you actually need to. Then you don't have a fair reading of my comment. I didn't say to never use it. There may be time-sensitive areas that perform a lot of work, very often. In those cases, go nuts, squeeze out every ms per frame you can. In the vast majority of cases, don't bother. Focus on maintainability and architecture and choose the right data structures (that's where your bottlenecks are going to be). Don't bother with low level details.
- 10y ago
- pizlonator 10y agoAs a VM dev what I find intriguing about these three optimizations is that they are unlikely to be obviated by any VM optimizations anytime soon. - VMs will indeed optimize the heck out of object allocations, but I think that hoisting out functions to reduce the rate of allocation is always going to be some kind of win. It definitely reduces work on the front-end, so if your app has a lot of code, it's a great idea. Remember, the VM may optimize away allocations once your code gets super hot and you end up in the optimizing JIT - but that doesn't happen for a lot of web framework code since it's only used for brief interactions. Avoiding allocations in that code is still worthwhile, because the more of that you do the lower the probability of a GC during page load or other important interaction. I'm surprised that function object allocation in particular was a hot spot for them, because I've struggled to find benchmarks where this is a huge deal. But I still think that optimization of theirs is a solid idea and it will continue to be a good thing for as long as I can foresee. - Rolling your own bitfields is always a win. The proof burden for the VM to do this optimization for you is very high, so it's totally not like register allocation or some other optimization that reliably Just Works. If a VM did infer that a cluster of boolean fields could be compacted into a bitfield, then this optimization would likely either happen late (so it wouldn't benefit short-running code) or it would incur early costs (so the presence of the optimization would penalize all code, including code to which the optimization does not apply). WebKit can infer that properties are boolean, but it won't build a bitfield out of your properties because of these concerns - the benefit is low and the cost is high. Also, lets not forget that this optimization is still not done by much more mature languages like C++. Last I checked, JVMs also didn't do this for you, because concurrency means that this optimization would be a perf fail in the common case. So, if you're writing code and you see an opportunity for a bitfield, please roll it yourself! That's a great idea and it will continue to be a great idea for a long time to come! - The no-op function trick is amazeballs. This isn't working around the VM - this is working with the VM to get the VM to perform some code specialization for you. I would equate it to using templates in C++ to specialize your code for two distinct cases (bad thing doesn't happen vs bad thing does happen, for example). Except here, you can specialize a lot of different things simultaneously. At least in WebKit, this will scale because even if you start overwriting the no-op functions, we'll recompile with exponential back-off, so the worst case isn't bad. Also, the back-off means that if you overwrite multiple no-op functions at a time, it will probably only cause one recompile because we'll wait before recompiling. The no-op function thing is just smart hacking, and I'm super happy that people are doing this in JS. Also, I'd be curious to hear exactly how anyone would think that this is a worse idiom than any other even ignoring perf. The hook that starts empty and is replaced with non-trivial functionality feels to me like an idiomatic use of the functional part of JS.
- gonyea 10y agoYes, yes, yes, yes. I am SO TIRED of seeing pre-optimizations from people who should know better. These optimizations are a neat FYI. But they do not belong anywhere near the business logic of a production app. If you have a massive app (doubtful) with bottlenecks that warrant these optimizations (doubtful), extract them into a library that is isolated, documented, and tested. Business logic should describe the needs of the business in the clearest and simplest terms.
- zokier 10y agoDid you read the article? It describes optimizations applied inside a relatively low-level building block library, not anywhere near business logic. Heck, the author goes as far to say: > I apply it in libraries and platform code because applications that I don't control or will not know about will depend on them and therefore I cannot make the assumption whether performance will matter or not for them. Everyday applications I work on typically don't have tight performance requirements so optimization is less prioritized
- gonyea 10y agoYes, I did. There's a lot of people who will ignore his caveat and try to use these optimizations where they don't belong. I see it a lot and it's painful. Hence the "throw it out the window" advocacy.
- rektide 10y agoI strongly tend to think the hard part is community, making a practice. I believe that we could optimize around the kind of practice spoken here- having flyweight objects, with little depth to them, few captured functions- believe is possible and doable. It's a very mixin style architecture, but more about structures than what a lot of focus is- methods. We are struggling to figuring out the answers to what you are challenging here- finding broad architecture, evident correctness, general maintainability, patterned readability- it's all hard. I tend to think the actual decisions factor in little though, that only at Facebook scale to mixins- particularly data-centric ones, rather than function centric ones- become hard to practice well, intra-organizationally. And different patterns will have some different balance. But overall I think it's mostly exposure- the good, advantageous patterns need leadership and example for them. Most advantages are portable, but take practice to borrow. Having your flyweight have a length property on it is not going to be a serious barrier to any of these ideas- architecture, correctness, maintainability, reliability. your side. I really really like the ideas suggested in this article- use a flyweight context, don't capture functions, don't nest. It's fast, bleedingly fast JS, and many folks could emulate and practice this, and not complicate their lives, and spread a practice that is fast.
- pjmlp 10y agoI see this a lot in the C community as well. Never had a use case of program being too slow due to the better type safety of the language being used. And on the few cases it actually mattered, like 1% of the code base after profiling, only there was the safety level turned off if no other means of optimization were possible. Apparently some programming language cultures are bound to the "micro-optimize every code line" cargo cult, even if it doesn't matter the difference to the use case at hand.