Skip to content

Commit 49b0c39

Browse files
committed
📖
1 parent ff14742 commit 49b0c39

File tree

11 files changed

+227
-54
lines changed

11 files changed

+227
-54
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Performance considerations
2+
3+
Generating a QR Code is not a trivial task - it is a combination of countless complex mathematical operations.
4+
5+
This library seeks not to be the fastest QR Code generator, but instead to provide flexibility and user friendlyness,
6+
which in turn comes with a slight performance cost.
7+
8+
9+
## Version
10+
11+
The [version of the QR symbol](./Terminology.md#version) is one of the major performance factors as it
12+
determines the size of the symbol and therefore the amount of data that can be stored. Iterating over the internal
13+
representation of the matrix takes more time with increasing size and the internals iterate over the matrix a LOT.
14+
15+
Because of that you want of course to select the smallest possible version for the given data, which the encoder does by default.
16+
However, sometimes the possibly varying size of the symbol may not be desired and you want to choose a fixed size, in which case
17+
you should determine the maximum size of the input data and choose a version that fits.
18+
19+
20+
## Ecc level
21+
22+
Another factor is the [ECC level](./Terminology.md#ecc-error-correction-coding) that determines the error correction capacity. The default setting is the lowest capacity (L, 7%)
23+
which allows the highest amount of data to be stored and which is good enough for e.g. on-screen display or poster prints.
24+
ECC level H on the other hand allows for up to 30% error correction capacity, which is great for "high risk" applications such as prints on mail.
25+
With increasing error correction capacity, the maximum amount of data a symbol can hold decreases, and a higher version number may be necessary.
26+
27+
28+
## Data mode
29+
30+
By default, the encoder auto-detects the best [mode for data encoding](Terminology.md#mode) (numeric, alphanumeric, kanji, hanzi or 8-bit binary)
31+
and depending on the length of the given data, the detection costs an increasing amount of time. To circumvent this,
32+
you can call one of the "add segment" methods on the `QRCode` instance, for example: `$qrcode->addByteSegment($data)`.
33+
34+
Generally, using 8-bit binary mode (or just "byte mode") is the fast and fail-safe mode for any kind of data, and with
35+
[ECI](https://en.wikipedia.org/wiki/Extended_Channel_Interpretation) it even offers support for character sets other than UTF-8.
36+
So, unless you want to fit a large amount of japanese or chinese characters into a QR symbol of a certain version,
37+
encoding those characters as 3 or 4 byte UTF-8 may still be faster in 8-bit byte than in the "compressed" 13-bit double byte modes.
38+
39+
40+
## Mask pattern
41+
42+
[Evaluating the QR symbol](./Terminology.md#data-masking) in order to pick the right [mask pattern](./Terminology.md#mask-pattern)
43+
is a complex and costly operation that is necessary to ensure the symbol is readable. Although [there is an option](../Usage/Configuration-settings.md#maskpattern)
44+
to override the evaluation and manually set a mask pattern, this is not recommended unless you know exactly what you're doing
45+
as it can render a QR symbol unreadable.
46+
47+
The table below shows the performance impact (in miliseconds) of the mask pattern evaluation for each version, the times may vary between systems.
48+
49+
| version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
50+
|-----------|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|
51+
| **1-10** | 4.414 | 5.697 | 7.986 | 9.221 | 10.877 | 11.293 | 13.901 | 15.563 | 18.142 | 20.501 |
52+
| **11-20** | 22.662 | 27.779 | 29.622 | 33.017 | 36.358 | 39.712 | 43.685 | 47.121 | 51.389 | 57.865 |
53+
| **21-30** | 59.753 | 68.502 | 68.523 | 72.866 | 78.245 | 83.593 | 88.327 | 94.921 | 103.394 | 106.358 |
54+
| **31-40** | 113.311 | 120.484 | 126.215 | 132.931 | 139.783 | 145.617 | 170.576 | 165.996 | 167.365 | 175.821 |
55+
56+
57+
## Output
58+
59+
Output rendering depends heavily on the size of the QR matrix, the desired type and the underlying libraries and/or PHP extensions.
60+
Especially the rendering of raster images through GD or ImagMagick can be very slow, depending on [the scale setting](../Usage/Configuration-settings.md#scale),
61+
filters and image type.
62+
63+
Below a comparison of the performance for the several built-in output classes (times in miliseconds, scale = 5):
64+
65+
| | v5 | v10 | v15 | v20 | v25 | v30 | v35 | v40 |
66+
|-------------------|-------:|-------:|--------:|--------:|--------:|--------:|--------:|--------:|
67+
| **QRMarkupSVG** | 3.732 | 8.645 | 13.846 | 21.127 | 32.842 | 43.753 | 56.584 | 73.885 |
68+
| **QRMarkupHTML** | 0.522 | 1.308 | 2.062 | 2.761 | 3.907 | 5.201 | 7.931 | 9.572 |
69+
| **QRGdImageBMP** | 5.998 | 12.541 | 20.728 | 32.336 | 46.345 | 62.842 | 81.555 | 106.482 |
70+
| **QRGdImageGIF** | 3.427 | 6.817 | 12.226 | 17.925 | 25.453 | 35.136 | 44.706 | 57.477 |
71+
| **QRGdImageJPEG** | 2.284 | 4.882 | 8.161 | 12.097 | 17.333 | 23.862 | 30.327 | 40.226 |
72+
| **QRGdImagePNG** | 4.523 | 9.377 | 16.581 | 26.207 | 36.516 | 49.066 | 63.765 | 82.074 |
73+
| **QRGdImageWEBP** | 8.211 | 17.367 | 30.079 | 47.095 | 69.668 | 91.378 | 119.869 | 150.288 |
74+
| **QRStringJSON** | 0.043 | 0.066 | 0.107 | 0.158 | 0.215 | 0.301 | 0.369 | 0.492 |
75+
| **QRStringText** | 0.229 | 0.387 | 0.628 | 0.952 | 1.312 | 1.759 | 2.329 | 3.045 |
76+
| **QRImagick** | 37.694 | 68.808 | 114.415 | 172.962 | 242.338 | 325.085 | 419.999 | 529.897 |
77+
| **QRFpdf** | 6.578 | 12.466 | 21.169 | 33.021 | 45.469 | 61.198 | 80.092 | 100.059 |
78+
| **QREps** | 1.269 | 2.694 | 4.515 | 6.933 | 11.049 | 14.181 | 20.799 | 25.886 |

docs/Appendix/Terminology.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ the module is located, with counting commencing at 0. Module `(0, 0)` is therefo
2020

2121
### Module
2222

23-
A *module* represents a single square "pixel" (not to confuse with pixels in a raster image or screen) in the matrix.
24-
A dark module is a binary one and a light module is a binary zero.
23+
A *module* represents a single square "pixel" in the matrix (not to confuse with pixels in a raster image or screen).
24+
A dark module represents a binary one and a light module represents a binary zero.
2525

2626

2727
### Version
2828

2929
The *version* of a QR symbol determines the side length of the matrix (and therefore the maximum capacity of code words),
30-
ranging from 21×21 modules at version 1 to 177×177 modules at version 40; the module count increases in steps of 4 and can
31-
be calculated by `4 * version + 17`.
30+
ranging from 21×21 modules (441 total) at version 1 to 177×177 modules (31329 total) at version 40.
31+
The module count increases in steps of 4 and can be calculated by `4 * version + 17`.
3232

3333
The maximum capacity for each version, mode and ECC level can be found in [this table (qrcode.com)](https://www.qrcode.com/en/about/version.html).
3434

docs/Built-In-Output/QRImagick.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ echo $imagick->getImageBlob();
9696
| `$imageTransparent` | `bool` |
9797
| `$imagickFormat` | `string` |
9898
| `$keepAsSquare` | `array` |
99-
| `$markupDark` | `string` |
100-
| `$markupLight` | `string` |
10199
| `$outputBase64` | `bool` |
102100
| `$quality` | `int` |
103101
| `$returnResource` | `bool` |

docs/Built-In-Output/QRMarkupHTML.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ $options = new QROptions;
1717

1818
$options->outputType = QROutputInterface::MARKUP_HTML;
1919
$options->cssClass = 'qrcode';
20-
// default values for unassigned module types
21-
$options->markupDark = '#555';
22-
$options->markupLight = '#CCC';
2320
$options->moduleValues = [
2421
// finder
2522
QRMatrix::M_FINDER_DARK => '#A71111', // dark (true)
@@ -88,8 +85,6 @@ header('Content-type: text/html');
8885
|----------------|----------|
8986
| `$cssClass` | `string` |
9087
| `$eol` | `string` |
91-
| `$markupDark` | `string` |
92-
| `$markupLight` | `string` |
9388

9489

9590
### Options that have no effect

docs/Built-In-Output/QRMarkupSVG.md

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,19 @@ Set the options:
1111
```php
1212
$options = new QROptions;
1313

14-
$options->version = 7;
15-
$options->outputType = QROutputInterface::MARKUP_SVG;
14+
$options->version = 7;
15+
$options->outputType = QROutputInterface::MARKUP_SVG;
1616
// if set to false, the light modules won't be rendered
17-
$options->drawLightModules = true;
18-
// empty the default value to remove the fill* and opacity* attributes from the <path> elements
19-
$options->markupDark = '';
20-
$options->markupLight = '';
17+
$options->drawLightModules = true;
18+
$options->svgUseFillAttributes = true;
2119
// draw the modules as circles isntead of squares
22-
$options->drawCircularModules = true;
23-
$options->circleRadius = 0.4;
20+
$options->drawCircularModules = true;
21+
$options->circleRadius = 0.4;
2422
// connect paths to avoid render glitches
2523
// @see https://github.com/chillerlan/php-qrcode/issues/57
26-
$options->connectPaths = true;
24+
$options->connectPaths = true;
2725
// keep modules of these types as square
28-
$options->keepAsSquare = [
26+
$options->keepAsSquare = [
2927
QRMatrix::M_FINDER_DARK,
3028
QRMatrix::M_FINDER_DOT,
3129
QRMatrix::M_ALIGNMENT_DARK,
@@ -72,24 +70,23 @@ printf('<img alt="%s" src="%s" />', $alt, $out);
7270
7371
## Options that affect this module
7472
75-
| property | type |
76-
|---------------------------|----------------|
77-
| `$circleRadius` | `float` |
78-
| `$connectPaths` | `bool` |
79-
| `$cssClass` | `string` |
80-
| `$drawCircularModules` | `bool` |
81-
| `$drawLightModules` | `bool` |
82-
| `$eol` | `string` |
83-
| `$excludeFromConnect` | `array` |
84-
| `$keepAsSquare` | `array` |
85-
| `$markupDark` | `string` |
86-
| `$markupLight` | `string` |
87-
| `$outputBase64` | `bool` |
88-
| `$svgAddXmlHeader` | `bool` |
89-
| `$svgDefs` | `string` |
90-
| `$svgOpacity` | `float` |
91-
| `$svgPreserveAspectRatio` | `string` |
92-
| `$svgViewBoxSize` | `int\|null` |
73+
| property | type |
74+
|---------------------------|-------------|
75+
| `$circleRadius` | `float` |
76+
| `$connectPaths` | `bool` |
77+
| `$cssClass` | `string` |
78+
| `$drawCircularModules` | `bool` |
79+
| `$drawLightModules` | `bool` |
80+
| `$eol` | `string` |
81+
| `$excludeFromConnect` | `array` |
82+
| `$keepAsSquare` | `array` |
83+
| `$outputBase64` | `bool` |
84+
| `$svgAddXmlHeader` | `bool` |
85+
| `$svgDefs` | `string` |
86+
| `$svgOpacity` | `float` |
87+
| `$svgPreserveAspectRatio` | `string` |
88+
| `$svgViewBoxSize` | `int\|null` |
89+
| `$svgUseFillAttributes` | `bool` |
9390
9491
9592
### Options that have no effect

docs/Customizing/QROutputAbstract.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ The finalized map of `$M_TYPE` to value for the current output. This map is gene
2626
### Copies of `QROptions` values
2727

2828
Some values from the `QROptions` instance are copied to properties to avoid calling the magic getters in long loops for a significant performance increase, e.g. in the module collector.
29-
Currently, the following values are copied via `copyVars()` during invocation:
30-
`$connectPaths`, `$excludeFromConnect`, `$eol`, `$drawLightModules`, `$drawCircularModules`, `$keepAsSquare`, `$circleRadius`.
29+
Currently, the following values are copied via `copyVars()` during invocation: `$connectPaths`, `$excludeFromConnect`, `$eol`,
30+
`$drawLightModules`, `$drawCircularModules`, `$keepAsSquare`, `$circleRadius` (and additionally `$circleDiameter`).
3131

3232

3333
## Methods

docs/Readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@ The markdown sources for the [Read the Docs online manual](https://php-qrcode.re
8383

8484
### Appendix
8585

86-
- [How to contribute](./Appendix/Contribute.md)
8786
- [Terminology](./Appendix/Terminology.md)
8887
- [Popular content and URI schemes](./Appendix/URI-Content.md)
88+
- [Performance considerations](./Appendix/Performance-considerations.md)
89+
- [How to contribute](./Appendix/Contribute.md)
8990
- [License](./Appendix/License.rst)
9091

9192

0 commit comments

Comments
 (0)