Typing system vs. Java
Markus Schaber
markus at schabi.de
Fri Aug 10 13:45:27 EDT 2001
Hi,
Alex Martelli <aleaxit at yahoo.com> schrub:
> Far more useful than (Java/Eiffel/&c) type declaration (which still
> need dynamic dispatching of methods) is supposed to be runtime caching
> of the dispatching (I believe that's what Self uses, for example).
Well - some implementations create an array of member offsets for every
different implementation of a type (Class or Interface). Then an Object
gets just a list of arrays.
Now, when you assign an object to a variable of type t, the compler
just gets a pointer to the interface array from the object (which
usually is O(1) without multiple inheritance). When you always keep the
interface array pointer together with the object pointer, you only have
to do this lookup at explicit casts - at the cost of doubling the size
of object references.
And every function and attribute access means one pointer indirection,
as the offsets of the members in the array are fixed - the types are
statically known.
This means if you want to access a objects member: Look into the offset
table, position X (which is known at compile time), and add this value
to the object address - et voilá, this is the members address.
Some good old cisc machines can do such calculations in one assembly
instruction, and every reasonable cisc processor should do this in less
than 6 instructions.
Python (as any other language without static types) has to do some (one
per namespace) complex dictionary lookups including hash calculations
and string comparisons here, which is _much_ slower than with fixed
types.
This applies with interpreted languages as much as with byte-code- or
machine-code languages.
Even with caching, dynamic lookups will never be as fast as static
lookups. And with caching, you get in trouble when multi-threading:
Imagine a method that signals another thread, and this thread replaces
the method. But your own thread has cached the old method...
> Python can be fast enough for most tasks today (and more every day,
> as machines get faster). It could be fast enough (without extensions)
> for a few more tasks (perhaps) if very substantial resources were
> expended in adapting advanced optimization technologies (I don't
> think projects to that end in the past, such as Vyper, went anyplace,
> but that could change in the future -- if enough people thought it
> matters, strongly enough to be willing to donate time, money and/or
> skills to the purpose). Perhaps some language changes might make
> optimization slightly easier, although I have my doubts whether such
> slightly easier optimization could be achieved without losing the key
> characteristics of Python's simplicity and power (untrammeled
> signature based polymorphism, for example: if the libraries started
> being full of type-testing to make optimizer-writers' life slightly
> easier, that would strike a huge blow to Python's power AND
> simplicity).
As long as Python doesn't allow self-modyfing code (means a block of
code is immutable once compiled), it should be no problem (except
implemenation effort) to replace the byte-code compiler with one that
provides machine code.
But this isn't the main slowdown - it is the dynamic lookup for every
access. But when we change this, we wouldn't have python any more.
>> I think that adding features to allow Python powerful enough to
>> remove the
>> need for extensions would be worth a little bit of extra complexity.
>> I
>
> I could hardly disagree more deeply, profoundly and totally than in
> fact
> I do. Nothing will remove the need for extensions, although their use
> may become less frequent.
Fully agree. The only way to get around this is to have _very good_
optimizing compilers, and to include every needed machine-specific
detail as a language feature.
In a project at our university (Ulm, Germany), we implement an OS using
a java-like language (older researches used an oberon derivate). We
included machine level things using a "virtual" class called Magic.
This class doesn't physically exist, the compiler directly generates
the corresponding machine code. This way, we have direct access to
memory (Magic.mem8[]), Intel IO-Space port commands (Magic.Out(),
Magic.In) and - for use in the memory management classes - magic.Cast.
We even can declare methods that use interrupt stack frame instead of
normal one.
But there are still some places where we have to use our nice inline
feature - sometimes for speed reasons (Memcopy, TCP-Checksum etc), and
the other times because they are very specific and needed only at one
place (MMU-Programming, TSC-Register access etc).
If you don't include assembly into the language, you always will have
to use extensions that don't follow the language's rules.
markus
--
Defend democrathy and freedom!
More information about the Python-list
mailing list