5 ms·
Mature Optimization: An Introduction
- AlisdairO 12y agoGood read. In my experience, one caveat to consider is that Knuth appears to be talking about talking about code optimisation, rather than architecture optimisation. Let's consider a persistence layer. Let's say you make a decision to use an architecture that retrieves objects from a backing store one at a time, rather than also providing a bulk retrieval method. You'll likely hit a performance wall at some point. Unfortunately, when you make the decision to provide bulk CRUD APIs, you may have a lot of code that's not so easy to update. If you'd provided bulk CRUD early on, even if the implementation was simple loops, you could have avoided a serious headache for little cost. I agree with the general sentiment of not optimising code too early. Blocks of code are easy to change later. Architecture can be very hard to change later - so it's perhaps worth a little more attention upfront.
- solipsism 12y agoI disagree. You're suggesting that we need to forsake Knuth's advice when designing the architecture of our solution because architecture is hard to change later. What you have not realized is that architecture that is hard to change later is poor architecture. One of the most important qualities of a good design is "easy to change later." That goal should permeate your design in almost all cases. To take your example, if you had made the decision from the start to abstract the nature of the retrieval method so that implementations like "bulk retrieval" and "one at a time" retrieval can be swapped for each other, you are free to follow Knuth's advice to not prematurely optimize. It's obviously not possible to accurately predict where optimization will be needed in the future, but a good design means that the disruption from any optimization work will only extend so far.
- hawleyal 12y agoAgreed. If I can't refactor the architecture as easily as the domain code, it's too brittle.
- AlisdairO 12y agoA persistence layer might have literally millions of lines of code that (directly or indirectly) depend upon it. The operation 'get me this object' is potentially present throughout your architecture. I can't imagine how you would make that as easy to refactor as an encapsulated piece of code. Sure, you could do a programmatic refactor that changes all the calls to request an array of one item, but that's pointless. Actually changing the code so that it truly batch-oriented is inevitably a substantial task.
- hawleyal 12y agoI don't understand how you would have a persistence layer or otherwise that can't be refactored without changing external code that depends on that layer. Batch is hard of course. But it's conceivable to have a crappy implementation (just looping single statements) and then later refactor it to do it database side, or perhaps in parallel (looping single statements simultanously). All the while without modifying the dependent code. No?
- AlisdairO 12y agoThat's exactly the approach I'm recommending :-). Basically, put thought into the api up front so that later, performance improvements are a master of improving local code, rather than architectural changes.
- dragonwriter 12y ago> If I can't refactor the architecture as easily as the domain code, it's too brittle. The thing is "refactoring architecture" often requires being able to abstract things in ways that popular programming languages make difficult, and which most programmers aren't familiar with dealing with and reasoning about. Its the same kind of problem that makes Haskell seem hostile to many programmers.
- Narishma 12y agoOn the other hand, abstracting too much results in a more complex architecture that leads to it's own hard to fix performance problems later on.
- collyw 12y ago> What you have not realized is that architecture that is hard to change later is poor architecture. In some circumstances yes others no. In my in house database, I asked a couple of years ago about the relationships between entities in the database. I got an answer, I designed (architected?) it from there. The database tracks samples for a DNA sequencing centre. Now a couple of years later, the technology has changed. And where it was a one to many relationship, its now a many-to-many. The tables affected are at the very heart of the application, so its going to be a pain to change. Is that bad architecture? The requirements genuinely did change, in a way that the non IT staff didn't anticipate. On the other hand there are plenty of times when I can see a quick hack that my team leader suggests will lead to a tangled mess a couple of months down the line. Basically when the application layer is compensating for a crap database design, then its going to cause problems.
- AlisdairO 12y agoDisagree completely. Firstly, I'm not saying we should forsake Knuth's advice - I don't think his advice ever really covered architectural decisions. It's more that I've seen it applied (incorrectly, imo) to justify some obviously questionable decisions. Changing my API to add bulk retrieval is easy. Changing all (or a significant fraction of) the code that depends on that API to take advantage of the change is hard, particularly when you're working on an enormous product. Unfortunately this is an example of a situation where you often experience death by a thousand cuts, and IME the 97%/3% split doesn't hold up at all. I think the other reason I think it's worth caring about this stuff up front is because it's not terrifyingly hard/time consuming, and applying simple considerations such that you don't screw yourself later doesn't have to impose an excessive tax upon your codebase quality. The same is often not true of pervasive code microoptimisation. I suppose there's an extent to which such basic architectural decisions could be likened to simply 'doing the right thing' when you're coding - using sets instead of arrays for 'contains?' heavy code, and so on. I guess I've just seen several projects make obvious blunders when starting up that could have been averted by a pretty small amount of thinking ahead.
- aristus 12y agoJust FYI, this is a freely downloadable book: http://carlos.bueno.org/optimization/mature-optimization.pdf http://carlos.bueno.org/optimization/mature-optimization.pdf
- kllrnohj 12y agoI'm actually going to call bullshit on the entire notion of a "critical 3%". That may previously have been true, but so, so many apps these days have the majority of their code on critical paths, and time and time again I've seen apps that are generally sluggish just because of death by a thousand cuts. There wasn't a 3% focus area where fix it and everything is magic, it was a "well, this anti-pattern permeates your entire app, and now you have to significantly overhaul 50% of it to fix it" The modern era of low-latency interaction with high framerate scrolling & animations has completely changed the performance landscape. Performance is not something you can bolt on at the end anymore.
- aristus 12y agoThe idea of the book is to take all advice with a grain of salt, and measure yourself. Inefficiency spread everywhere is kind of a best case. Or it might be an indication that you are looking at the wrong layer of the stack. Also, judging from your jargon I'd say you work in games. Games are an entirely different dimension from the mainstream of programming.
- kllrnohj 12y ago> Inefficiency spread everywhere is kind of a best case. Not if that inefficiency is enough to cause visible issues, which is not unusual. > Also, judging from your jargon I'd say you work in games. Nope, I work on mobile apps. Which are not entirely unlike games.