Test performance impact (was: The dreaded M-R)
John Hughes
rjmh at cs.chalmers.se
Thu Feb 2 04:51:58 EST 2006
Summary: 2 programs failed to compile due to type errors (anna, gg).
One program did 19% more allocation, a few other programs increased
allocation very slightly (<2%).
pic +0.28% +19.27% 0.02
Thanks, that was interesting. A follow-up question: pic has a space bug.
How long will it take you
to find and fix it? And how come speed improved slightly in many
cases--that seems counter-
intuitive.
Let me make clear that what concerns me is not the impact of the M-R on
space and time
performance on average. What concerns me is the difficulty of debugging
performance
problems. Even if we Haskell programmers usually consider correctness
first and
performance later, when we want to actually use our beautiful code, we
need to find and
fix at least the worst performance problems.
At that point, I'm reading the code and trying to understand--with the
help of profiling
tools--why it performs the way it does. I need the performance behaviour
of the code
to be *obvious*. When I pull out a common sub-expression into a
let-binding, I want
to *know* that it will be evaluated at most once. When I see a
collection of variable
bindings, likewise, I want to *know* that they are computed once only.
When I see
a seq on such a variable, I want to *know* that any pointers in its
unevaluated form
are thereby dropped. When I introduce or remove overloading in a
function definition,
I want to *know* that I have not thereby changed the sharing properties
of a variable
binding somewhere else, potentially introducing a space or time leak. I
want to know
these things by looking at the code in front of me, not by running the
compiler with the
right flags and reading its warning messages. Unexpected behaviour at
this point is a trap,
that can lead to many wasted hours as one reads the same code again and
again, assuming it
behaves as expected, only to eventually convince oneself, by long
examination of profiles,
that it cannot be doing so. If the unexpected behaviour is rare, that
only means that when it
*does* happen, it will take all the longer to find and fix. I find
languages with such traps
intensely frustrating to work with. If I can't even tell, *by reading
it*, what my code means,
then what hope have I got?
There are plenty who will argue, quite reasonably, that lazy evaluation
in itself makes
understanding performance behaviour unreasonably difficult; that strict
languages
should be preferred because the space and time behaviour is much more
obvious.
I don't agree, because I find the software engineering benefits of lazy
evaluation to
be so large, that it's worth the cost in making performance reasoning
more difficult
--but I accept there is a trade-off there. I don't see benefits on
anything like the same scale
from dropping the M-R.
Today's M-R has the merit that it at least makes it evident, in the
code, where
sharing may be lost. It's often a minor irritant, occasionally a bit
more than minor.
Were it to be removed with no replacement, then the irritation would go
away, and
the signs are that most of the time, performance would not change much. But
occasionally--just occasionally--there would be a space or time bug
caused by
loss of sharing *somewhere* in a large body of code, and searching for
it, we
would descend into nightmare. I'll put up with the irritation any day, to be
sure of being spared the nightmare.
John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org//pipermail/haskell-prime/attachments/20060202/f8daec83/attachment-0001.htm
More information about the Haskell-prime
mailing list