print statements and profiling a function slowed performance

Chris Angelico rosuav at gmail.com
Thu Jun 26 22:06:54 EDT 2014


On Fri, Jun 27, 2014 at 6:36 AM, CM <cmpython at gmail.com> wrote:
>> Yes, it stands to reason that profiling code
>> is going to introduce a runtime cost.  How else
>> would we expect profiling to work?
>
> I think I was hoping for magic. :D

Thank you for being honest :) The fact is, though, that time-of-day
and console output take a lot more time than many people seem to
realize; this is especially true if you print something repeatedly on
the same line, such as:

num = len(x)
for i,foo in enumerate(x):
    print(i/num,end="\r")
    # perform processing

If x is, say, range(1000000), a simple "for foo in x: pass" will
complete fairly quickly (maybe 100ms on my computer), while the
progress-indicated loop will take much longer (about 30 seconds when I
tried it). Obviously you'll be doing more work than just "pass", but
it's easy to completely dwarf the actual processing with the display
to the user. (And yes, this can happen in production code, too. We had
an old Windows 3 program that, for some reason, completed its
processing in less time if someone moved the mouse around than if it
sat idle. Its stupid animation - not even a progress indication, just
"hi, I'm still working here" - interacted badly with idle
sensitivity.)

>>  What I do find Heisenbergian are bugs that show
>> up when debugging and profiling stuff are removed,
>> but completely gone when present.  IE profiling and
>> debugging slow it down enough that often subtle race
>> conditions are masked.
>
> Would never have occurred to me.  That *is* odd!

Race conditions are by their nature subtle. I've seen all sorts of
crazy things change their behaviour... refactoring a function can
appear to introduce or eliminate a bug (because the call/return
sequence adds a small delay), and occasionally, even a completely
benign change can influence something - renaming a file on the disk
can cause a cache miss and make the program work perfectly (or fail to
work) the one next time it's run. Yeah, that can be fun.

(Though not as much fun as debugging a refcount error, where a program
will crash if certain things are done *and then certain others*. The
actually-faulty code just plants a land mine [1], and until you tread
on it, nothing goes wrong. Depending on how many other references
there are to that object, the freeing could happen at any time; and
even after it's freed, there might be no apparent problem, until the
memory gets reused somewhere. Now THAT is fun to debug. Pretty much
*any* change to the code can affect whether or not it crashes.)

ChrisA

[1] Like this guy.
http://media.wizards.com/images/magic/tcg/products/m15/sf0JdVsk2/EN_42um78zriv.png



More information about the Python-list mailing list