R
Ron Adam
Ron Adam wrote:
...Is it possible to make the argument optional for while? That may
Yes, it is technically possible -- you'd need to play around with the
Dreaded Grammar File, but as Python grammar tasks go this one seems
simple.
allow for an even faster time?
No, there is no reason why "while 1:", "while True:" once True is
a keyword, and "while:" were the syntax extended to accept it, could
or should compile down to code that is at all different.
while:
<instructions>
It would be the equivalent as making the default argument for while
equal to 1 or True. Could it optimize to single cpu instruction when
that format is used? No checks or look ups at all?
"while 1:" is _already_ compiled to a single (bytecode, of course)
instruction with "no checks or look ups at all". Easy to check:
1 0 SETUP_LOOP 19 (to 22)
3 JUMP_FORWARD 4 (to 10)
6 JUMP_IF_FALSE 11 (to 20)
9 POP_TOP13 CALL_FUNCTION 0
16 POP_TOP
17 JUMP_ABSOLUTE 1025 RETURN_VALUE
the four bytecodes from 10 to 17 are the loop: name 'foop'
is loaded, it's called with no argument, its result is
discarded, and an unconditional jump back to the first of
these steps is taken (this loop, of course, will only get
out when function foop [or the lookup for its name] cause
an exception). (The 2 opcodes at 6 and 9 never execute,
and the opcode at 3 could be eliminated if those two were,
but that's the typical kind of job for a peephole optimizer,
an easy but low-returns project).
Note the subtle difference when we use True rather than 1:
6 JUMP_IF_FALSE 11 (to 20)
9 POP_TOP
10 LOAD_NAME 1 (foop)
13 CALL_FUNCTION 0
16 POP_TOP
17 JUMP_ABSOLUTE 325 RETURN_VALUE
_Now_, the loop runs all the way through the bytecodes
from 3 to 20 included (the opcodes at 0 and 21 surround
it just like they surrounded the unconditional loop we
just examined). Before we can get to the "real job" of
bytecodes 10 to 17, each time around the loop, we need
to load the value of name True (implying a lookup), do
a conditional jump on it, otherwise discard its value.
If True was a keyword, the compiler could recognize it and
generate just the same code as it does for "while 1:" --
or as it could do for "while:", were that extension of
the syntax accepted into the language.
As to the chances that a patch, implementing "while:" as
equivalent to "while 1:", might be accepted, I wouldn't
be particularly optimistic. Still, one never knows!
Alex
Thanks for the detailed explanation. I would only suggest 'while:' if
there was a performance advantage. Since there is none, the only
plus is it save two keystrokes. That isn't reason enough to change
something that isn't broken.
Thanks for showing me how to use compile() and dis().
1 0 SETUP_LOOP 12 (to 15)
3 JUMP_FORWARD 4 (to 10)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP 18 RETURN_VALUE
Yes, this is as short as it gets.
In the case of using 'while 1:' it seems to me you end up loosing
what you gain because you have to test inside the loop which is more
expensive than testing at the 'while' statement.
1 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (a)
2 6 SETUP_LOOP 18 (to 27) 12 JUMP_IF_FALSE 10 (to 25)
15 POP_TOP
3 16 LOAD_CONST 1 (0)
19 STORE_NAME 0 (a)
22 JUMP_ABSOLUTE 9 30 RETURN_VALUE
1 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (a)
2 6 SETUP_LOOP 36 (to 45) 12 JUMP_IF_FALSE 28 (to 43)
15 POP_TOP
3 >> 16 LOAD_CONST 1 (0)
19 STORE_NAME 0 (a)
4 22 LOAD_NAME 0 (a)
25 LOAD_CONST 1 (0)
28 COMPARE_OP 2 (==)
31 JUMP_IF_FALSE 5 (to 39)
34 POP_TOP
5 35 BREAK_LOOP
36 JUMP_ABSOLUTE 9
This requires twice as many instructions, 12 vs 6. So it's probably
better to avoid 'while 1:' or 'while True': if possible. But it is
nice to know 'while 1:' is 20% faster than 'while True:' in those
situations where you need to use it.
_Ron Adam