The way to a faster python [was Python IS slow !]

Christian Tismer tismer at appliedbiometrics.com
Wed May 12 14:48:34 EDT 1999


Martijn Faassen wrote:
> 
> Christian Tismer wrote:
> >
> > Martijn Faassen wrote:
> > >
> > > Christian Tismer wrote:
> > > >
> > > > Martijn Faassen wrote:
> > >
> > > [snip]
> > > [Christian describes problems with statically typed globals interacting
> > > with Python]
> > >
> > > Okay, let's remove globals from Swallow for now, then. :) Or make them
> > > inaccessible to Python, perhaps.
> >
> > Danger, danger! :-)
> 
> Thank you, my faithful robot. Oh, no, that was the Timbot, right?
> (obscure lost in space reference :)

Not yet. But I fear it will not take long until
Uncle Timmy takes us down to the earth :)

[string et al]

> You are right, but in my head I was thinking about making a subset of
> commonly used modules (or at least functions in them, and later on
> classes), and make Swallowed variants. Of course this can get a mess,
> but Swallow should use those swallowed modules preferably. Perhaps this
> is transparant:
> 
> string.strip(str)
> 
> Error: The Swallow version of the string module does not support
> 'strip'.

Can't be. string is a standard module which is per se not
swallowed, unless this will be so in some future.

> swallow.string.strip(str)

This might work.
If you look into string.py, you will see that it
defines everything, and later removest most of it
by importing the strop module.
strop is a builtin which should be immutable enough to
be a swallow module already.

Then, after importing string, swallow could recognize that
most entries in its dict are coming from strop, which allows
to generate a frozen swallow.string module with these entries,
but immutable. I believe that eventually remaining functions
could be deduced to be swallowable as well, since they all build
upon some builtins anyway.

> Perhaps the transparant option is best, for the subset reason; any
> Swallow code should be Python code (but not vice versa).

And if I later change string.py? How to invalidate the
generated swallow code?

...

> Right, as I describe before. This is fairly inevitable if one wants
> Swallow. Of course *Python* has no problem calling Swallow code, so that
> the Swallow libraries can eventually replace parts of the C extension
> libraries. (yeah, yeah, a maniacal plan! Soon Timbot will come and say
> "sorry guys, can't/shouldn't be done, because <brilliant explanation>",
> I keep fearing :)

Me too. :)

Note that it is a very old wish of mine to get rid of
all C extension modules, even the C core, and do this all in
Python, which then could be expanded into C or whatever,
interpreted by a tiny machine, or any combination of this.

At least for this issue I don't fear Timbot since he knows
my thoughts about that and doesn't take them serious,
which gives em the freedom of the insanes. Welcome in the club.

<big schnipp/>

> > Dynamic things should sit upon static things, the same
> > way as Python is constructed itself.
> 
> Agreed! This was the idea, sorry I didn't express it well and got
> muddled in details. :)

I know:-) it was just this "subset" idea which led me
to talk too much. If this subset is little more than tiny,
whoops, the whole elephant is pulled back in, while we
wanted to pick just a flee.

> Swallow is a subset of Python, plus static typing information in a
> dictionary. (or possibly this information is more integrated in the
> code, but that would involve preprocessors which makes Swallow<->Python
> code interchange more difficult).

Another example where we could abuse the docstring property,
of course compatible with docstring testing (ahem, no I'm not here).

> Initially the plan is to support Swallow functions. Classes come later.
> We will need to support 'built-in type' object semantics however (such
> as list.append()) right away, though. To avoid class/type dichotomy in
> the future it's good to think this through carefully in advance so that
> classes can be added smoothly.
> 
> The backend of Swallow is either a fast interpreter, automatically
> generated C code, or both can be tried.
> 
> Make Swallow varieties of most built-in functions. Then go on to some
> modules, such as string.
> 
> Then see about classes.
> 
> How does this outline of a plan sound?

Sounds good. Now there's nothing more than
a huge heap of work. Let me try to explain.

Before coding any line, here's a subheap of work:
Define the transformations which are necessary to gain a speedup.
You know that the interpreter itself is just 30% of the time.
Even if that can go away, I wouldn't invest my time.
You need to figure out what it helps you if you know
the type of certain things. If you still go through
the C api, there is only small win.

I've been working a little on this heap already.

You can of course avoid a couple of temporary expression
results to always create objects on the interpreter stack, but
generate inlined c code for this. You get then the problem
to decide wether and when you need to convert an int back
into an object.

Well, but if you want to gain real speed, you must have special
treatment of strings, tuples, dicts, lists. Avoid to use the
object protocol, but prove that you can access things directly
since you know the type.

This has the nice side effect that you have to re-define
almost every builtin Python object to several degrees,
create many special macroes, especially for directly indexing
of these. This means, you need to lift an object description
from the C level up into Python, and express the various
accessor function variants in a way which can be used for 
code generation.

Besides that, the inference machine must be built which deduces
which reduction can be made in what context.

I believe this is about a year of moonlighting for the 
two of us. But this, given enough locality and simple enough
types, would be able to run at C speed.

Do you have so much breathe?

------------

Now, here what I've been planning if I 
have several months of spare time.

As a proof of concept, I'd take ceval.c, and write a Python
equivalent of it. This is not very hard, everything can be done
with static types, and every call of C functions can stay for the
moment, since this isn't worse that now.

Stack and other tables would be emulated by lists, tuples
and so on, where in this case we would not have to solve
the general access problem, just use the knowledge that
we are emulating a static thing.

This simulator in Python should be able to produce a C source
with nearly the functionality of ceval.c .

If this is not slower than, say, a factor of three to five
compared to the original, then we have proven the concept.
With the side effect that alternative interpreters can be
generated and tested much easier than by coding them in C.

Then, I would start with the most urgent builtin objects
and try to do the same. And while doing that, I would
define the additional access functions which say
"if this and that is known, this can be done instad of..."
and given all of that, you can make a table of shortcut
expressions for given type information.

Swallow can then try to optimize away whatever possible,
and expand object access calls into short pointer
expressions, if it knows enough in the current context.
Note that this technique partially also works for
standard Python.

---------

If I'm not too wrong, it is something like that what
you are undertaking. Maybe there are some shortcuts
or better approaches.

I have no idea if one should start this at all, but I like
very much to think about it.

insaneous'ly y'rs - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home




More information about the Python-list mailing list