|
September 2006
September 29, 2006
Which is faster, i++ or ++i?
The answer is that you're probably asking the wrong question--for two reasons.
The first reason that it's the wrong question is that such questions concern only micro-performance: Does the statement take one machine cycle, or two, or whatever. Questions about micro-performance often depend strongly on implementation details, which means you can't really know the answers without measuring them as part of the overall application.
The second reason that it's the wrong question is that you would usually be better asking which usage is a better fit for your problem. For example, if you are asking about
for (int i = 0; i != n; i++) {/* do something */ }
the answer is that you are better off using ++i than i++, but not for any reasons of efficiency. Rather, when you write i++, you are directing that the value of i be copied, then incremented, and then the copy thrown away. There is no reason to make that copy in the first place, so why specify it?
As yet another example, if it is an iterator and M is a map, then writing
M.erase(it++);
is by far the most succinct way of erasing the element to which it refers while leaving it referring to the position immediately after the erasure.
Posted by Andrew Koenig at 04:50 PM Permalink
|
September 28, 2006
Abstracting programmer behavior
While I was waking up this morning, I had a sudden insight. Like most half-conscious insights, this one is only partly baked--but I thought it interesting enough to share it anyway.
Usually, we think about abstraction of program behavior. Sometimes, however, it can be useful to form abstractions of programmer behavior.
One example should be fairly well known: When offered a variety of options, most programmers will choose the default most of the time. We learn from this behavior to take care that defaults will be usable most of the time; if we can't think of a default that is usually the right thing to do, it is better to force the programmer to make an explicit choice.
A design example that follows from this phenomenon: If the default action after detecting an error is to ignore it, most errors will be ignored. It is this observation that led to the design of C++ exception handling--specifically, the idea of signaling an error in a way that can be handled, but for which the default is to behave in a way that is difficult to ignore.
I welcome comments about other examples of behavioral abstraction.
Posted by Andrew Koenig at 11:24 AM Permalink
|
September 26, 2006
Abstraction penalties are complex
Programmers often talk about the "abstraction penalty" -- the extra cost that one takes on in order to be able to think abstractly about a problem. How expensive is it really? The answer is complex--in the sense that it has a real part and an imaginary part.
For example, consider calling a subroutine. On most computers, if the compiler actually generates a subroutine-call instruction, the cost can be quite substantial. I once used a computer on which I estimated that half of its total execution time was spent in subroutine call or return instructions.
That's the real part. On the other hand, from its inception C++ has let the programmer ask the compiler to generate code inline rather than using hardware subroutine-call instructions. Moreover, many compilers these days generate inline code for small subroutines even if you don't explicitly ask for it.
So the penalty for using subroutines as abstractions can be substantial, or it can be zero, depending on your compiler.
Sometimes the penalty is even negative. For example, if you have a library routine available that does something in N log N time that you would do in quadratic time if you were writing it yourself, you can make your programs run much faster by using the library, even if you have to pay for subroutine calls.
I like a simple approach: Avoid gross inefficiencies (such as choosing bad algorithms) when you come across them; if the program is still too slow, measure it and figure out why. If it's not too slow, don't worry about it.
Posted by Andrew Koenig at 05:00 PM Permalink
|
September 13, 2006
An example of an abstraction
People sometimes have trouble understanding the notion of selective ignorance because it's too, umm, abstract. Sometimes an example will clear it up.
Most of us who use computers use systems that include a graphical input device, such as a mouse, trackball, or finger pad, which lets us move a cursor around the screen. Such systems are commonplace today.
In fact, they're so commonplace that I snuck an important abstraction past you in the last paragraph: the notion of a cursor. The abstraction: You move the mouse and the cursor moves. What we're selectively ignoring: There is no such thing as a cursor. Putting it differently, a cursor isn't a thing.
In other words, although we can see what we think of as a cursor doing something that we think of as moving, in reality there is no thing that moves. Instead what happens is that some pixels on the screen change color for a while, in a way that creates the illusion of something moving. If we dig deeply enough into the software, we might find that there are variables somewhere that contain the coordinates of the cursor's current position, and those variables might change values from time to time; but that's as close as we come to anything moving.
Think of the mental process that allows us to treat the changes in the screen's pixels as if an object were moving on the screen. That process, whatever it may be, is deeply ingrained in our makeup. Indeed, it is so deep that we share it with other animals--as anyone who has watched a cat try to attack a cursor will agree.
Viewing pixels that change color in a certain way as a moving object is an example of abstraction. We are temporarily ignoring part of what is going on so that we can interpret it in a more useful way. This processs of selective ignorance is the essence of abstraction.
Posted by Andrew Koenig at 01:37 PM Permalink
|
September 06, 2006
Why selective ignorance?
Once upon a time, while writing a lecture about important abstractions in programming, I suddenly realized that I didn't know how to define abstraction, even though I was sure I could recognize it when I saw it. So I went looking for definitions.
First I found one in the Oxford English Dictionary:
Abstraction: the act or process of separating in thought,
of considering a thing independently of its associations;
or a substance independently of its attributes;
or an attribute or quality independently of
the substance to which it belongs.
This definition seemed wordy, so I looked further and found the following quote, attributed to Locke in 1782 by Priestly:
Abstraction: leaving out of a number of resembling ideas
what is peculiar to each.
The language here is slightly archaic but the concept is not: Abstraction is the act of taking several ideas that resemble each other--in other words, several ideas that are similar but not identical--and removing everything but what the ideas have in common.
For example, I have three cats: one almost all black, one calico, and one tabby. Not only do they look different from each other, but they behave differently, and the texture of their fur is so individual that I can distinguish them in the dark by touch. Nevertheless, they are all cats; and when I think about them as cats rather than as individuals, I am disregarding everything but their catness--what they have in common. In doing so, I am thinking abstractly.
Although I liked the second definition, I thought my audience (mostly college sophomores) would feel uncomfortable with the archaic language; so I looked for a more modern way of expressing the same idea. Eventually, I came up with
Abstraction: selective ignorance.
Although I don't usually consider ignorance to be a virtue, the selective nature of abstraction changes the whole picture. The point is that most aspects of technology are too hard to understand completely, so our choice is really between selective ignorance and haphazard ignorance. Given that choice, I'll pick selective every time.
We practice selective ignorance all the time when we deal with technology. For example, if you are driving a car, you should concentrate on the road, rather than thinking about how the car works. On the other hand, when you're fixing a car, you have to think about how it works; you can put the road out of your mind until after you've fixed it.
In other words, when we are faced with a problem that is too large to understand, one of our most important intellectual tools is to understand just part of the problem, constructing a mental model that lets that part stand in for the whole in a useful way. In other words, selective ignorance--abstraction--lets us deal with problems that we would otherwise be unable to manage.
Now you know the origin of this blog's title. I intend to discuss a wide range of ideas. What they will have in common will be their relationship to various forms of abstraction. If you like, the notion of abstraction is an abstraction of the blog's ideas.
If you find the previous paragraph too confusing, you are welcome to ignore it.
Posted by Andrew Koenig at 07:12 PM Permalink
|
September 05, 2006
Welcome
As the editor of the C++ Department here on Dr. Dobb's Portal, I'd like to take this opportunity to welcome a new blogger to this space. Andrew Koenig will be taking over blogging duties from Pete Becker. Andrew's presence here will come as no surprise to many of you—He has been a frequent contributor to DDJ over the years, and has an impressive résumé. Please join me in welcoming Andrew to the Dr. Dobb's blogoshpere.
Posted by Kevin Carlson at 12:48 PM Permalink
|
|