Re: while True or while 1

Discussion in 'Python' started by BartC, Dec 16, 2010.

  1. BartC

    BartC Guest

    "Steve Holden" <> wrote in message
    news:...
    > On 12/12/2010 2:32 PM, Christian Heimes wrote:
    >> Am 12.12.2010 19:31, schrieb Steve Holden:
    >> $ python -m timeit -n20 -- "i = 0" "while 1:" " i+=1" " if i ==
    >> 1000000: break"
    >> 20 loops, best of 3: 89.7 msec per loop
    >> $ python -m timeit -n20 -- "i = 0" "while True:" " i+=1" " if i ==
    >> 1000000: break"
    >> 20 loops, best of 3: 117 msec per loop


    >> No argue with that! I was merely making a point that "while 1" executes
    >> different byte code than "while True". Readability is important but
    >> sometimes speed is of the essence. "while 1" is one of the few tricks to
    >> speed up tight loops a bit.

    >
    > OK, but the figures you quote save you 27.3 ms per million iterations,
    > for a grand total saving of 27.3 ns per iteration. So "a bit" is hardly
    > worth considering for most programs, is it?


    One these is 30% faster than the other. That's an appreciable difference,
    which you can't really just dismiss.

    And you can't tell what the overall effect on a program will be: perhaps the
    loop will be in a library function , which might be called billions of
    times.

    --
    Bartc
    BartC, Dec 16, 2010
    #1
    1. Advertising

  2. BartC

    Ethan Furman Guest

    BartC wrote:
    > "Steve Holden" <> wrote in message
    > news:...
    >> On 12/12/2010 2:32 PM, Christian Heimes wrote:
    >>> Am 12.12.2010 19:31, schrieb Steve Holden:
    >>> $ python -m timeit -n20 -- "i = 0" "while 1:" " i+=1" " if i ==
    >>> 1000000: break"
    >>> 20 loops, best of 3: 89.7 msec per loop
    >>> $ python -m timeit -n20 -- "i = 0" "while True:" " i+=1" " if i ==
    >>> 1000000: break"
    >>> 20 loops, best of 3: 117 msec per loop

    >
    >>> No argue with that! I was merely making a point that "while 1" executes
    >>> different byte code than "while True". Readability is important but
    >>> sometimes speed is of the essence. "while 1" is one of the few tricks to
    >>> speed up tight loops a bit.

    >>
    >> OK, but the figures you quote save you 27.3 ms per million iterations,
    >> for a grand total saving of 27.3 ns per iteration. So "a bit" is hardly
    >> worth considering for most programs, is it?

    >
    > One these is 30% faster than the other. That's an appreciable
    > difference, which you can't really just dismiss.


    Anecdotal evidence says it is easily dismissed:

    I had a routine that processed records from a table using custom, on the
    fly, code. I could either use exec for each record to do the work, or
    create a function that would then be called. I timed exec vs function,
    and found the function style to be about 200% faster... Eureka!, I
    thought. After putting the functional method in place, a run that took
    about 16 minutes using the old exec method ran two (2!) seconds faster.

    Great learning experience, for both the function method (which I
    prefer), and the need for profiling.


    ~Ethan~
    Ethan Furman, Dec 16, 2010
    #2
    1. Advertising

  3. Ethan Furman <> writes:

    > ...I timed exec vs function, and found the function style to be about
    > 200% faster...


    So it finished before it started?

    --
    Arnaud
    Arnaud Delobelle, Dec 16, 2010
    #3
  4. BartC

    Terry Reedy Guest

    On 12/16/2010 7:23 AM, Steve Holden wrote:
    > On 12/16/2010 5:44 AM, BartC wrote:


    >> One these is 30% faster than the other. That's an appreciable
    >> difference, which you can't really just dismiss.
    >>
    >> And you can't tell what the overall effect on a program will be: perhaps
    >> the loop will be in a library function , which might be called billions
    >> of times.

    >
    > It might. But if the code it is calling does *anything* at all
    > significant I can promise you that spending an extra 30% purely on the
    > looping construct will still make a negligible difference to a program's
    > execution time, and there are almost certainly going to be many other
    > aspects of performance that will yield greater benefits from tuning.
    >
    > I realise that there are going to be some people who just flatly say
    > "since 'while 1:' is quicker I am going to use it every time", and that
    > their programs will still work. And I still maintain that (for English
    > speakers) "while True:" is to be preferred.
    >
    > sholden@lifeboy ~
    > $ python -m timeit -- "i = 1" "while True:" " i += 1" " if i ==
    > 1000000: break"
    > 10 loops, best of 3: 157 msec per loop
    >
    > sholden@lifeboy ~
    > $ python -m timeit -- "i = 1" "while True:" " i += 1" " if i ==
    > 1000000: break" " x = i+1"
    > 10 loops, best of 3: 238 msec per loop
    >
    > sholden@lifeboy ~
    > $ python -m timeit -- "i = 1" "while 1:" " i += 1" " if i ==
    > 1000000: break"
    > 10 loops, best of 3: 116 msec per loop
    >
    > sholden@lifeboy ~
    > $ python -m timeit -- "i = 1" "while 1:" " i += 1" " if i ==
    > 1000000: break" " x = i+1"
    > 10 loops, best of 3: 195 msec per loop


    This are all Python2 timings.

    > If binding a simple arithmetic expression adds more to the loop than the
    > difference between "while 1:" and "while True:" you are wasting your
    > time thinking about the savings under all but the most rigorous
    > circumstances.


    *Especially* when the 'problem' has been fixed in Python 3.

    --
    Terry Jan Reedy
    Terry Reedy, Dec 16, 2010
    #4
  5. BartC

    Ethan Furman Guest

    Arnaud Delobelle wrote:
    > Ethan Furman <> writes:
    >
    >> ...I timed exec vs function, and found the function style to be about
    >> 200% faster...

    >
    > So it finished before it started?


    Hmmm....

    Let me check my calculator...

    ..

    ..

    ..

    Ah! Okay, that was 200x faster. :) I think -- it was a few months ago
    now, and my numbers might be off a bit, but I was definitely impressed
    with A) how much faster the function style was, and B), how very little
    time it saved me.

    ~Ethan~
    Ethan Furman, Dec 16, 2010
    #5
  6. BartC

    BartC Guest

    "Steve Holden" <> wrote in message
    news:...
    > On 12/16/2010 5:44 AM, BartC wrote:


    >> One these is 30% faster than the other. That's an appreciable
    >> difference, which you can't really just dismiss.


    > sholden@lifeboy ~
    > $ python -m timeit -- "i = 1" "while True:" " i += 1" " if i ==
    > 1000000: break"
    > 10 loops, best of 3: 157 msec per loop


    > $ python -m timeit -- "i = 1" "while 1:" " i += 1" " if i ==
    > 1000000: break"
    > 10 loops, best of 3: 116 msec per loop


    I used a single loop counting to 10 million, and the timings were roughly
    2.5xx and 1.8xx seconds, on Python 2.5 (1.35 and 1.05 seconds inside a
    function).

    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).

    --
    Bartc
    BartC, Dec 16, 2010
    #6
  7. BartC

    Ian Guest

    On Dec 16, 4:34 pm, "BartC" <> wrote:
    > def p2(n):
    >   p=1
    >  whileTrue:
    >     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.


    def p2(n):
    return 1 << n.bit_length()
    Ian, Dec 17, 2010
    #7
  8. 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.



    --
    Steven
    Steven D'Aprano, Dec 17, 2010
    #8
  9. BartC

    Francesco Guest

    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.
    Francesco, Dec 28, 2010
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timothy Fitz

    while 1 vs while True

    Timothy Fitz, Dec 13, 2004, in forum: Python
    Replies:
    16
    Views:
    625
    Terry Reedy
    Dec 15, 2004
  2. bdb112
    Replies:
    45
    Views:
    1,334
    jazbees
    Apr 29, 2009
  3. Krister Svanlund

    Re: while True or while 1

    Krister Svanlund, Dec 12, 2010, in forum: Python
    Replies:
    6
    Views:
    234
    Arnaud Delobelle
    Dec 14, 2010
  4. Andrea Crotti

    while True or while 1

    Andrea Crotti, Jan 21, 2012, in forum: Python
    Replies:
    0
    Views:
    148
    Andrea Crotti
    Jan 21, 2012
  5. Chris Angelico

    Re: while True or while 1

    Chris Angelico, Jan 21, 2012, in forum: Python
    Replies:
    16
    Views:
    468
    Steven D'Aprano
    Jan 24, 2012
Loading...

Share This Page