while True or while 1

Francesco fal at togliquesto.fastwebnet.it
Tue Dec 28 10:00:37 EST 2010


hehehehehehe...

On 17/12/2010 2.01, Steven D'Aprano wrote:
> On Thu, 16 Dec 2010 23:34:21 +0000, BartC wrote:
>
>> In terms of a more realistic function (admittedly still a little
>> contrived, as the loop would be written differently), I tried this:
>>
>> def p2(n):
>>    p=1
>>    while True:
>>      if n<=p: return p
>>      p<<=1
>>    return 0
>>
>> for i in xrange(1000000):
>>    x=p2(i)
>>
>> p2() calculates the smallest power of 2>= it's operand.
>>
>> Using while True as shown, it took 3.4 seconds. Using While 1, it took
>> 2.6 seconds (Python 2.5).
>
>
> Right. And a saving of 0.8 microseconds per iteration is a micro-
> optimization which is likely to be invisible in any real situation.
>
> I mean, yes, you saved almost an entire second. Wow. Save another 179 of
> them and you'll almost have enough time to make yourself a coffee.
>
> Bart, we get it. Nobody denies that the optimization is real, only that
> it is generally meaningful. Who cares whether it takes 2 seconds or 4
> seconds to generate one million results if the rest of the application
> takes 3 minutes to run?
>
> *If* your application is such that saving 0.8 microseconds per iteration
> actually is useful, AND your loop has to be written as a while True loop,
> then this *may* be a useful micro-optimization to save 0.8 microseconds
> per iteration. That's a vanishingly tiny proportion of all code written.
> If your code happens to meet those conditions, then by all means use
> "while 1". Or move to Python 3, where "while True" has the same
> optimization performed.
>
> But in general, such micro-optimizations are not terribly useful. If you
> shave off 1 second off a program that runs in 3 seconds, chances are
> nobody is even going to notice. Two seconds or three, who cares? Either
> way, it's too short to do anything else, and not long enough to matter.
> If you shave off an hour off a program that takes 20 hours, who is going
> to care?
>
> But so long as it doesn't introduce bugs, or make maintenance harder, or
> add complexity, such micro-optimizations don't harm either.
>

HEY! That was MY argument! ;-))

Newsgroups: comp.lang.python
Subject: Re: If/then style question
Date: Tue, 21 Dec 2010 20:54:02 +0100

I'd bet you would stress your point Steven! But you don't need to persuade me, I do already agree.
I just meant to say that, when the advantage is little, there's no need to rewrite a working function.
And that with modern CPUs, if tests take so little time, that even some redundant one is not so much of a nuisance.
in your working example, the "payload" is just a couple of integer calculations, that take very little time too. So the overhead due 
to redundant if tests does show clearly. And also in that not-really-real situation, 60% overhead just meant less than 3 seconds. 
Just for the sake of discussion, I tried to give both functions some plough to pull, and a worst-case situation too:

 >>> t1 = Timer('for x in range(100): print func1(0),',
...  'from __main__ import func1')
 >>>
 >>> t2 = Timer('for x in range(100): print func2(0),',
...  'from __main__ import func2')
 >>>
 >>> min(t1.repeat(number=1, repeat=1))
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
53.011015366479114
 >>> min(t2.repeat(number=1, repeat=1))
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
47.55442856564332

that accounts for a scant 11% overhead, on more than one million tests per cycle.

That said,  let's make really clear that I would heartily prefer func2 to func1, based both on readability and speed. Thank you for 
having spent some time playing with me!
Francesco

On 19/12/2010 1.05, Steven D'Aprano wrote:
 > Well, let's try it with a working (albeit contrived) example. This is
 > just an example -- obviously I wouldn't write the function like this in
 > real life, I'd use a while loop, but to illustrate the issue it will do.
 >
 > def func1(n):
 >      result = -1
 >      done = False
 >      n = (n+1)//2
 >      if n%2 == 1:
 >          result = n
 >          done = True
 >      if not done:
 >          n = (n+1)//2
 >          if n%2 == 1:
 >              result = n
 >              done = True
 >      if not done:
 >          n = (n+1)//2
 >          if n%2 == 1:
 >              result = n
 >              done = True
 >      if not done:
 >          for i in range(1000000):
 >              if not done:
 >                  n = (n+1)//2
 >                  if n%2 == 1:
 >                      result = n
 >                      done = True
 >      return result
 >
 >
 > def func2(n):
 >      n = (n+1)//2
 >      if n%2 == 1:
 >          return n
 >      n = (n+1)//2
 >      if n%2 == 1:
 >          return n
 >      n = (n+1)//2
 >      if n%2 == 1:
 >          return n
 >      for i in range(1000000):
 >          n = (n+1)//2
 >          if n%2 == 1:
 >              return n
 >      return -1
 >
 >
 > Not only is the second far more readable that the first, but it's also
 > significantly faster:
 >
 >>>> from timeit import Timer
 >>>> t1 = Timer('for i in range(20): x = func1(i)',
 > ... 'from __main__ import func1')
 >>>> t2 = Timer('for i in range(20): x = func2(i)',
 > ... 'from __main__ import func2')
 >>>> min(t1.repeat(number=10, repeat=5))
 > 7.3219029903411865
 >>>> min(t2.repeat(number=10, repeat=5))
 > 4.530779838562012
 >
 > The first function does approximately 60% more work than the first, all
 > of it unnecessary overhead.





More information about the Python-list mailing list