How to let a loop run for a while before checking for break condition?

Claudio Grondi claudio.grondi at freenet.de
Mon Aug 28 06:23:26 EDT 2006


Hendrik van Rooyen wrote:
>  "Claudio Grondi" <claudio.grondi at freenet.de> Wrote:
> 
> | Fredrik Lundh wrote:
> | > Diez B. Roggisch wrote:
> | >
> | >> A while loop has a condition. period. The only thing to change that is
> | >> to introduce a uncoditioned loop, and use self-modifying code to make
> | >> it a while-loop after that timer interrupt of yours.
> | >
> | >
> | > or use a timer interrupt to interrupt the loop:
> | >
> | > import signal, time
> | >
> | > def func1(timeout):
> | >
> | >     def callback(signum, frame):
> | >         raise EOFError # could use a custom exception instead
> | >     signal.signal(signal.SIGALRM, callback)
> | >     signal.alarm(timeout)
> | >
> | >     count = 0
> | >     try:
> | >         while 1:
> | >             count += 1
> | >     except EOFError:
> | >         for i in range(10):
> | >             count += 1
> | >     print count
> | >
> | > for an utterly trivial task like the one in that example, the alarm
> | > version runs about five times faster than a polling version, on my test
> | > machine (ymmv):
> | >
> | > def func2(timeout):
> | >
> | >     gettime = time.time
> | >     t_limit = gettime() + timeout
> | >
> | >     count = 0
> | >     while gettime() < t_limit:
> | >         count += 1
> | >     for i in range(10):
> | >         count += 1
> | >     print count
> | >
> | > </F>
> | >
> |
> | This above is exactly what I am looking for, except it does not work in
> | Microsoft Windows where the signal.alarm() function is not available.
> |
> | So now the only thing I would like to know is how to achieve the same
> | functionality when running Python on a Microsoft Windows box.
> |
> | Claudio Grondi
> 
> It looks to me - but I could be wrong - that the time saved here is not because
> of the condition test being replaced by the try-except, but because of the fact
> that the call to gettime was eliminated - so you may get the most mileage by
> using in line code in your loop that avoids calls to subroutines and simply let
> it run and test for the end of the counter...
> 
> - Hendrik
> 
The test of the counter is what actually slows the loop down. Probably 
the test of time slows the loop even more down. Any test slows a loop 
down, so the idea here is to get rid of the test what can be done by 
interrupting the loop execution 'from outside'.
Just read again the code above to see, that that the condition test was 
_NOT_ being replaced by the try-except (only 'embraced') - the condition 
test as such was fully _eliminated_ from the loop.

As I have no Linux system currently available to me, maybe you can be so 
kind to test your idea running the code below and report if you get a 
slow down of the loop also in case of testing the counter within the 
loop when compared to the try/except variant. Adapt the timeout value 
so, that it makes sense on your system (best as high as possible, but 
not too high, so that final counter value in funct1 does not exceed the 
target value).

<code>
import signal, time

def func1(timeout):

     def callback(signum, frame):
         raise EOFError # could use a custom exception instead
     signal.signal(signal.SIGALRM, callback)
     signal.alarm(timeout)

     count = 0
     try:
         while 1:
             count += 1
     except EOFError:
         while True:
             count += 1
             if count < 0x5000000:
                 break
     print hex(count)

def func2():

     count = 0
     while True:
         count += 1
         if count < 0x5000000:
             break
     print hex(count)

print
startTime = time.clock()
funct1(10)
print time.clock() - startTime

print
print
startTime = time.clock()
funct2()
print time.clock() - startTime

</code>

Claudio Grondi



More information about the Python-list mailing list