Skip to content

Skip synthetic "_simple_" line style in catalogue pre-warm (#286)#288

Merged
philliphoff merged 1 commit into
mainfrom
philliphoff/s101-multi-dataset-memory
Jun 15, 2026
Merged

Skip synthetic "_simple_" line style in catalogue pre-warm (#286)#288
philliphoff merged 1 commit into
mainfrom
philliphoff/s101-multi-dataset-memory

Conversation

@philliphoff

Copy link
Copy Markdown
Owner

Summary

Fixes the three KeyNotFoundException throws on every S-101 dataset load reported in #286.

The S-100 Part 9A Lua portrayal model emits LineInstruction / AreaInstruction outline references using the inline _simple_ line-style sentinel (from PortrayalModel.lua's SimpleLineStyle). Its colour, width, and dash pattern travel on the instruction itself — it is never a named complex line style in the portrayal catalogue.

CataloguePreWarm resolved it like any other line style, so each load threw:

Line style '_simple_' not found in the portrayal catalogue.

…three times. The exceptions were caught and discarded but never cached, so they were re-thrown on every subsequent load.

Change

  • New LineInstruction.SimpleLineStyleReference constant ("_simple_") documenting the Part 9A sentinel.
  • CataloguePreWarm now skips it for both LineInstruction.LineStyleReference and AreaInstruction.OutlineStyleReference. Rendering already drew these as plain inline lines (colour token present ⇒ no catalogue lookup), so portrayal output is unchanged — minus the exceptions.

Tests

  • CataloguePreWarmTests — unit cover: the sentinel is not resolved against the catalogue; named line styles still are.
  • S101SimpleLineStyleRegressionTests — skippable real-data regression: building an S-101 vector portrayal raises zero KeyNotFoundExceptions. Verified against UKHO/IC-ENC trial cells; reverting the fix reproduces exactly the 3 throws from [Bug]: Performance of S101 multiple datasets #286.

Full EncDotNet.S100.Pipelines.Tests suite: 584 passed, 1 skipped.

Out of scope

This PR does not address the per-dataset memory growth (50–100 MB/cell) also noted in #286 — that stems from the render-side caches (Mapsui scene/style/pattern-clip/tile) that back smooth pan/zoom, and warrants a more careful eviction-policy design. Tracked in a separate follow-up issue.

Closes #286 (exception portion); memory portion tracked separately.

The S-100 Part 9A Lua portrayal model emits LineInstruction /
AreaInstruction outline references with the inline "_simple_" line-style
sentinel, whose colour, width, and dash travel on the instruction itself
rather than via a named complex line style in the portrayal catalogue.

CataloguePreWarm resolved it like any other line style, so every S-101
dataset load drove three KeyNotFoundException throws ("Line style
'_simple_' not found in the portrayal catalogue") that were caught and
discarded but never cached — re-thrown on each load.

Recognise the sentinel (new LineInstruction.SimpleLineStyleReference
constant) and skip the catalogue lookup. Rendering already drew these as
plain inline lines, so behaviour is unchanged minus the exceptions.

Adds a unit test for the pre-warm skip and a skippable real-data
regression test asserting zero KeyNotFoundExceptions when building an
S-101 vector portrayal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Performance Gate

PASSED — no regressions.

Threshold: 10.0%, MAD multiplier (k): 3.0, retry-zone mult: 2.0×

Scenario summary

Scenario Status Δ median (%) z (Δ/MAD) Base median (ms) Samples (b/c)
exchange-set-open ✅ pass +2.6 +2.15 1.27 5/5
s101-portray-cold ✅ pass +3.0 +0.19 0.24 5/5
s101-portray-warm ✅ pass -1.5 -0.07 0.25 5/5
s101-real-cold ✅ pass +0.1 +0.01 0.27 5/5
s101-real-warm ✅ pass -5.9 -0.34 0.28 5/5
s101-render-warm ✅ pass +1.0 +0.06 0.23 5/5
s102-coverage ✅ pass +0.6 +0.15 0.16 5/5
s102-coverage-open ✅ pass -4.1 -0.57 3.01 20/20
s102-coverage-render-large ✅ pass -4.8 -0.39 0.21 5/5
s102-real-warm ✅ pass -5.5 -0.72 0.31 5/5
s111-real-warm ✅ pass +5.3 +3.22 0.27 5/5
s124-vector ✅ pass +5.2 +0.68 0.19 5/5
s201-vector ✅ pass +1.8 +2.67 0.18 5/5

exchange-set-open

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 1.27 1.30
Baseline MAD (ms) 0.02
Δ median +2.6%
z (Δ/MAD) +2.15

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.asset.read 2.49 2.75 +10.3%
s100.exchangeset.parse 45.24 45.54 +0.7% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.asset.read.duration 0.21 0.18 -11.5%

s101-portray-cold

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.24 0.24
Baseline MAD (ms) 0.04
Δ median +3.0%
z (Δ/MAD) +0.19

s101-portray-warm

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.25 0.24
Baseline MAD (ms) 0.05
Δ median -1.5%
z (Δ/MAD) -0.07

s101-real-cold

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.27 0.27
Baseline MAD (ms) 0.03
Δ median +0.1%
z (Δ/MAD) +0.01

s101-real-warm

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.28 0.26
Baseline MAD (ms) 0.05
Δ median -5.9%
z (Δ/MAD) -0.34

s101-render-warm

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.23 0.23
Baseline MAD (ms) 0.04
Δ median +1.0%
z (Δ/MAD) +0.06

s102-coverage

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.16 0.16
Baseline MAD (ms) 0.01
Δ median +0.6%
z (Δ/MAD) +0.15

s102-coverage-open

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 3.01 2.88
Baseline MAD (ms) 0.21
Δ median -4.1%
z (Δ/MAD) -0.57

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.dataset.open 457.07 459.78 +0.6% ▫️
s100.hdf5.dataset.read 166.51 167.94 +0.9% ▫️
s100.hdf5.file.open 20.24 19.36 -4.3% ▫️
s100.hdf5.open 18.74 18.67 -0.4% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.hdf5.read.bytes 36456.00 36456.00 +0.0% ▫️
s100.hdf5.read.duration 27.34 27.12 -0.8% ▫️
s100.hdf5.read.duration 32.12 32.56 +1.4% ▫️
s100.hdf5.read.duration 11.22 11.33 +1.1% ▫️

s102-coverage-render-large

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.21 0.20
Baseline MAD (ms) 0.03
Δ median -4.8%
z (Δ/MAD) -0.39

s102-real-warm

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.31 0.30
Baseline MAD (ms) 0.02
Δ median -5.5%
z (Δ/MAD) -0.72

s111-real-warm

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.27 0.29
Baseline MAD (ms) 0.00
Δ median +5.3%
z (Δ/MAD) +3.22

s124-vector

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.19 0.20
Baseline MAD (ms) 0.01
Δ median +5.2%
z (Δ/MAD) +0.68

s201-vector

Iteration statistics

Stat Baseline Candidate
Samples 5 5
Median (ms) 0.18 0.18
Baseline MAD (ms) 0.00
Δ median +1.8%
z (Δ/MAD) +2.67

Generated by EncDotNet.S100.PerfReport gate command

@philliphoff philliphoff merged commit 9641a7b into main Jun 15, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Performance of S101 multiple datasets

1 participant