Introduction to PCS

Read : 2,711 times
(2 votes, average 4.50 out of 5)

1 - Historical needs

Mixing C and PHP code in a PHP extension is a long-awaited feature. Improvements in maintainability are obvious, and it is now widely agreed that porting a lot of non performance-critical C code to PHP would be welcome. Today, the PHP 7 performance improvements still provide more potential candidates for a port to PHP code.

In theory, including PHP code in an extension and executing it has been possible for a long time. Unfortunately, two important issues were hard to solve :

Those constraints may be acceptable when considering two or three scripts, but we are potentially considering hundreds of scripts, recompiled from scratch at the beginning of every request (note that embedding the MongoDB library in the MongoDB extension, for instance, represents about 60 scripts).

For these reasons, despite some exceptions, mixing C and PHP code in an extension is very rare today.

2 - Solutions

Unlike other PHP extensions, PCS does not expose features to the user space, but provides a service to other extensions. The schema below shows how PCS interacts with other extensions and the PHP core :

Client extensions have the possibility to interact with PCS after the PHP code registration step but, in most cases, they don't, fully delegating the management of their PHP code to PCS.

Let's see how PCS solves the issues I was talking about :

2.1 - Opcode cache compatibility

Opcode caches, as any cache, require a key for each object they cache. So, trapping zend_compile_string() is not an option, as there is no way to get a key to cache the compiled contents. So, scripts must be executed via zend_compile_file(), and we need to provide unique and persistent paths to identify each of them. PCS maintains a stream wrapper for this. This stream wrapper, using the 'pcs://' prefix, maintains a tree of virtual files registered by the client extensions. As these files cannot be overwritten, the unicity between the stream-wrapped path and the file's contents is guaranteed.

This is the first required step but that's not enough. When detecting a 'stream-wrapped' path, opcode caches have no way to know whether the path should be cached or not. Some should, like 'pcs://' ones, but many are transient by nature and must not be cached. Today, the 'logic' is to cache everything belonging to the file/plain and 'phar' wrappers, and to ignore the rest. The easy way would be to add 'pcs' to the list, but I don't work the 'phar' way ;). So, an additional stream operation, named 'cache_key', will be proposed soon for inclusion in the PHP core. This operation will be used by opcode caches to ask stream wrappers whether a given URI must be cached, and which key to use (the key may potentially differ from the URI).

2.2 - Minimizing load overhead

Several ways were imagined to avoid loading everything at the beginning of each request :

So, PCS combines these constraints and uses two load mechanisms :

The reasons :

Note that the autoloader is based on a symbol map. File paths and names are free, and there's no limit to the number of classes/functions/constants defined in a single file. Symbols are automatically extracted from the PHP source at registration time.

2.3 - Other features

You may also note that :

3 - Potential uses

Several have been given in past discussions :

Joomla SEO powered by JoomSEF