6 ms·
While this article is itself worth a read, remember the programming mantra: * Make it Work * Make it Right * Make it Fast And this is the last step. Wh
by critium 10y ago
While this article is itself worth a read, remember the programming mantra:
* Make it Work
* Make it Right
* Make it Fast
And this is the last step. While this does not apply to all projects but it does apply to the majority.
- svdree 10y agoWhat you'll often find however, is that in the last step ("make it fast") you have limited room to maneuver, because of the stuff you did in the first 2 steps. If you really need high performance, you need to design for high performance, not just leave it as an afterthought.
- critium 10y agoabsolutely agree with your last sentence. But thats not a majority of software written in my experience. "If you really need *high performance*, you need to design for high performance, not just leave it as an afterthought." Emphasis, mine.
- jackmott 10y agoThen why do I encounter slow software every day? Why do we keep encouraging this?
- rakoo 10y agoBecause there is no user story for "make it performant", and there is little thought put into dynamic design vs static design. If money comes in with crappy performance and it is hard to predict how much more money will come if the developer improved performance, then it won't be a business priority.
- lostcolony 10y agoBecause they stopped at step one (make it work) or two (make it right). Or the first of my three (borrowed from Joe Armstrong), make it work, make it beautiful. It's not simply that they failed to plan for performance, it's that after making it work -they never measured and removed obvious bottlenecks-. Most pieces of software don't need high performance. Drawing some widgets on screen just isn't that demanding. But it -does- require you to go back afterwards and remove places you introduced inefficiencies. You don't need to code in C and optimize against cache misses for that; you just need to take time after things work to make them not suck, and thats something a lot of software development doesn't take the time to do.
- JoeAltmaier 10y agoMost client software doesn't need performance. Drawing widgets is a client-side thing. Scaling is really the hot point that discovers bottlenecks. Server have to scale. And nobody has time to plan/code very far for scaling when they haven't succeeded yet. I think its perfectly normal to write slow, non-scalable code as proof of concept. Then continue to attack bottlenecks as you grow (if you grow). Its a lucky startup that has to deal with performance. They can afford to dedicate a couple smart developers just to that issue. Michael Dell said every time your company doubles in size, you have to reinvent your processes. True for software too.
- lostcolony 10y agoYeah, I just gave a random example of something that is very common in a generic software application; at some point, you draw some basic GUIs. Those can lead to performance bottlenecks as well (loading and displaying 10 data points in your test bed; easy. Loading and displaying 1 million data points in a production situation, a little harder). There's also basic network operations, some DB/disk writes, actual CPU usage for whatever processing has to occur, etc. Any of those may need to be super performant for some apps, some will be front end, some backend, but for many applications and uses, at least initially, it's not worth worrying about at first. That said, I'd draw a distinction between vertical scaling and horizontal scaling. The former you should address as needed, as the gains are comparatively limited, and the bottlenecks are unknown (you think you're CPU bound; whoops, nope, I/O. Or whatever); the latter should be designed for if there's a chance you'll need it. Because oftentimes, things that are merely decisions early on (no difference in amount of work) can lead to savings of months of effort and churn down the line if you go for something that scales. Decisions like deciding what data needs to have strong consistency, versus what data can be eventually consistent (and choosing data stores based on that), trying to avoid shared state, thinking about "what happens if there are more than one of these?" and designing/implementing with that in mind (even if some aspects are super hard and you punt on them, there's plenty of low hanging fruit that you can address with minimal effort early, rather than massive later on).
- brianwawok 10y agoBecause this entire Mantra is horrible advice. All 3 need to be in the spec, and all 3 need to be coded for.
- arethuza 10y ago"Make it fast" sometimes does not need to be coded for if the applications is fast enough after the "Make it right" step.
- brianwawok 10y agoDoesn't matter, every app has some speed requirement.. if it is trivial, then there isn't much to do for it. It's not something you can just do later, because thats not how software works. Fast code needs designed to be fast. Not "fixed" at the end.
- zzzcpan 10y agoUsually it's almost impossible to predict where your design flaws would be until you actually use the thing in production. Because you make a lot of assumptions and some of them will inevitably be false. So, make it fast is mostly about changing design.
- crdoconnor 10y agoI've seen more performance problems caused by people not having clean code than I ever have from people not thinking about performance from the get go. I've also seen plenty of performance issues ironically caused by performance hacks wedged in early on.
- critium 10y agothis reminds me of the post about the jvm code cache a few days ago where if they had left the jvm to optimize the code cache by itself, the would not have ended up with the problem situation where the had to spend time to figure it out their optimization was the cause of the problem. -- sorry for the run on sentence.
- brianwawok 10y agoYou will often find clean code and fast code converge on very similar places. It is often a false dichotomy to think code needs to be either clean OR fast. Now this does break down, if you need to get to the point where you are bit twiddling, it is not going to be clean as using something higher level.. but you can often put the nasty parts in a static method somewhere and still have the code be very easy to read.
- barrkel 10y agoSure; but a working version is still really really useful to compare against (e.g. build up a suite of test cases) even if you have to redesign large parts for performance later.
- brianwawok 10y agoThis is really an overly simplistic way to code. I urge people to think deeper up front about performance. Know your performance goals going in and code accordingly. If you require 100 micro average latency and you coded in Node.js, step 3 will be a rewrite. Every single line of code I write, I can tell you my performance goals. If indeed it is a simple crud screen by a user, the goal may be "meh, document.ready called when viewed from 100ms browser lag within 1 second". Backend trading code would have different goals..
- karmelapple 10y agoHow do you know the speed expectations? Do you always talk concrete numbers with the stakeholders before each change you make, or just use reasonable rules of thumb you determine?
- brianwawok 10y agoDepends on the project! Asking stakeholders is good. Often then will have no idea, or say something generic like "make it fast". Try to pin them to something more concrete. "So how about adding this new feature makes X happen no more than 5% slower than it currently does"
- kasey_junk 10y agoNot before each change but before any major new initiative or refactor. Having those numbers up front is the only way to make appropriate trade offs. Having this conversation with stakeholders often educates them on the costs of performance as well. Getting 100% of responses sub 200ms is frequently orders of magnitude more expensive than getting 99% of them there, and stakeholders usually get that fast when you show them budget info.
- ansgri 10y agoReplying to the second paragraph, there often is a real value in maintaining strong upper bound for the latency, especially in distributed real-time systems (which are most of the real systems, anyway). E.g. (99% sub-200ms and 1% _unbounded_) vs (80% sub-200ms and _always_ sub-500ms) means 1% of potentially unanticipated crashes (a hell to debug and explain to customers!) vs a highly reliable system and happy customers.
- gabemart 10y agoMy personal approach is to do some order-of-magnitude performance testing as early as possible, to validate that the approach chosen to solve a particular problem is at least tenable. If you ignore performance completely until late in the project, you can paint yourself into a corner. This includes cases like knowing that performance is 50x slower than will be acceptable throughout development, but saying "we can add X later for an easy performance win". If you don't actually test that X gets you within reach of your performance target at an early stage, you can end up with a fully built system that is unusable.
- hawski 10y agoOne should put performance considerations under "Make it Work", but that is probably obvious. The definition of "It works" (or eventually "Its correct") should include certain latency or throughput requirements and sometimes can't be left out for "Make it Fast" phase. On the one hand I understand that most programs don't need to be specially fast. But on the other it leads to such of waste of time for the users. Where it really matters we usually see some kind of rewrite or new program that is designed to be fast and it can take significant slice of the pie. At the same time there is also a case for ease of use - ease of use can make even slow programs not only feel fast, but also take shorter time from decision to install/run said program to achieving user's goal. There is no silver bullet, but few (or many?) rules of thumb ;)
- jsingleton 10y agoAs with any engineering problem, there is usually a trade-off involved. Premature optimization is bad but software does need to be fast enough to start with and flexible enough to be improved later. You don't want to code yourself into a corner by accident. It's fine to knowingly take on technical debt, as long as you have a plan to fix it in the future. Even if this is never required. I always try to take a pragmatic approach, as things are usually not as binary as these simple rules of thumb assume. The real world is typically very nuanced, which is why engineering can sometimes seem like more of an art than a science, and why experience is so valuable. Shameless plug - I hope this attitude comes across in my book that focuses on web application performance issues: "ASP.NET Core 1.0 High Performance" (https://unop.uk/book/ https://unop.uk/book/).
- losvedir 10y agoWhat's the difference between "work" and "right"?
- jnordwick 10y agoIf this is your mantra, you aren't really working on code that require performance. If you where, the "make it fast" and "make it right" would be the same thing.
- oldmanjay 10y agoYes, it is unfortunate that this approach only works 99% of the time.
- overgard 10y agoYes and no; we all know the Knuth quote etc, but there are a lot of design decisions you have to make up front (language, database, server, framework, etc.) that you can't change later, but which will set the floor and the ceiling for what your performance looks like. For instance, if you're working in a resource constrained environment, garbage collected vs not garbage collected is a big decision. Or if you're working on a web app, how you layout your database tables or your nosql equivalents is going to have a huge effect, and is much harder to change later. There's a huge difference between premature optimization vs making decisions that will have performance consequences down the road. If you wait till the end of a project/release cycle to think about performance, the amount you can do about it will usually be disappointing.