[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Cheap COW clones for surfaces



I have been thinking for some time about how to optimise Pygame Zero games on Raspberry Pi. Most Pi models have multiple cores and an obvious improvement is to parallelise. Logic has to be synchronous but I would like to offload painting the screen to a separate thread.

The problem I would have is in passing references to mutable objects between threads. Primarily this applies to Surface objects, which are mutable and expensive to copy. If I have a draw thread that maintains a queue of screen blit operations, I want the queue to hold references to surface data that won't change even if I later mutate the surfaces in the logic thread.

If I was writing a game myself, I could work around this easily by taking copies of surfaces that I want to mutate again in a different thread. But as a game framework I don't know how users will use the surfaces in their code. I would have to copy everything in case the logic thread updates it - and that is unacceptable overhead given that I expect mutation to be very rare.

A solution could be copy-on-write clones for mutable objects. For example, Surface.__copy__() would return a new PyObject referring to the same SDL surface, incrementing a refcount for that surface data. All mutation methods would create a single-user copy of the surface if the refcount was higher than 1. Code that doesn't use clones would pay a small overhead in performing refcount checks. Refcount checks could be guarded by the GIL.

This solves my problem, as I can then clone every surface when passing it to a draw thread, and this becomes a very cheap operation. If the logic thread does mutate a surface it creates a copy in that thread.

How feasible is this? Are there other applications that could benefit from it? I could do it in Pygame Zero by wrapping all Surface objects in a Python class but this makes Pygame Zero a thicker and slower layer around Pygame (the goal is to be "training wheels" for Pygame) and creates more pitfalls when users dig into Pygame proper.