Why does pressing the enter key periodically speed up my code?

I inadvertently came across a phenomenon that puzzled me a bit. I used IDLE for quick testing, and I had very simple code like this (which I simplified for illustration):

from time import clock # I am presently using windows def test_speedup(): c = clock() for i in range(1000): print i, print '=>', clock() - c 

Now I ran this code like this (several times, with the same basic results):

 # without pressing enter >>> test_speedup() 0 1 2 3 4 . . . 997 998 999 => 12.8300956124 # the time to run code in seconds # pressing enter ONLY 3 TIMES while the code ran >>> test_speedup() 0 1 2 3 4 . . . 997 998 999 => 4.8656890089 # Pressing enter several times while the code ran >>> test_speedup() 0 1 2 3 4 . . . 997 998 999 => 1.91522580283 

My first guess was that the code might have worked faster because the output system might not have to match as many lines as I pressed enter (starting each time with each press). In fact, the output system always seemed to get acceleration right after I pressed the enter button.

I also looked at the documentation here , but I'm still a little puzzled why the three newlines are significantly faster.

This question is admittedly somewhat trivial unless you want to know how to speed up the output system in IDLE without interrupting the script. However, I would like to understand what happens to the output system here.

(I am using Python 2.7.x.)

+7
python python-idle
source share
2 answers

Underneath the covers, IDLE mimics a terminal on top of a Tk widget, which I am sure is ultimately derived from Text .

Having long lines slows down this widget a bit. And adding to long lines takes longer than adding to short lines. If you really want to understand why this happens, you need to look at the Tcl code underlying the Tk Text widget, which Tkinter.Text just a thin wrapper around.

Meanwhile, the Tkinter loop that runs IDLE triggers some funky things, allowing it to accept input without blocking the loop. When he thinks that nothing else is happening, he can sometimes block for a short time until he sees the input or event Tk, and all these short blocks can add up; pressing Enter can just undo a few of them.

In fact, I'm not sure which of these two is more relevant. You will need to test it with a program that simply spams long lines compared to one that inserts new lines each, say, 10 numbers, and see how much of the performance improvement you get in this way.

From a quick test on my Mac, the original program noticeably slows down gradually, and also has two quantum transitions in the slowness of about 500 and 920. Thus, it makes sense that getting into them every 333 or so will speed up the process -You probably avoid both of these quantum downturns. If I change it to just remove the comma, the problem goes away.

Printing a new line for each number can, of course, cause another slowdown, since this makes the terminal long enough to scroll, increases the scroll buffer, etc. I did not see this value in IDLE, but I ran the same one on the Windows command line, and you will see problems with too many newlines as bad as problems with too few IDLEs. The best compromise should probably come from "square" data or data that is as close to 80 columns as possible without going over.

+7
source share

I believe this has something to do with the IDE that you use to execute the code.

I ran your code (with syntax changes for version 3.3) and got the same time to execute both times:

999 => 8.09542283367021

edit : This was done in an IDLE warehouse with Python 3.3. I spammed the input key with several experiments and did not see the time difference between the string output on control v. Experiment.

While waiting, I decided to remove the print function and condense it in one line .:

 print(i, "=>", clock()-c) 

this produced 999 => 7.141783124325343

Based on this, I believe that the time difference you see is due to the IDE sucking out more threads to process your code, which leads to faster times. Clearly, the time at the end is the total amount of time for computing and printing the for loop.

To confirm my suspicion, I decided to put everything in a list of tuples, and then print this list.

 def new_speed_test(): speed_list = [] c = clock() for i in range(1000): speed_list.append((i, clock()-c)) print(speed_list[-1]) 

which outputs: (999,0.0005668934240929957)

In conclusion: my experiment confirms that your IDE is processing output and processor consumption.

0
source share

All Articles