Skip to content

Commit 8648d0f

Browse files
committed
Optimizations in parser
- array_walk is slower than a foreach, so buffer now uses foreach. - By caching some of the inline node parsers we can strip out about 9% of the overhead in the inline parser, as we do not have to check them for every token.
1 parent 0881d30 commit 8648d0f

File tree

10 files changed

+84
-10
lines changed

10 files changed

+84
-10
lines changed

packages/guides-restructured-text/src/RestructuredText/Parser/Buffer.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
namespace phpDocumentor\Guides\RestructuredText\Parser;
1515

1616
use function array_pop;
17-
use function array_walk;
1817
use function count;
1918
use function implode;
2019
use function ltrim;

packages/guides-restructured-text/src/RestructuredText/Parser/InlineParser.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
use Exception;
1717
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
1818
use phpDocumentor\Guides\Nodes\InlineCompoundNode;
19+
use phpDocumentor\Guides\RestructuredText\Parser\Productions\InlineRules\CachableInlineRule;
1920
use phpDocumentor\Guides\RestructuredText\Parser\Productions\InlineRules\InlineRule;
2021

22+
use function array_filter;
23+
use function array_key_exists;
2124
use function usort;
2225

2326
/** @internal */
@@ -26,11 +29,21 @@ class InlineParser
2629
/** @var InlineRule[] */
2730
private array $rules;
2831

32+
/** @var array<InlineLexer::*, CachableInlineRule> */
33+
private array $cache = [];
34+
2935
/** @param iterable<InlineRule> $inlineRules */
3036
public function __construct(iterable $inlineRules)
3137
{
32-
$this->rules = [...$inlineRules];
38+
$this->rules = array_filter([...$inlineRules], static fn ($rule) => $rule instanceof CachableInlineRule === false);
3339
usort($this->rules, static fn (InlineRule $a, InlineRule $b): int => $a->getPriority() > $b->getPriority() ? -1 : 1);
40+
foreach ($inlineRules as $rule) {
41+
if (!($rule instanceof CachableInlineRule)) {
42+
continue;
43+
}
44+
45+
$this->cache[$rule->getToken()] = $rule;
46+
}
3447
}
3548

3649
public function parse(string $content, BlockContext $blockContext): InlineCompoundNode
@@ -44,7 +57,9 @@ public function parse(string $content, BlockContext $blockContext): InlineCompou
4457
while ($lexer->token !== null) {
4558
foreach ($this->rules as $inlineRule) {
4659
$node = null;
47-
if ($inlineRule->applies($lexer)) {
60+
if (array_key_exists($lexer->token->type ?? -1, $this->cache)) {
61+
$node = $this->cache[$lexer->token->type]->apply($blockContext, $lexer);
62+
} elseif ($inlineRule->applies($lexer)) {
4863
$node = $inlineRule->apply($blockContext, $lexer);
4964
}
5065

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/AnonymousReferenceRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
*
2929
* @see https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#anonymous-hyperlinks
3030
*/
31-
final class AnonymousReferenceRule extends ReferenceRule
31+
final class AnonymousReferenceRule extends ReferenceRule implements CachableInlineRule
3232
{
33+
public function getToken(): int
34+
{
35+
return InlineLexer::ANONYMOUSE_REFERENCE;
36+
}
37+
3338
public function applies(InlineLexer $lexer): bool
3439
{
3540
return $lexer->token?->type === InlineLexer::ANONYMOUSE_REFERENCE;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\RestructuredText\Parser\Productions\InlineRules;
15+
16+
use phpDocumentor\Guides\RestructuredText\Parser\InlineLexer;
17+
18+
interface CachableInlineRule extends InlineRule
19+
{
20+
/** @return InlineLexer::* */
21+
public function getToken(): int;
22+
}

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/LiteralRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@
2323
/**
2424
* Rule for literals such as ``something``
2525
*/
26-
final class LiteralRule extends AbstractInlineRule
26+
final class LiteralRule extends AbstractInlineRule implements CachableInlineRule
2727
{
28+
public function getToken(): int
29+
{
30+
return InlineLexer::LITERAL;
31+
}
32+
2833
public function applies(InlineLexer $lexer): bool
2934
{
3035
return $lexer->token?->type === InlineLexer::LITERAL;

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/NamedReferenceRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
*
2929
* @see https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#hyperlink-references
3030
*/
31-
final class NamedReferenceRule extends ReferenceRule
31+
final class NamedReferenceRule extends ReferenceRule implements CachableInlineRule
3232
{
33+
public function getToken(): int
34+
{
35+
return InlineLexer::NAMED_REFERENCE;
36+
}
37+
3338
public function applies(InlineLexer $lexer): bool
3439
{
3540
return $lexer->token?->type === InlineLexer::NAMED_REFERENCE;

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/NbspRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@
2020
/**
2121
* Rule to parse for non-breaking spaces: a~b
2222
*/
23-
final class NbspRule extends ReferenceRule
23+
final class NbspRule extends AbstractInlineRule implements CachableInlineRule
2424
{
25+
public function getToken(): int
26+
{
27+
return InlineLexer::NBSP;
28+
}
29+
2530
public function applies(InlineLexer $lexer): bool
2631
{
2732
return $lexer->token?->type === InlineLexer::NBSP;

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/StandaloneEmailRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@
2626
*
2727
* @see https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#standalone-hyperlinks
2828
*/
29-
final class StandaloneEmailRule extends ReferenceRule
29+
final class StandaloneEmailRule extends ReferenceRule implements CachableInlineRule
3030
{
31+
public function getToken(): int
32+
{
33+
return InlineLexer::EMAIL;
34+
}
35+
3136
public function applies(InlineLexer $lexer): bool
3237
{
3338
return $lexer->token?->type === InlineLexer::EMAIL;

packages/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules/StandaloneHyperlinkRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@
2626
*
2727
* @see https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#standalone-hyperlinks
2828
*/
29-
final class StandaloneHyperlinkRule extends ReferenceRule
29+
final class StandaloneHyperlinkRule extends ReferenceRule implements CachableInlineRule
3030
{
31+
public function getToken(): int
32+
{
33+
return InlineLexer::HYPERLINK;
34+
}
35+
3136
public function applies(InlineLexer $lexer): bool
3237
{
3338
return $lexer->token?->type === InlineLexer::HYPERLINK;

packages/guides-restructured-text/tests/benchmarks/BufferBench.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
declare(strict_types=1);
44

5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
514
namespace phpDocumentor\Guides\RestructuredText;
615

716
use PhpBench\Attributes\Iterations;
@@ -21,7 +30,6 @@ public function __construct()
2130
$this->buffer->push(' Final line.');
2231
}
2332

24-
2533
#[Revs([1000, 10_000])]
2634
#[Iterations(5)]
2735
public function benchGetLines(): void

0 commit comments

Comments
 (0)