, 3 min read

PECL's Yaml Way Faster Than Symfony's Yaml

PECL is the PHP Extension Community Library. These extensions are written in C. Symfony is a PHP web application framework written in PHP.

Initially I just wanted to reduce the dependencies in Saaze, so I installed PECL PHP package yaml. When I compared run-times between the original, "old" Symfony-based Yaml parsing and the new C based Yaml parsing, I noticed that run-time went down from 1.3s to 0.9s. I then found out that more than 40% of the run-time in Saaze is Yaml parsing.

PHP documents an official Yaml parser: yaml_parse. Saaze instead uses the Symfony supplied Yaml parser.

1. Installation. Here are the steps to install the yaml PECL from source. Arch Linux and Ubuntu provide precompiled packages. In that case there is no need to go through below steps.

  1. Download latest yaml package from PECL
  2. tar zxf yaml...
  3. Run phpize
  4. Run ./configure
  5. Run make. Library is here modules/yaml.so.
  6. Run make test. Conducted 74 tests, which all succeeded.
  7. As root copy modules/yaml.so to /usr/lib/php/modules
  8. Edit /etc/php/php.ini and add extension=yaml

Now you should see a yaml entry when calling phpinfo() or php -m or php -i.

2. Code changes. I changed function parseEntry() in Entry.php and added time measurements:

$t0 = microtime(true);
. . .
$GLOBALS['YamlParser'] += microtime(true) - $t0;

The original call $matter = Yaml::parse($matter); is changed to $matter = yaml_parse($matter);. Below dependency is no longer required:

use Symfony\Component\Yaml\Yaml;

3. Performance comparison. Old run-times:

$ time php saaze build
Building static site in /home/klm/tmp/sndsaaze/build...
        execute(): filePath=/home/klm/tmp/sndsaaze/content/blog.yml, entries=1, totalPages=11, entries_per_page=30
        execute(): filePath=/home/klm/tmp/sndsaaze/content/music.yml, entries=1, totalPages=1, entries_per_page=30
        execute(): filePath=/home/klm/tmp/sndsaaze/content/pages.yml, entries=1, totalPages=1, entries_per_page=30
Finished creating 3 collections and 338 entries (1.25 secs / 10.17MB), YamlParser=0.48152208328247, md2html=0.21977066993713, MathParser=0.10401964187622
        real 1.31s
        user 1.15s
        sys 0
        swapped 0
        total space 0

New run-times:

$ time php saaze build
Building static site in /home/klm/tmp/sndsaaze/build...
        execute(): filePath=/home/klm/tmp/sndsaaze/content/blog.yml, entries=1, totalPages=11, entries_per_page=30
        execute(): filePath=/home/klm/tmp/sndsaaze/content/music.yml, entries=1, totalPages=1, entries_per_page=30
        execute(): filePath=/home/klm/tmp/sndsaaze/content/pages.yml, entries=1, totalPages=1, entries_per_page=30
Finished creating 3 collections and 338 entries (0.88 secs / 10.16MB), YamlParser=0.11651396751404, md2html=0.22396731376648, MathParser=0.10581231117249
        real 0.94s
        user 0.77s
        sys 0
        swapped 0
        total space 0

Above numbers for the old run-times show a ratio of 0.48/1.25, i.e., roughly 40% of the old run-time is Yaml parsing. For the new version the ratio is 0.12/0.88, i.e., roughly 13%.

4. Caveats. Whenever a new PHP version comes out, you have to re-install the extension. For example, from PHP 8.0 to 8.1 you have to recompile and re-install. Check as below:

$ php -v
PHP Warning:  PHP Startup: yaml: Unable to initialize module
Module compiled with module API=20200930
PHP    compiled with module API=20210902
These options need to match
 in Unknown on line 0
PHP 8.1.2 (cli) (built: Jan 21 2022 18:08:47) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies

Added 14-Jan-2023: Installing PECL yaml package is easy on Arch Linux, because there is an AUR package php-yaml. In case of a PHP version update you remove php-yaml with pacman -R, then reinstall again with your favorite AUR helper. One particular good AUR helper is trizen.

Added 17-Jan-2023: Installing PECL yaml package is also easy on Ubuntu. Just run apt-get install php-yaml.

Added 15-Jan-2024: Reinstalling on Arch Linux is like this:

trizen -au php-yaml