Ankur Kothari experimented with trying to optimize CTGradient to only cover his particular needs. As he discovered, CTGradient is a rather hefty class, weighing in at about 1300 lines of code.
He went on to try and eliminate all the pieces he won’t need. First down to 200 lines, then just “a little over 100″, “a lean 80″ and, finally, 30. Quite a change. Thus, his conclusion:
Please: When you use other people’s code, don’t put it in without a thought. Go through it, understand it, and optimize it for your specific need. For the better performance and reduced RAM usage, computers will thank you.
And yet, this wasn’t quite met with unanimous applause. To understand why the notion of cutting down a class like this can be misguided, let’s review why CTGradient was, at the time, created to begin with. It was first introduced in January ‘06, and the first three paragraphs lay out the rationale for the existence of this class:
While [Core Graphics] is a heck of a powerful library… It always seems to take an elaborate amount of code (as well as time, if your not yet acquainted with it) to do some of the simplest little things. [..] AppKit provides a pretty decent layer of abstraction, but I find that there are still a number of holes in its coverage. [..] One of those that AppKit doesn’t cover (that it really, really should [..]), are gradients.
So. CTGradient does not provide new functionality; rather, it exists expressly as a simple abstraction to existing functionality that Core Graphics already does expose. This is a crucial point: CTGradient is purely there to make life easier for developers. Similar classes exist for different purposes. A typical application easily ships with a dozen of third-party classes or entire dynamically linked frameworks, whether it’s custom user interface controls, a parser for a file format, or client functionality for a common network protocol. Why? To save the developer tons of work that someone else has already done.
And it is for that precise reason why Ankur’s postulation is so absurd: if developers were to spend the time he did cutting down classes like CTGradient to the extreme where they only have the code they need, they might as well just not use the class at all. That is, in this example, they could just have called CG* functions directly. That they didn’t do so doesn’t mean they screwed the user over; it means they focused on different aspects of their piece of software.
Does it ultimately cause bloat? Yes, in a sense. There is no denying that plenty of virtual memory could be saved through this process. It’s empirically measurable. But:
- OS X’s memory management is excellent and really couldn’t care less if you’re using a few Megabytes more or not (and it’s not going to affect the amount of physical RAM used in any meaningful way). More or less the same is true on Windows Vista (but not on XP).
- Ankur is going to have a hard time proving his assertion that this will lead to “better performance”. (From what? The code is never called, so how could it impact the CPU or GPU in any way?)
- Whatever amount of time developers didn’t spend “optimizing” the code (or figuring out how to write it themselves) they get to spend implementing features, fixing bugs and interacting with the customer.
- Using someone else’s publicly available code benefits from occasional improvements, possibly from a community of other third-party developers who might fix bugs and add features. Try that with your own home-rolled code in a monolith of an app.
So is code bloat bad? Sure. Nobody benefits from that. However, there’s something even worse than abundance of code bloat: lack of pragmatism. I’d take an app that ships any day over one that is hung up in development hell due to developers who try too hard to make it perfect. I believe any self-respecting developer ought to normally do the same. ‘Normally’, because, there certainly are cases where these issues are more relevant – performance-critical apps in space shuttles, stability-critical ones in nuclear power plants, and so on. But none of that have anything to do with drawing a gradient.
It is even possible to compromise on the two: you could use a script (say, a Makefile) that generates a cut-down version of a class like CTGradient using given parameters – similarly to how ./configure does it for compiled code. For instance, a gradient class could have an –linear-only argument when you’re never going to work with other types of gradients, such as radial ones. But still, the question remains whether the benefit in resource usage outweighs the additional effort required to create, maintain, customize and use such a hypothetical script.
Now, nothing I’ve said above is any new revelation, and all of it could have been expressed in comments to Ankur’s post. Unfortunately, as Jonathan thoroughly discussed, Sir RixStep apparently preferred to turn the discussion into a venue for once again displaying his lacking people skills. It’s a shame, because I think Ankur’s post did make for an interesting read, regardless of whether I agree with is conclusion.
Others' Thoughts
Comment on November 22nd, 2007 at 10:49 pm
I don’t want to start another flame war, but he mentioned that too:
They may not have deliberately “screwed the user over”, but they have bashed and trolled the author for pointing out their “mistake” of using CTGradient instead of the CG function directly.
Comment on November 22nd, 2007 at 10:56 pm
Sigh. You didn’t read the code, did you?
The more defensive people get the more it makes me think the author is correct. And incorrect statements like that help too. This is depressing. I’m heading back to the safety of my cave.
Comment on November 23rd, 2007 at 12:52 pm
My statement is not incorrect: code that isn’t called can cause additional resource usage, but shouldn’t have any meaningful effect on performance. If you’re referring to optimizing functions like linearEvaluation, that’s a different issue entirely. There’s no doubt that algorithms can be tweaked, but that only affects functions that are actually called.
In fact, having community review of such functions and accepting improvements on a public, central repository is another upside (not flaw) of a project such as CTGradient, because developers can then simply update their local copies of the CTGradient class and automatically benefit.
Comment on December 6th, 2007 at 1:53 am
“In fact there are lots of great reasons for bloatware.” http://www.joelonsoftware.com/articles/fog0000000020.html The only thing that has changed since that article was written is that hard-disk space has gotten almost 25x cheaper!
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” (Knuth, Donald. Structured Programming with go to Statements, ACM Journal Computing Surveys, Vol 6, No. 4, Dec. 1974. p.268.)
Your Own Thoughts
I'd love to hear your input. Just try to stick to a few rules:
Before you comment for the first time (or, after you have deleted cookies), you will have to answer a little challenge to prove that you are not a spammer.
Comments are written in Markdown.