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
_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime

Reply via email to