6th October 2021

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.

  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 run-time is Yaml parsing.

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



Categories: programming
Tags: PHP, Symfony, yaml
Author: Elmar Klausmeier