Bacon / BaconQrCode

QR Code Generator for PHP
BSD 2-Clause "Simplified" License
1.83k stars 208 forks source link

performance comparison #70

Closed ghost closed 2 years ago

ghost commented 4 years ago

Hi!

As part of researching ways of generating QR codes in my PHP application I did some simple performance tests comparing BaconQrCode against the CLI qrencode tool. I was expecting the BaconQrCode library to be faster than using passthru from PHP, but maybe it is not:

Method Requests / second
/usr/bin/qrencode 141.03 [#/sec] (mean)
BaconQrCode 1.0.3 34.49 [#/sec] (mean)
BaconQrCode master 8.10 [#/sec] (mean)
chillerlan/php-qrcode 20.63 [#/sec] (mean)

The example code I used with the CLI tool:

<?php
$qrString = 'otpauth://totp/foo%40example.org:My%20Service%20Inc.?secret=H7ISMUHIREODCOONJUOPKJJ4HJCS2PUD&algorithm=SHA1&digits=8&period=10&issuer=My%20Service%20Inc.';
ob_start();
passthru('/usr/bin/qrencode -s 5 -t PNG -o - ' . escapeshellcmd($qrString));
header('Content-Type: image/png');
echo ob_get_clean();

For BaconQrCode 1.0.3 I used this script:

<?php

$qrString = 'otpauth://totp/foo%40example.org:My%20Service%20Inc.?secret=H7ISMUHIREODCOONJUOPKJJ4HJCS2PUD&algorithm=SHA1&digits=8&period=10&issuer=My%20Service%20Inc.';

require_once 'bacon/vendor/autoload.php';

use BaconQrCode\Renderer\Image\Png;
use BaconQrCode\Writer;

$renderer = new Png();
$renderer->setHeight(256);
$renderer->setWidth(256);
$writer = new Writer($renderer);
header('Content-Type: image/png');
echo $writer->writeString($qrString);

For BaconQrCode from master I used this script:

<?php

$qrString = 'otpauth://totp/foo%40example.org:My%20Service%20Inc.?secret=H7ISMUHIREODCOONJUOPKJJ4HJCS2PUD&algorithm=SHA1&digits=8&period=10&issuer=My%20Service%20Inc.';

require_once 'bacon2/vendor/autoload.php';

use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;

$renderer = new ImageRenderer(
    new RendererStyle(256),
    new ImagickImageBackEnd()
);
$writer = new Writer($renderer);
header('Content-Type: image/png');
echo $writer->writeString($qrString);

I tested both with BaconQrCode 1.0.3 and BaconQrCode master on PHP 7.4 (Fedora 32) by accessing the script through Apache+FPM-FPM using Apache Bench to check the performance:

$ ab -n 1000 -c 50 https://HOST/qr.php

Is this performance difference expected? Is there anything that can be done to improve the performance of BaconQrCode, maybe specific opcache configuration? Am I testing wrong? Can the PHP code be optimized? Is Composer the bottleneck? Although I tested with phpab directly as well, which didn't help much... Is there a good reason not to consider using passthru with /usr/bin/qrencode?

Thanks

DASPRiD commented 4 years ago

It is pretty normal that a native code implementation will perform way better than an interpreted language ever could, especially in this case where a lot (and I really mean a lot) of computations are happening.

As for your question about passhrough: The qrencode library does not support all the features which the BaconQrCode renderer does, so for this library that is out of scope. Of course, for your personal projects, you are free to just use a pass through if available.