On 24/03/2016 18:10, Steven D'Aprano wrote:
On Fri, 25 Mar 2016 12:01 am, BartC wrote:
Python 3 (on Windows) might take 200ns. Clisp is 1300ns (interpreted,
presumably). Ruby 170ns. Lua 80ns. Mine 10-20ns. Unoptimised C is 4ns,
but this is not executing code indirectly as most of the rest have to.
"Might"? Are you making those numbers up?
No.
[Timings include loop overheads that need to be factored out.]
Then those numbers are pointless.
Yes, they would need some adjustment to do this stuff properly. FWIW the
loop overheads were about 30% in Python, 40% in Ruby, and 20% in mine.
The Python figure, for example, might be
199ns for the loop overhead and 1ns for the function call, or 1ns for the
loop overhead and 199ns for the function call. Or anything in between. How
do you know which is which?
It sounds like they would both need some work!
So there might be room for improvement, but those faster languages are
also simpler.
In the case of C, the line is limited to working with some specific type
(say, an int32). Even there, if the addition might overflow, the behaviour
is undefined and the compiler can do anything it wants (including time
travel,
I'm pretty sure it can't do time travel...
or erasing your hard disk).
In the case of Python, the line will work with a potentially infinite number
of types: int, float, complex, Fraction, Decimal, subclasses of all the
above, custom numeric types, and anything else that quacks like a number.
Yes, it has to do some dynamic type dispatch. All the languages except C
were dynamic (C cheats in so many ways).
However, my bit of code (a for-loop calling an empty function) doesn't
on the surface, do anything that requires type dispatch, or does it?
This is where we come to the first differences between how Python works
and how, say, my language works (I don't know about Lua, Ruby and Lisp.)
Python bytecode for empty function bill():
4 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
Inner loop calling bill():
>> 13 FOR_ITER 13 (to 29)
16 STORE_FAST 0 (n)
8 19 LOAD_GLOBAL 1 (bill)
22 CALL_FUNCTION 0 (0 positional... )
25 POP_TOP
26 JUMP_ABSOLUTE 13
My bytecode for function bill():
0: 000 --------- return
My inner loop bytecode:
1: 005 %4:
1: 006 --------- call [&t.bill], 0
1: 006 --------- to_f %4, [t.start.av$1:-1]
Half the explanation is right here: I use 1 op in the function, and 2 in
the loop. Python uses 2 in the function, and 6 in the loop.
(I use a dedicated repeat-N-times loop that needs no explicit loop
variable, only an internal integer count. I use a special 'proc' form of
function with no return value. And I use static functions so the
byte-code knows the function being called, and knows it returns no value
that needs to be popped.)
--
Bartc
--
https://mail.python.org/mailman/listinfo/python-list