A checklist for framework developers

So, there have been some new frameworks being posted on reddit, with the expected result of receiving a lot of hate and criticism. I can kind of understand both sides here, since just about a year ago I’ve seen similar responses towards my PHPixie. Since then the flames calmed down and it has now a considerable userbase with 386 installs in the last 30 days. The important part here is to be able to take in constructive criticism and carry on making your project better. I’ve learned a few things the hard way as I went, and I’d like to share them with other people willing to release their brainchild to the world.

  • Tests – you must have those to be taken seriously. Even if it’s the first version, alpha or anything. The tests are the first indicator that you are putting real effort in
  • Find a niche – There has to be something about your framework that makes it stand out, and you have to focus on it. I really pushed a lot of effort behind the “great performance” argument. I also submitted it to Techempower Framework Benchmark Suite to prove it. Don’t ever state something while not having anything to back it up with
  • Read a book – there should be no singletons, god objects, shared state or anything like that in a modern app
  • Write docs – That includes writing docblocks, generating an API documentation from those docblocks, writing some tutorials and a nice about page.
  • Be prepared to compare it to existing frameworks – there has to be something better with your approach. If there isn’t don’t bother releasing it.
  • Use PSR-2 – I made the mistake of writing PHPixie in the style I liked and then had to rewrite it. The style must suite the majority, not just you. You’re not making it for yourself
  • Don’t expect any help or pull requests from the very start
  • Support your users as much as possible, at least install some forums script to be able to talk to them
  • Buy a domain and spend some time on site design. Make it look legit
  • Commit frequently – Your Github history has to indicate your project is not dead
  • Participate in the community – You can’t expect people to help you with your project if you ignore theirs
  • Don’t give up

If this sounds like too much work, just pick a smaller project. It’s better to make a smaller masterpiece than a big ball of mud.

PHP memory leaks and garbage collection

Historically memory leaks have not been a huge concern for PHP development. Since PHP processes exit after processing a request all used memory is deallocated. But that doesn’t mean we are free to not care about memory management altogether. If your application is processing several requests at the sime time, the total amount of wasted memory may add up to a hefty number.

With projects like ReactPHP become more popular and widely used PHP is entering the domain of permanently running processes and we all look forward to using those to speed up our applications. But for that to become a reality our applications and frameworks have to be carefully rewritten to prevent memory leaks, since even the smallest one can grow to eat all available memory in a span of a month.

PHP utilizes reference counting to decide when a object can be removed. Eachtime you assign an object to a new variable its refcount is increased by one


$a = new stdClass;
$c = $b = $a;
xdebug_debug_zval('a'); //refcount = 3
unset($b, $c);
xdebug_debug_zval('a'); //refcount = 1

When a refcount reaches 0 the memory is deallocated. This is the first thing you have to think about when instantiating multiple objects, e.g. your domain entities. You have to make sure that the references to them don’t hang around after they are no longer needed. One good rule of thumb for doing so is avoiding global state as much as possible. If all your object references are inside some local scope, it’s much easier to keep track on whats happening to them than when they are scattered all over the place.

Now let’s see wht happens here:


$a = new stdClass;
$b = new stdClass;

$a->b = $b;
$b->a = $a;

xdebug_debug_zval('a'); //refcount = 2
xdebug_debug_zval('b'); //refcount = 2

unset($a, $b);

After we unset both $a and $b variables we have no way of accessing those objects from our application anymore, but their refcount is not 0. Since what was $a still references $b and vice versa both their refcounts are 1, and they won’t be removed from memory. And that is what a memory leak is. In a perfect world we would try to avoid this as much as possible, but this might be hard to achieve. PHP tries to detect such unreachable objects using it’s garbage collector. When it’s called it looks through the memory for lopps in object references and deallocates them, thus saving us memory. But this process is not free, running it too often may slow down the execution time. The PHP manual states the impact is about 7% which is quite considerable.

I have found a nice trick that works for me to both have gc collection and get an almost insignificant performance impact: to run the garbage collection only after the end of each request. You can do it like so:


gc_enable();
gc_collect_cycles();
gc_disable();

Basically we are enabling garbage collection, running it once and disabling it again. This way we ensure that it runs only a single time per request.