parsica-php / parsica

Parsica - PHP Parser Combinators - The easiest way to build robust parsers.
https://parsica-php.github.io/
MIT License
405 stars 18 forks source link

performance: use instanceof instead of isFail() / isSuccess() which gains ~10% #42

Open staabm opened 3 years ago

staabm commented 3 years ago

while doing further performance investigation I came to the conclusion that parsica is "slow" on JSONBench, because

this PR reduces the number of methods beeing called per character in the most basic building blocks. take it as a PoC to show where we loose performance because of design decisions

before

Subjects: 3, Assertions: 0, Failures: 0, Errors: 0
suite: 13462909f97540adcd33373b9725d9abe46c65fa, date: 2021-03-20, stime: 21:27:36
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+----------+--------+-----------+
| benchmark | subject              | set | revs | its | mem_peak   | best         | mean         | mode         | worst        | stdev    | rstdev | diff      |
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+----------+--------+-----------+
| JSONBench | bench_json_encode    | 0   | 5    | 3   | 1,668,112b | 12.600μs     | 13.067μs     | 13.240μs     | 13.400μs     | 0.340μs  | 2.60%  | 1.00x     |
| JSONBench | bench_Parsica_JSON   | 0   | 5    | 3   | 2,155,904b | 20,074.800μs | 20,181.200μs | 20,195.400μs | 20,281.600μs | 84.532μs | 0.42%  | 1,544.48x |
| JSONBench | bench_basemax_jpophp | 0   | 5    | 3   | 1,867,848b | 1,344.800μs  | 1,352.933μs  | 1,347.340μs  | 1,366.800μs  | 9.854μs  | 0.73%  | 103.54x   |
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+----------+--------+-----------+

after

Subjects: 3, Assertions: 0, Failures: 0, Errors: 0
suite: 13462904c8d3eb3c864dcdd7273330a020c9bb0d, date: 2021-03-20, stime: 21:21:25
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+-----------+--------+-----------+
| benchmark | subject              | set | revs | its | mem_peak   | best         | mean         | mode         | worst        | stdev     | rstdev | diff      |
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+-----------+--------+-----------+
| JSONBench | bench_json_encode    | 0   | 5    | 3   | 1,667,728b | 13.200μs     | 13.600μs     | 13.599μs     | 14.000μs     | 0.327μs   | 2.40%  | 1.00x     |
| JSONBench | bench_Parsica_JSON   | 0   | 5    | 3   | 2,155,504b | 18,604.600μs | 19,093.067μs | 19,270.684μs | 19,453.400μs | 358.170μs | 1.88%  | 1,403.90x |
| JSONBench | bench_basemax_jpophp | 0   | 5    | 3   | 1,867,400b | 1,308.200μs  | 1,334.133μs  | 1,324.149μs  | 1,366.000μs  | 23.967μs  | 1.80%  | 98.10x    |
+-----------+----------------------+-----+------+-----+------------+--------------+--------------+--------------+--------------+-----------+--------+-----------+

blackfire reports a ~10% perf boost

grafik

staabm commented 3 years ago

I feel we could get the most out of persica (in the json bench), if we could either reduce take1 to an absolute minimum regarding overhead, or alternatively try to achieve parsing by doing multiple chars at a time instead of 1 by 1 (not sure this is possible).

my assumptions stem just from profilling source code. take it with a grain of salt, as I have zero experience building parsers and haven't used parsica at all yet.