Phil Hassey - game dev blog
Phil Hassey as Snidely Whiplash
"You can't buy awesomeness.
You're born that way."

Archive for the 'python' Category

64k tinypy – now with VM included

Thursday, January 10th, 2008

I’ve managed to build a simple VM into tinypy – modeled after the lua VM. It’s register based and “stackless” in the “it doesn’t use the C-stack” sense of the word. (Not in the, it does anything fancy like “stackless python” does sense.)

‘ve just reached the 64k mark, so that means anything I add into the code will require me to clean up other code to save space. I’ve already done a bit of that with good results. The one rule I follow in shortening code is that the code must retain readability, if not improve it.

Garbage collection is rather complicated, so I think I’ve decided to continue to leave that to libgc. I read some literature on the matter, and it sounds like I could write one, but it probably wouldn’t be very good. I’ve put it at the bottom of my TODO.txt list in the section labeled “Probably not going to happen”.

At present tinypy supports basic python code with functions and loops and lists and dicts and classes. At least, in some basic form. I’m looking towards adding in list comprehensions and *args **nargs to tinypy as those are two of my favorite python features. After that I’ve got a handful of functions I want to write and then some packaging work.

For the curious svn://www.imitationpickles.org/tinypy/trunk – ./run_julia_o3 to see it all happen. It depends on python to compile the bytecode (we’re not bootstrapped yet), libgc, and SDL.

64k tinypy – vm or no ..

Tuesday, January 1st, 2008

Well, things continue to come along with tinypy. I’ve been experimenting with a lot of different things with this. Some things I’ve tried:

– Assumed all infix operations were for numbers – was able to get quite a bit of speed at the sacrifice of things being “obvious”. I’ve disabled this for now, since I figure if you really want speed, you’d be using C anyways, not “tinypy”.

– Tried switching from passing around 16 byte structures to pointers to those structures. This didn’t work so well, because given my simple implementation it meant that any time any operation happened, another 16 bytes had to be allocated to store my floats. Not so hot for rendering fractals 😉 This caused a 10x slow-down. I reverted that out, but I copied that stuff to a branch for reference.

– I learned more about how libgc works. Basically, you need to use the GC_MALLOC and GC_REALLOC functions instead of the libc ones. libgc takes care of the rest. Also, if you integrate with libsdl (or some such library), you’ll need to do the memory management for it. There is hope – gc.h includes a function called GC_REGISTER_FINALIZER which makes it possible to trigger finalizers when an object is about to be freed. I’ve added some code to do this to tp.c, but haven’t tested it yet. That’ll get more testing when I start using libsdl for a game.

At present I’m debating between two options — leaving tinypy as-is and just cleaning it up, thus using it as a C code generator. Or changing it into a bytecode generator and writing a simple VM to run the bytecode. Advantages and disadvantages as I see them:

C code generator:

  • Quite simple and reasonably fast. Optimizations and goodies come from the compiler.
  • Really swell “FFI” (all functions are accessed directly and available as functions in C. Really, this means, no notable FFI at all.)
  • No need to do much more than tweaking stuff, etc.
  • No “eval” unless I use tinycc. Even then, no “safety”.

Bytecode + VM:

  • I’d be able to implement exceptions and tracebacks and stuff
  • I’d be able to build a “safe” environment for running scripts “eval”
  • Things would be a bit slower, but not much
  • FFI would be more complex (but I could probably work around that by auto-generating some goodies for people)

I’ll have to think about it for a bit .. I might just try making a fun little game with tinypy as-is, and work to keep the FFI really clean. And if I feel like upgrading tinypy, try to do it in such a way as to not break my “clean” FFI.

If you care to take a peak: svn://www.imitationpickles.org/tinypy/trunk – ./run_julia to see the julia demo. Must have libsdl and libgc installed. It’s sort of slow, but if you want to see it “fast” set JIT_DISABLE = False at the top of dumpout.py

64k “tinypy” keeps plugging along …

Friday, December 28th, 2007

So .. I had a hard time resisting working on my 64k version of “python”. I’ve been able to get quite a few features into it and I’ve gotten my julia demo up to near-C speed as well as tamed the crazy memory problems I was having.
I suppose the question I ponder is “why bother”? Well:

  • It’s fun 🙂
  • I’m learning the basics of parsing, code generation.
  • It might even be somewhat useful!

The first two don’t require much explanation, the third (usefulness?):

  • By keeping the codebase < 64k, it will be readable by mortals
  • By generating C code, it can build self-contained binaries easily
  • It has a really simple “FFI” which auto-generates many of the “FFI” wrappers for you
  • It’s sort of fast now (no promises for anything real)

It, of course, isn’t python, it just looks a bit like it. Notable differences are:

  • Access to members is like lua / javascript. x[“y”] and x.y mean the same thing.
  • Most infix operators only work with numbers. “x”+”y” won’t work. (Rational: makes numerical math fast)
  • It’s missing (and will never have) a bunch of really nice features. Syntax checking is notably weak. Maybe I should scrap my parser, etc and just use python’s.
  • No exception handling. Incorrect use of anything will result in a seg fault.

Notable similarities:

  • Language contains separate list and dict types. I thought about doing like lua / javascript / php and having a single type, but it just didn’t feel right.
  • It’s indented (duh)
  • Garbage collection via libgc

Well .. that’s about it. I expect before I’m done I’ll make a game with it, to see how it works in the real world. I’ve got a few more things on my TODO list to get done first. If you are brave, check out svn://www.imitationpickles.org/tinypy/trunk and run ./run_julia (linux) to see the julia demo.

Oh, and for all you “test first” folks, I’ve (more or less) been doing that. It’s made development considerably easier. See the bottom of “pylang.py” “dumbparse.py” and “dumpout.py” for all the testing fun.

64k version of python is 4234x faster* than c-python!

Saturday, December 22nd, 2007

To satisfy some sick curiosity of mine, I decided to write a miniature version of python in less than 64k of code. The code includes a tokenizer (which works rather well) a parser (which sort of works ) a translator (which does the job). All of those bits are written in python. The last bit is the C library I wrote to handle all the grit. That part isn’t so good.

To sum up, my implementation does very little, and what it does, it does very slowly. Most of the speed is spent up in memory allocation (my best guess). I wish I had a julia screenshot to show you, but I don’t think I have the patience, nor the RAM, to provide you with the pleasure.

If you wish to witness the horrors, feel free to check out svn://www.imitationpickles.org/tinypy/trunk … Please don’t look too closely. I think if I really want to work on this sort of stuff my time would be better spent either:

  • Learning the python C API or ctypes so I can do stuff without SWIG. (I’ve liked SWIG, but all the magic makes me nervous.)
  • Contribute to shed-skin, and add some features I’d like to it
  • Contribute to PyPy-Rpython, and add some features I’d like to it
  • Wait for py3k, where hopefully someone will write some magic code that uses the swell function annotation features to make fast things happen.

Of my options, learning the C-Python API (or maybe ctypes) is probably the easiest answer – I’d get all the fun of python, and I’d get my C speed. Between working on shed-skin and PyPy — my feeling is that I really wish shed-skin generated C code or that PyPy-Rpython wasn’t so huge and scary. All that said, I’ll probably just wait for py3k and hope 😉

*today is opposite day!

Pyrex – from confusion to enlightenment

Wednesday, December 5th, 2007

My last post explained my frustration trying to get pyrex to do *anything*. Since then, several people posted solutions and e-mailed me with more ideas (thanks allefant and Filip Wasilewski). My review was focused on the usability of pyrex as a python->C translator, since that’s what I was working on with both shed-skin and pypy/rpython. It didn’t hold up so well. This is because … pyrex ISN’T a python->C translator.

pyrex is its own special language that contains both python and C stuff. pyrex does not do type inference. What pyrex provides is a way to mix both python and python-like C code together in the same files. The trick to understanding pyrex is to know where the line between python and C is in pyrex.

Here are some of the gotchas I experienced. I wasn’t able to detail them in my previous post because I didn’t really “get it”. Now I think I do, so I’ll explain some stuff so you can try out pyrex without getting confused the way I did:

Gotcha #1: float() is a python function

cdef int a
cdef float b
a = 3
b = float(a)

Solution: use pyrex’s casting to avoid massive object-conversion speed penalties

b = <float>a

Gotcha #2: pyrex doesn’t do type inference

def set_video(int w, int h):
    s = Surface()
    s.surf = SDL_SetVideoMode(w,h,32,0)
    return s
pyrex: Cannot convert 'SDL_Surface *' to Python object

Solution: to access your C-members you must declare the variable’s type first

def set_video(int w, int h):
    cdef Surface s
    s = Surface()
    s.surf = SDL_SetVideoMode(w,h,32,0)
    return s

Gotcha #3: def makes python functions – which are slow

def set_pixel(self,int x, int y, int color)

Solution: To be able to access a fast version of a method in C and be able to access the same method in python you must define two versions of it

cdef _set_pixel(self,int x, int y, int color):
    pass # do this really fast
def set_pixel(self,int x, int y, int color):
    return self._set_pixel(x,y,color)

All that said, I think pyrex is really neat for writing extensions!  One of the best features it has is properties (which are like descriptors, only easier).  Just be careful if you use it to not mistake it for python.  Lastly, by using those tips I was able to get my julia example to be full speed.

Struggling with pyrex

Monday, December 3rd, 2007

In my last blog post, someone said I should check out pyrex. So I did.

pyrex-julia.png

Okay .. I must say, I found it extremely difficult to use and rather slow – 700 ms per frame (my pure C implementation is around 65 ms per frame). I had quite a bit of trouble figuring out the magic of getting anything to work, a few things seem pretty inconsistent. Thankfully I found someone (allefant – thanks) who helped me get some stuff working, but even he was rather baffled by some of the stuff we had to do to get it going.

Unfortunately, even after all our efforts, it was still slow. pyrex does so many magic things, that even with everything defined out to be C-ish, it still wraps ’em up so we don’t get the C-speed we want. I think the largest confusion is that pyrex marries both python and a magic brand of c-python code together in the same place – making it hard to know what “context” you are in at any point. To be kind, it does have some *really* cool features that Shed-Skin and PyPy/Rpython don’t have (such as properties). But the feeling of inconsistency and confusion I got while working with it just took the fun out of it for me.

Attacking PyPy

Friday, November 30th, 2007

Hey, more fractal fun tonight as I attack PyPy! I must admit, this effort was more challenging – PyPy is pretty big and scary, but I found the folks in #pypy to be quite helpful. exarkun helped me quite a bit in working out the details. (Apparently PyPy doesn’t use ctypes anymore, it uses rffi .. which is sparsely documented.) Anyway with exarkun’s help I got a crude SDL wrapper put together!

pypy-mandel2.png

Initially I just implemented my julia demo again, but I figured it would make for a boring blog entry to have the same pictures two days in a row. As it turns out, the julia was about 30% faster in PyPy than in shed-skin. Both shed-skin and PyPy appear to have similar limitations. shed-skin’s error messages are less cryptic than PyPy’s. Both FFI’s were somewhat challenging to work with, though I think I prefer shed-skin’s.

If you want to give it a whirl, download PyPy and my junk. The NOTES.txt file lists the command I used to build the executable. Sorry if the mouse interface is a bit lousy, but it was the best I could do in 2 minutes.

Taking on Shed-Skin

Thursday, November 29th, 2007

There’s this swell python to c++ compiler called shedskin. It’s really interesting. I took a few hours tonight to make it do something:

shedskin-julia2.png shedskin-julia4.png shedskin-julia3.png

Yep those are real-time julia fractals 🙂 If you dare – check it out (make sure python and SDL-devel are all setup):

wget http://www.imitationpickles.org/tmp/juliashed.zip ; unzip juliashed.zip ; cd juliashed ; python ss.py test.py ; make ; ./test

I’ve sent Mark an excessively long e-mail with my comments. I’ll spare you the trouble and just give the highlights:

  • My C++ skills don’t exist
  • python descriptors are probably the feature I would like to see most – so I could implement pygame.Rect style Rects!
  • misc packaging issues (see his previous blog post)
  • The README says it “does not scale very well beyond a few hundred lines” – so I guess I’ll wait a while before I try to make a game with it. (Even simple games I make are around 1500 lines.)

Anyway, it’s a cool project. I plan to keep an eye on it.

This just in – I made a python+pygame equivalent. The shed-skin version is ~100x faster! Also, the black areas in the middle of the shapes are caused by my access of out-of-bounds palette entries. I added the -b (bounds check) to the command line and fixed the bug. The bounds check gave me no noticeable speed penalty.

Galcon talk at pycon

Monday, November 12th, 2007

I’m working on writing up a proposal for a pycon talk. Which of these ideas sounds the most interesting?

– Galcon post-mortem – stuff that worked, stuff that didn’t – gfx, networking, python, etc. What I would do differently “next time”.

– Galcon modding – how to build a Galcon bot and other nifty tricks.

– Galcon business – all the grisly details of selling a game

– Something else?

I’d like to do an open space for people who want to have a Galcon bot writing competition as well as another open space for a real-people tournament.

Halloween game development

Thursday, November 8th, 2007

Marshie Attacks: Halloween Interactive Driveway Activity

Some really cool game dev going on there.  They used python, pygame, pysight, lasers, bedsheets and potato canons to create an interactive Halloween game!