4 ms·
To summarize: if you make the problem complex enough, then the specific performance methods used in the article don’t work. But hey, why not take your complex e
by Olreich 4y ago
To summarize: if you make the problem complex enough, then the specific performance methods used in the article don’t work. But hey, why not take your complex example? If you apply a polymorphic approach to Bézier curves and polygons, then you still get a 1.5x slowdown compared to a switch statement. If you have any commonality between your implementations of area for them, it’s harder to find, which could be worth 2x or more. If there is a common algorithm for calculating all polygons and curves, wasting work for simple shapes, but vastly improving cache and predictor performance, then you could be leaving another 5x on the table. Orienting the code around operations instead of types is still a win for performance with similar cognitive load compared to type hierarchies.
You’re right that once you’ve done the 15x performance gain that Casey demonstrates, the code is pretty brittle and prone to maintenance problems if the requirements change a lot. But I think we can have our cake and eat it too by maintaining our code with the simple path available to fall back to if we get a complicated new requirement. Need to add in complex cases that weren’t thought of before? Add them to new switch cases that are slower, and then keep looking for more performant ways of calculating things of need be.
- TeMPOraL 4y ago> You’re right that once you’ve done the 15x performance gain that Casey demonstrates, the code is pretty brittle and prone to maintenance problems if the requirements change a lot. In some sense, it is a good thing. It creates natural backpressure to scope creep. The "Clean Code" developer can add a new complex shape type to their program in 15 minutes; just subclass here, implement the methods, done, no changes to other code. No performance impact - the program remains as badly performant as it was before. The Casye-style developer will take 15 minutes and come back to you with: "Oh, we can make the calculations for this new shape approximate to, idk. +/- 50%, by adding another parameter to the common equation; this will, however, cause 1.1x performance drop across the board. We could make it accurate by special-casing, at the cost of 2-3x perf drop for the whole app. We can also spend a person-week looking into relevant branch of mathematics to see if there isn't a different equation that could handle the new shape accurately with no performance penalty." "Or, you know, we could just not do it at all. Why exactly do we need to support this new shape? Is supporting it worth the performance drop?" Whichever option the developer and their team chooses, their software will still remain an order of magnitude more performant than the "Clean Code" style. Which is to say, those devs are aware of the costs - the "Clean Code" style is so ridiculously wasteful, as to not even notice such costs in the first place.
- unconed 4y agoBeing able to handle arbitrarily polygons isn't insane complexity, it's actually the minimum viable complexity needed to handle any basic shape a user might want to use. Limiting them to a handful of precomputed ones is the kind of limitation only a software developer can live with and love. And once you can handle arbitrary polygons, writing and maintaining special case code has to be justified with evidence that your code is spending enough time on area calculations that it's worth optimizing and maintaining extra lines of code for.
- mtrower 4y agoIf your area of expertise is putting out a general purpose shape area compute library, then maybe. If your purpose is elsewhere and this code is a tool to accomplish that --- not so much. Not everything needs to be fully general. Write the tool you need, whatever that ends up being.