Commit 68e8b50
committed
minor #3779 [Map] Render each UX icon once instead of once per marker (Kocal)
This PR was merged into the 3.x branch.
Discussion
----------
[Map] Render each UX icon once instead of once per marker
| Q | A
| -------------- | ---
| Bug fix? | no
| New feature? | no
| Deprecations? | no
| Documentation? | no
| Issues | -
| License | MIT
Markers on a map almost always share the same icon, but `AbstractRenderer::getMapAttributes()` called `UxIconRenderer::render()` for every single marker: a registry lookup, two attribute-validation passes and an HTML build, repeated identically thousands of times.
Memoize inside `UxIconRenderer` on the arguments it receives, so the cache key can't drift from them and every map in the request shares it. The generated payload is unchanged.
Rendering a Leaflet map: 1000 markers ~9.7 ms -> ~6.5 ms, 5000 markers ~53 ms -> ~37 ms.
Benchmarked from the repository root with `blackfire run symfony php bench.php`:
```php
<?php
require __DIR__.'/src/Map/vendor/autoload.php';
require __DIR__.'/src/Map/src/Bridge/Leaflet/vendor/autoload.php';
use Symfony\UX\Icons\Icon as UxIconsIcon;
use Symfony\UX\Icons\IconRegistryInterface;
use Symfony\UX\Icons\IconRenderer;
use Symfony\UX\Map\Bridge\Leaflet\Renderer\LeafletRenderer;
use Symfony\UX\Map\Icon\Icon;
use Symfony\UX\Map\Icon\UxIconRenderer;
use Symfony\UX\Map\Map;
use Symfony\UX\Map\Marker;
use Symfony\UX\Map\Point;
use Symfony\UX\StimulusBundle\Helper\StimulusHelper;
$registry = new class implements IconRegistryInterface {
public function get(string $name): UxIconsIcon
{
return new UxIconsIcon(
'<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/>',
['viewBox' => '0 0 24 24', 'fill' => 'none', 'stroke' => 'currentColor', 'stroke-width' => '2'],
);
}
};
$renderer = new LeafletRenderer(
new StimulusHelper(null),
new UxIconRenderer(new IconRenderer($registry, ['fill' => 'currentColor'])),
);
$map = new Map(center: new Point(48.86, 2.35), zoom: 12);
for ($i = 0; $i < 2000; ++$i) {
$map->addMarker(new Marker(
position: new Point(48.86 + $i / 10000, 2.35 + $i / 10000),
title: 'Marker '.$i,
icon: Icon::ux('lucide:map-pin'),
));
}
$renderer->renderMap($map);
```
Blackfire:
- before (177ms wall / 164ms CPU / 9MB): https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/e78d0d4c-5a78-4a30-a550-7ba075c36a90/graph
- after (82ms wall / 81ms CPU / 8MB): https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/b299a751-fac7-4e67-96bb-4d0dcb0dda8c/graph
- diff: https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/compare/e78d0d4c-5a78-4a30-a550-7ba075c36a90...b299a751-fac7-4e67-96bb-4d0dcb0dda8c/graph
Analysis, implementation and benchmarks by Claude Opus 5.
Commits
-------
3291457 [Map] Render each UX icon once instead of once per marker1 file changed
Lines changed: 8 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
23 | 28 | | |
24 | 29 | | |
25 | 30 | | |
| |||
34 | 39 | | |
35 | 40 | | |
36 | 41 | | |
37 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
38 | 45 | | |
39 | 46 | | |
40 | 47 | | |
| |||
0 commit comments