Well I've finally registered with SF as "xigmorph". Not sure if I'll have the time for active development, but I sure am interested
My observations from over 600 days of use are that stability is not an issue, the implementation is bulletproof, it didn't crash a single time and handled well over 160 billion(!) packets. However, packet interpretation and object creation is also one of its major performance killers. I've found that performance could be increased by up to 66% (in my test environment, running 5.3.1 on Win2k3 x86) if a reference instance of every packet class is kept and cloned instead of always creating new instances. This will be particularly useful with incoming packets, since the constructor serves no purpose with those as they need to be unpacked.
As for memory usage, there might be room for improvement, but not much. The script I'm running on DriftWars (which is fairly complex) uses 8M with a total of ~24M allocated, the pyinsim running alongside uses approx. 6M but allocated 32M. I definitely prefer a slightly worse memory footprint over the performance impact of aggressive garbage collection.
Regarding the memory leak issues, I know of no solution that's entirely obscure to the script writer. We do need the object reference in the handler array and it will leak if the object is unset() because it will not be unset until the reference in the handler array is unset. The solution I have in mind is a plugin manager that takes care of all references, but for it to work, script authors must NEVER unset() loaded plugins themselves (instead use $plugin_manager->unload(...)) and must not create references to objects handled by the plugin manager (or if they do, unset them prior to an unload() call). I'm curious what kind of magic plugin system Mark is working on
And finally, I will be focusing on all the concepts I've neglected in the past, namely interfaces, abstract classes, magic methods and type hinting. A balance must be found between a semantically robust syntax and efficient code design. For example, this might be misleading at first, but to me it makes sense semantically:
<?php
$dispatcher[ISP_TINY] = array($this, 'tiny');
?>
Don't be fooled by the syntax, the dispatcher class implements ArrayAccess, this is
not an assignment to an element of an array. Well, it is, but $dispatcher is not the array, it's an object behaving like an array. What happens is the dispatcher's offsetSet() will add the received array to its list of handlers for the passed packet type:
<?php
// Sadly we cannot use type hinting as it would
// differ from the ArrayAccess interface's signature
public function offsetSet($packet_type, $handler)
{
if(is_int($packet_type) && is_callable($handler))
{
$this->handlers[$packet_type][] = $handler;
}
// Instead of the else, the conditional above could return.
// We need to discuss coding standards :P
else
{
// Exceptions or error reporting? I'm for exceptions.
throw new InvalidArgumentException('...');
}
}
?>
Thoughts?
Edit: Also, regarding the project title, will the "new" project be called PHPLFS?
Another edit: Since I'd like the plugin system to be as robust as possible, it should not allow for inclusion of plugins that cause fatal errors. Anyone got a better solution for checking than:
php -l plugin_file
?