Skip to content

Commit 4465376

Browse files
authored
Merge pull request #37 from keepsuit/caches
Template cache options
2 parents 9bc39a5 + 34545bb commit 4465376

File tree

13 files changed

+357
-23
lines changed

13 files changed

+357
-23
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ phpunit.xml
1212
psalm.xml
1313
vendor
1414
.php-cs-fixer.cache
15+
tests/cache

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
"phpstan/phpstan-deprecation-rules": "^2.0",
2929
"spatie/invade": "^2.0",
3030
"spatie/ray": "^1.28",
31-
"symfony/console": "^6.3 || ^7.0",
32-
"symfony/yaml": "^6.0 || ^7.0"
31+
"symfony/console": "^6.1 || ^7.0",
32+
"symfony/var-exporter": "^6.1 || ^7.0",
33+
"symfony/yaml": "^6.1 || ^7.0"
3334
},
3435
"autoload": {
3536
"psr-4": {
@@ -49,7 +50,7 @@
4950
"pint",
5051
"phpstan analyse"
5152
],
52-
"benchmark": "phpbench run --report=aggregate --php-config=\"opcache.enable: 1, opcache.enable_cli: 1\"",
53+
"benchmark": "phpbench run --report=aggregate",
5354
"profile": "phpbench xdebug:profile"
5455
},
5556
"config": {

performance/benchmarks/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cache
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
namespace Keepsuit\Liquid\Performance\benchmarks;
4+
5+
use Keepsuit\Liquid\Environment;
6+
use Keepsuit\Liquid\EnvironmentFactory;
7+
use Keepsuit\Liquid\FileSystems\LocalFileSystem;
8+
use Keepsuit\Liquid\Performance\Shopify\CommentFormTag;
9+
use Keepsuit\Liquid\Performance\Shopify\CustomFilters;
10+
use Keepsuit\Liquid\Performance\Shopify\Database;
11+
use Keepsuit\Liquid\Performance\Shopify\PaginateTag;
12+
use Keepsuit\Liquid\Support\Arr;
13+
use Keepsuit\Liquid\TemplatesCache\MemoryTemplatesCache;
14+
use Keepsuit\Liquid\TemplatesCache\SerializeTemplatesCache;
15+
use Keepsuit\Liquid\TemplatesCache\VarExportTemplatesCache;
16+
use PhpBench\Attributes\AfterMethods;
17+
use PhpBench\Attributes\BeforeMethods;
18+
use PhpBench\Attributes\Iterations;
19+
use PhpBench\Attributes\OutputMode;
20+
use PhpBench\Attributes\OutputTimeUnit;
21+
use PhpBench\Attributes\Revs;
22+
use PhpBench\Attributes\Warmup;
23+
24+
#[Iterations(10)]
25+
#[Revs(10)]
26+
#[Warmup(1)]
27+
#[OutputMode('throughput')]
28+
#[OutputTimeUnit('seconds', precision: 3)]
29+
#[AfterMethods('clearCache')]
30+
class TemplateCacheBench
31+
{
32+
protected Environment $environment;
33+
34+
protected array $templates;
35+
36+
#[BeforeMethods('setupInMemory')]
37+
public function benchInMemory(): void
38+
{
39+
$this->renderTemplates();
40+
}
41+
42+
public function setupInMemory(): void
43+
{
44+
$this->environment = $this->environmentBuilder()
45+
->setTemplatesCache(new MemoryTemplatesCache)
46+
->build();
47+
48+
$this->loadTemplates();
49+
}
50+
51+
#[BeforeMethods('setupVarExporter')]
52+
public function benchVarExporter(): void
53+
{
54+
$this->renderTemplates();
55+
}
56+
57+
public function setupVarExporter(): void
58+
{
59+
$this->environment = $this->environmentBuilder()
60+
->setTemplatesCache(new VarExportTemplatesCache(__DIR__.'/cache/var_export', keepInMemory: false))
61+
->build();
62+
63+
$this->loadTemplates();
64+
}
65+
66+
#[BeforeMethods('setupSerialize')]
67+
public function benchSerialize(): void
68+
{
69+
$this->renderTemplates();
70+
}
71+
72+
public function setupSerialize(): void
73+
{
74+
$this->environment = $this->environmentBuilder()
75+
->setTemplatesCache(new SerializeTemplatesCache(__DIR__.'/cache/serialize', keepInMemory: false))
76+
->build();
77+
78+
$this->loadTemplates();
79+
}
80+
81+
protected function loadTemplates(): void
82+
{
83+
$baseDir = __DIR__.'/../tests';
84+
$files = glob($baseDir.'/**/*.liquid');
85+
86+
if ($files === false) {
87+
throw new \RuntimeException('Could not find any tests');
88+
}
89+
90+
$this->templates = Arr::map($files, function (string $path) use ($baseDir) {
91+
// relative path to the base directory
92+
$name = str_replace($baseDir.'/', '', $path);
93+
// remove .liquid extension
94+
$name = substr($name, 0, -7);
95+
96+
// replace / with .
97+
return str_replace('/', '.', $name);
98+
});
99+
100+
foreach ($this->templates as $template) {
101+
$this->environment->parseTemplate($template);
102+
}
103+
}
104+
105+
protected function environmentBuilder(): EnvironmentFactory
106+
{
107+
return EnvironmentFactory::new()
108+
->setFilesystem(new LocalFileSystem(__DIR__.'/../tests'))
109+
->registerTag(CommentFormTag::class)
110+
->registerTag(PaginateTag::class)
111+
->registerFilters(CustomFilters::class);
112+
}
113+
114+
protected function renderTemplates(): void
115+
{
116+
foreach ($this->templates as $template) {
117+
$this->environment->parseTemplate($template)
118+
->render($this->environment->newRenderContext(staticData: [...Database::tables()]));
119+
}
120+
}
121+
122+
public function clearCache(): void
123+
{
124+
$this->environment->templatesCache->clear();
125+
}
126+
}

phpbench.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"$schema": "./vendor/phpbench/phpbench/phpbench.schema.json",
33
"runner.bootstrap": "vendor/autoload.php",
4-
"runner.path": "performance/benchmarks"
4+
"runner.path": "performance/benchmarks",
5+
"runner.php_config": {
6+
"opcache.enable": 1,
7+
"opcache.enable_cli": 1,
8+
"opcache.validate_timestamps": 1,
9+
"opcache.revalidate_freq": 0
10+
}
511
}

src/Contracts/LiquidTemplatesCache.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,5 @@ public function has(string $name): bool;
1414

1515
public function remove(string $name): void;
1616

17-
/**
18-
* @return array<string,Template>
19-
*/
20-
public function all(): array;
21-
2217
public function clear(): void;
2318
}

src/Environment.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Keepsuit\Liquid\Support\Arr;
1818
use Keepsuit\Liquid\Support\FilterRegistry;
1919
use Keepsuit\Liquid\Support\TagRegistry;
20-
use Keepsuit\Liquid\Support\TemplatesCache;
20+
use Keepsuit\Liquid\TemplatesCache\MemoryTemplatesCache;
2121

2222
class Environment
2323
{
@@ -55,7 +55,7 @@ public function __construct(
5555
$this->filterRegistry = new FilterRegistry;
5656
$this->fileSystem = $fileSystem ?? new BlankFileSystem;
5757
$this->errorHandler = $errorHandler ?? new DefaultErrorHandler;
58-
$this->templatesCache = $templatesCache ?? new TemplatesCache;
58+
$this->templatesCache = $templatesCache ?? new MemoryTemplatesCache;
5959
$this->defaultResourceLimits = $defaultResourceLimits ?? new ResourceLimits;
6060
$this->defaultRenderContextOptions = $defaultRenderContextOptions ?? new RenderContextOptions;
6161

src/EnvironmentFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use Keepsuit\Liquid\Filters\FiltersProvider;
1313
use Keepsuit\Liquid\Render\RenderContextOptions;
1414
use Keepsuit\Liquid\Render\ResourceLimits;
15-
use Keepsuit\Liquid\Support\TemplatesCache;
15+
use Keepsuit\Liquid\TemplatesCache\MemoryTemplatesCache;
1616

1717
final class EnvironmentFactory
1818
{
@@ -45,7 +45,7 @@ public function __construct()
4545
{
4646
$this->fileSystem = new BlankFileSystem;
4747
$this->errorHandler = new DefaultErrorHandler;
48-
$this->templatesCache = new TemplatesCache;
48+
$this->templatesCache = new MemoryTemplatesCache;
4949
$this->resourceLimits = new ResourceLimits;
5050
$this->defaultRenderContextOptions = new RenderContextOptions;
5151

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Keepsuit\Liquid\TemplatesCache;
4+
5+
use Keepsuit\Liquid\Template;
6+
7+
abstract class FilesystemTemplatesCache extends MemoryTemplatesCache
8+
{
9+
public function __construct(
10+
protected string $cachePath,
11+
protected bool $keepInMemory = true,
12+
) {
13+
$this->ensureCacheDirectoryExists();
14+
}
15+
16+
public function set(string $name, Template $template): void
17+
{
18+
if ($this->keepInMemory) {
19+
parent::set($name, $template);
20+
}
21+
22+
$this->saveCompiledTemplate($this->getCompiledPath($name), $template);
23+
}
24+
25+
public function get(string $name): ?Template
26+
{
27+
if ($this->keepInMemory && $template = parent::get($name)) {
28+
return $template;
29+
}
30+
31+
if (! $this->has($name)) {
32+
return null;
33+
}
34+
35+
$compiledPath = $this->getCompiledPath($name);
36+
37+
return $this->loadCompiledTemplate($compiledPath);
38+
}
39+
40+
public function has(string $name): bool
41+
{
42+
return file_exists($this->getCompiledPath($name));
43+
}
44+
45+
public function remove(string $name): void
46+
{
47+
if ($this->keepInMemory) {
48+
parent::remove($name);
49+
}
50+
51+
unlink($this->getCompiledPath($name));
52+
}
53+
54+
public function clear(): void
55+
{
56+
if ($this->keepInMemory) {
57+
parent::clear();
58+
}
59+
60+
$files = new \FilesystemIterator($this->cachePath);
61+
62+
foreach ($files as $file) {
63+
if ($file instanceof \SplFileInfo) {
64+
unlink($file->getPathname());
65+
}
66+
}
67+
}
68+
69+
protected function getCompiledPath(string $name): string
70+
{
71+
return $this->cachePath.'/'.hash('sha256', $name);
72+
}
73+
74+
protected function ensureCacheDirectoryExists(): void
75+
{
76+
if (! is_dir($this->cachePath)) {
77+
mkdir($this->cachePath, 0755, true);
78+
}
79+
}
80+
81+
abstract protected function saveCompiledTemplate(string $compiledPath, Template $template): void;
82+
83+
abstract protected function loadCompiledTemplate(string $compiledPath): ?Template;
84+
}

src/Support/TemplatesCache.php renamed to src/TemplatesCache/MemoryTemplatesCache.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?php
22

3-
namespace Keepsuit\Liquid\Support;
3+
namespace Keepsuit\Liquid\TemplatesCache;
44

55
use Keepsuit\Liquid\Contracts\LiquidTemplatesCache;
66
use Keepsuit\Liquid\Template;
77

8-
class TemplatesCache implements LiquidTemplatesCache
8+
class MemoryTemplatesCache implements LiquidTemplatesCache
99
{
1010
/**
1111
* @var array<string,Template>
@@ -32,14 +32,6 @@ public function remove(string $name): void
3232
unset($this->cache[$name]);
3333
}
3434

35-
/**
36-
* @return array<string,Template>
37-
*/
38-
public function all(): array
39-
{
40-
return $this->cache;
41-
}
42-
4335
public function clear(): void
4436
{
4537
$this->cache = [];

0 commit comments

Comments
 (0)