Needless copying in iterations?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Sep 16 05:50:39 EDT 2007


On Sun, 16 Sep 2007 15:05:55 +1000, Ben Finney wrote:

> Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:
> 
>> In *general* the compiler can't tell, but in specific cases it could. A
>> (hypothetical) optimizing compiler would tell the difference between:
>> 
>> for item in alist[1:5]:
>>     print item # no possible side-effects
> 
> The 'print' statement converts the 'item' to a str. That conversion
> could, in a pathological case, have a side-effect (say, if the class of
> 'item' had an overridden '__str__' method with side effects), and the
> compiler can't know this isn't a pathological case.

Fair enough... but I'm reminded of a rant by Joel Spolsky about GUI 
design:

'...programmers have tended to think that if users are allowed to resize 
and move windows, they should have complete flexibility over where these 
windows go, right down to the last pixel. After all, positioning a window 
2 pixels from the top of the screen is "equally likely" as positioning a 
window exactly at the top of the screen.'

http://www.joelonsoftware.com/uibook/fog0000000249.html

(three quarters of the way down, in Chapter 7.)

Maybe I'm being unfair, but it seems to me that the attitude is similar: 
'there's no point optimizing the common case of printing (say) ints 
stored in a list, Just In Case the programmer wants the incredibly rare 
case of setting sys.stdout to some wacky object that modifies the list 
he's iterating over. It could happen.'

*shrug* But apart from the occasional smart-alec who does it just to 
demonstrate that it is possible, it probably never has.

It seems to me that the "consenting adults" philosophy of Python doesn't 
extend to the compiler, and perhaps it should. Maybe Python could 
optimize common cases, and if developers wanted to do wacky things, let 
them turn optimization off on a module-by-module basis.

Or even function-by-function. Wouldn't it be nice to have decorators that 
could optimize the functions they decorated?


>> for item in alist[1:5]:
>>     alist.append(item) # side-effects DON'T matter
> 
> The compiler doesn't know that, at the time of invocation,
> 'alist.append' doesn't have side effects that matter.

It might if it knows what type alist is, and how long it is (as Marc 
Rintsch points out). That's why I used "alist" in my example rather than 
"an_arbitrary_sequence".


> The compiler for a dynamic language like Python has very little absolute
> "no significant side-effect in these specific cases" guarantee of the
> kind you're assuming even in the cases you choose for contrast with the
> ones that *do* have significant side-effects.

Yes, in general one might not be able to make those guarantees, but still 
there are common cases where you can. That's how Psycho works.

The point is rather moot, since CPython (and probably other Pythons) do 
almost no optimizations. But just because Python is a dynamic language 
doesn't mean there are no optimizations possible: Haskell is a dynamic 
language, and there are optimizing compilers for it. Of course, it is 
much simpler for Haskell, because of the type system it uses.

The CPython compiler already does a couple of source-code optimizations 
(ignores some unused strings; some constant folding) and at least one 
runtime optimization (string concatenation is no longer _always_ slow):

http://utcc.utoronto.ca/~cks/space/blog/python/ExaminingStringConcatOpt

Because of its very nature, optimizing Python is hard. Even something as 
simple as tail-call recursion optimization is verboten, because Guido 
considers good stack traces more important than preventing stack 
overflows in the first place:

http://www.tratt.net/laurie/tech_articles/articles/tail_call_optimization

Anyway, I'm not really complaining. I like Python, I'm grateful for the 
work the Python-dev people have already done, and I'm in no position to 
volunteer to write an optimizing compiler. And it may be that, regardless 
of how smart you make the compiler, Python simply can't be optimized 
because of design decisions made back in 1990-whatever when Guido first 
started his grand plan.



-- 
Steven.



More information about the Python-list mailing list