Skip to content

Add zoom-gated AIS subscription with viewport-span threshold#149

Merged
philliphoff merged 1 commit into
mainfrom
philliphoff/ais-zoom-gated-subscription
May 31, 2026
Merged

Add zoom-gated AIS subscription with viewport-span threshold#149
philliphoff merged 1 commit into
mainfrom
philliphoff/ais-zoom-gated-subscription

Conversation

@philliphoff
Copy link
Copy Markdown
Owner

Why

PR-D3 (#142) shipped the AIS overlay; PR-D4 (#147) added click-to-identify. Today the overlay subscribes to aisstream.io immediately on viewer startup with whatever the initial (effectively global) viewport is. That floods the map with vessels far from anything the user is looking at, wastes aisstream.io quota, and slows cold start.

What

This PR adds a viewer-side gate that defers the first AIS subscription until the visible viewport's lat-span and lon-span have both shrunk to or below a configurable threshold. Once the gate trips, the subscription opens with the live viewport bounding box, and subsequent pans / zooms keep the bbox in sync via debounced UpdateArea calls. Activation is one-shot — the subscription stays alive even if the user later zooms back out.

Decisions (full rationale in the design doc)

Q Decision
Q1 Activation criterion Viewport bounding-box span in degrees (lat-span AND lon-span both ≤ threshold). Maps 1:1 to aisstream.io's filter.
Q2 Drives area filter? Yes. Gate trip seeds the subscription with the current viewport bbox; subsequent viewport changes call UpdateArea (debounced 250 ms).
Q3 Setting New AisOverlaySettings.ActivationViewportSpanDegrees — nullable double, default 50.0. null = no gate (legacy behaviour).
Q4 UI Numeric input + tooltip in the AIS section of Settings. Layer-stack "waiting" hint deferred (scope creep).
Q5 Lifecycle Deferred decorator wrapping IDynamicFeatureSource. Lazily constructs the real AisDynamicFeatureSource on first activation; pre-activation CurrentFeatures is empty and Changed never fires.
Q6 After activation One-shot. Source stays activated for the process lifetime; zoom-out does not tear down.

Changes

  • Settings: AisOverlaySettings.ActivationViewportSpanDegrees (nullable double, default 50.0); null preserves the legacy subscribe-immediately path.
  • Decorator: DeferredAisFeatureSource wraps the real AisDynamicFeatureSource, gates construction on the first qualifying viewport snapshot, then debounces UpdateArea (250 ms trailing-edge by default; TimeSpan.Zero for tests).
  • Viewport plumbing: IMapViewportNotifier + MapViewportNotifier translate Mapsui's EPSG:3857 viewport into a lat/lon snapshot. MainWindow binds the notifier to the live Navigator before the dynamic-source overlay host is built. This is also the first time UpdateArea is wired anywhere in the viewer.
  • Settings UI: Localised numeric input + tooltip + helper string in the AIS section of the Settings dialog.
  • Docs: New docs/design/ais-zoom-gated-subscription.md; updated viewer + DynamicSources.Ais READMEs; new entry in docs/toc.yml under Design notes.

Tests

Test Focus
AisOverlaySettingsTests Property default / null / round-trip through ViewerSettings JSON.
DeferredAisFeatureSourceTests Gate stays closed when either span > threshold; activates exactly once at-or-below threshold; one-shot (zoom-out doesn't deactivate); seed bbox plumbed to factory; subsequent viewports trigger UpdateArea; debounce coalesces bursts; Changed events forward; DisposeAsync disposes inner; reads initial snapshot from notifier at construction; throws on non-positive threshold.
MapViewportNotifierTests TryProject returns null for unsized viewport; round-trips through SphericalMercator; whole-world view yields ±180/±~85° clamped extents.
SettingsViewModelAisActivationTests Hydration from settings; persistence on set; ≤ 0 normalises to null; null persists as null.
AisOverlayFactoryTests (extended) BuildSource returns the deferred wrapper when threshold is set and notifier is provided; returns the real source when threshold is null OR notifier is unavailable.

dotnet build -c Release is clean (0 errors). dotnet test -c Release is green across all test projects.

Out of scope

  • Tearing down the subscription on zoom-out (Q6 — one-shot).
  • Layer-stack "waiting to activate" indicator (Q4 — defer; DynamicSourceMetadata.Description isn't surfaced on the row today).
  • Generalising the gate to other dynamic sources (decorator stays AIS-named).
  • Persisting "already activated" across restarts.

The AIS overlay used to subscribe to aisstream.io immediately on
viewer startup, using whatever the initial (effectively global)
viewport was. That flooded the map with vessels far from anything
the user was looking at, wasted aisstream.io quota, and slowed
cold start.

This change introduces a viewer-side gate that defers the first
subscription until the visible viewport's lat-span and lon-span
have both shrunk to or below a configurable threshold. Once the
gate trips, the subscription is opened with the live viewport
bounding box, and subsequent pans / zooms keep the bbox in sync
via debounced UpdateArea calls. Activation is one-shot: the
subscription stays alive even if the user later zooms back out.

* AisOverlaySettings.ActivationViewportSpanDegrees (nullable
  double, default 50.0; null preserves the legacy
  subscribe-immediately behaviour) is round-trippable through
  ViewerSettings JSON.
* DeferredAisFeatureSource decorator wraps the real
  AisDynamicFeatureSource and gates construction on the first
  qualifying viewport snapshot.
* IMapViewportNotifier + MapViewportNotifier translate Mapsui's
  EPSG:3857 viewport into a lat/lon snapshot and publish it to
  subscribers. MainWindow binds the notifier to the live
  Navigator before the dynamic-source overlay host is built.
* Settings dialog gets a localised numeric input for the
  threshold with tooltip + helper text.
* Design doc docs/design/ais-zoom-gated-subscription.md
  captures the Q1-Q6 decisions; viewer + AIS READMEs and
  docs/toc.yml are updated.

Tests: AisOverlaySettings round-trip; DeferredAisFeatureSource
gate-closed/open semantics, one-shot activation, debounced
UpdateArea, dispose; MapViewportNotifier projection;
SettingsViewModel persistence and <=0 normalisation; factory
deferred-wrapper branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@philliphoff philliphoff merged commit e32f093 into main May 31, 2026
2 of 3 checks passed
@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 -5.5 -0.51 0.64 20/20
s101-portray-cold ✅ pass +0.1 +0.01 416.09 20/20
s101-portray-warm ✅ pass +1.9 +0.54 249.26 20/20
s101-render-warm ✅ pass +4.0 +4.71 234.66 20/20
s102-coverage ✅ pass +0.6 +0.30 1.06 20/20
s102-coverage-open ✅ pass +5.9 +3.83 2.58 20/20
s102-coverage-render-large ✅ pass -1.4 -1.14 140.21 20/20
s124-vector ✅ pass +13.2 +2.33 0.31 20/20
s201-vector ✅ pass +8.2 +1.31 0.33 20/20

exchange-set-open

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 0.64 0.61
Baseline MAD (ms) 0.07
Δ median -5.5%
z (Δ/MAD) -0.51

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.asset.read 10.79 10.94 +1.4% ▫️
s100.exchangeset.parse 41.81 41.93 +0.3% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.asset.read.duration 18.12 18.19 +0.3% ▫️

s101-portray-cold

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 416.09 416.33
Baseline MAD (ms) 23.29
Δ median +0.1%
z (Δ/MAD) +0.01

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.lua.execute 7812.22 7816.97 +0.1% ▫️
s100.lua.rule.invoke 6791.13 6774.12 -0.3% ▫️
s100.pipeline.vector.process 8064.07 8055.70 -0.1% ▫️
s100.pipeline.vector.stage.assemble 0.22 0.23 +1.8% ▫️
s100.pipeline.vector.stage.feature_xml 182.74 182.11 -0.3% ▫️
s100.pipeline.vector.stage.lua 7813.91 7818.68 +0.1% ▫️
s100.pipeline.vector.stage.rule_select 17.82 6.24 -65.0%
s100.pipeline.vector.stage.sort 13.70 13.69 -0.1% ▫️
s100.pipeline.vector.stage.viewing_groups 15.59 15.48 -0.7% ▫️
s100.pipeline.vector.stage.xslt 0.31 0.31 +0.9% ▫️
s100.render.frame 1834.14 1853.43 +1.1% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 7.00 7.00 +0.0% ▫️
s100.featurecatalogue.cache.hit.count 6.00 6.00 +0.0% ▫️
s100.featurecatalogue.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.lua.execute.duration 2622.02 2644.21 +0.8% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 42.00 42.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 217.00 217.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 21.00 21.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.features.count 2478.00 2478.00 +0.0% ▫️
s100.lua.instructions.emitted.count 4004.00 4004.00 +0.0% ▫️
s100.lua.rule.invoke.count 7.00 7.00 +0.0% ▫️
s100.lua.rule.invoke.count 77.00 77.00 +0.0% ▫️
s100.lua.rule.invoke.duration 2209.79 2248.54 +1.8% ▫️
s100.lua.rule.invoke.duration 5.01 4.79 -4.2% ▫️
s100.lua.source.cache.hit.count 552.00 552.00 +0.0% ▫️
s100.lua.source.cache.miss.count 43.00 43.00 +0.0% ▫️
s100.pattern.cache.hit.count 210.00 210.00 +0.0% ▫️
s100.pattern.cache.miss.count 14.00 14.00 +0.0% ▫️
s100.pipeline.drawinginstructions.out 4004.00 4004.00 +0.0% ▫️
s100.pipeline.duration 2694.84 2721.61 +1.0% ▫️
s100.pipeline.features.in 217.00 217.00 +0.0% ▫️
s100.pipeline.stage.duration 0.25 0.31 +22.8%
s100.pipeline.stage.duration 52.37 61.97 +18.3%
s100.pipeline.stage.duration 2623.40 2645.53 +0.8% ▫️
s100.pipeline.stage.duration 10.48 4.82 -54.0%
s100.pipeline.stage.duration 4.68 5.04 +7.7%
s100.pipeline.stage.duration 1.02 1.11 +8.6%
s100.pipeline.stage.duration 0.83 0.83 -0.5% ▫️
s100.pipeline.stage.instructions.count 0.00 0.00 N/A ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.portrayal.cache.hit.count 12.00 12.00 +0.0% ▫️
s100.portrayal.cache.hit.count 552.00 552.00 +0.0% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 96.00 96.00 +0.0% ▫️
s100.portrayal.cache.miss.count 2.00 2.00 +0.0% ▫️
s100.portrayal.cache.miss.count 43.00 43.00 +0.0% ▫️
s100.portrayal.cache.miss.count 16.00 16.00 +0.0% ▫️
s100.render.frame.duration 710.94 711.90 +0.1% ▫️
s100.render.instructions.processed.count 4004.00 4004.00 +0.0% ▫️
s100.render.styles.applied.count 4256.00 4256.00 +0.0% ▫️
s100.symbol.cache.hit.count 364.00 364.00 +0.0% ▫️
s100.symbol.cache.miss.count 98.00 98.00 +0.0% ▫️
s100.symbol.resolve.duration 0.39 0.37 -5.9% ▫️
s100.symbol.resolve.duration 17.33 18.19 +5.0% ▫️

s101-portray-warm

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 249.26 253.90
Baseline MAD (ms) 8.63
Δ median +1.9%
z (Δ/MAD) +0.54

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.lua.execute 5983.72 6029.41 +0.8% ▫️
s100.lua.rule.invoke 5342.59 5405.74 +1.2% ▫️
s100.pipeline.vector.process 6291.24 6341.54 +0.8% ▫️
s100.pipeline.vector.stage.assemble 0.17 0.17 -1.0% ▫️
s100.pipeline.vector.stage.feature_xml 283.52 287.41 +1.4% ▫️
s100.pipeline.vector.stage.lua 5984.69 6030.47 +0.8% ▫️
s100.pipeline.vector.stage.rule_select 3.66 3.92 +7.3%
s100.pipeline.vector.stage.sort 14.39 14.72 +2.3% ▫️
s100.pipeline.vector.stage.viewing_groups 16.11 16.38 +1.7% ▫️
s100.pipeline.vector.stage.xslt 0.22 0.23 +8.2%
s100.render.frame 250.00 243.88 -2.4% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.featurecatalogue.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.lua.execute.duration 1673.99 1650.93 -1.4% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 42.00 42.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 217.00 217.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 21.00 21.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.features.count 2478.00 2478.00 +0.0% ▫️
s100.lua.instructions.emitted.count 4004.00 4004.00 +0.0% ▫️
s100.lua.rule.invoke.count 7.00 7.00 +0.0% ▫️
s100.lua.rule.invoke.count 77.00 77.00 +0.0% ▫️
s100.lua.rule.invoke.duration 1489.02 1473.95 -1.0% ▫️
s100.lua.rule.invoke.duration 2.53 2.58 +2.1% ▫️
s100.lua.source.cache.hit.count 595.00 595.00 +0.0% ▫️
s100.pattern.cache.hit.count 222.00 222.00 +0.0% ▫️
s100.pattern.cache.miss.count 2.00 2.00 +0.0% ▫️
s100.pipeline.drawinginstructions.out 4004.00 4004.00 +0.0% ▫️
s100.pipeline.duration 1756.92 1727.33 -1.7% ▫️
s100.pipeline.features.in 217.00 217.00 +0.0% ▫️
s100.pipeline.stage.duration 0.02 0.02 -10.7%
s100.pipeline.stage.duration 75.09 69.70 -7.2% ▫️
s100.pipeline.stage.duration 1674.30 1651.18 -1.4% ▫️
s100.pipeline.stage.duration 1.26 1.05 -16.3%
s100.pipeline.stage.duration 4.46 4.05 -9.2% ▫️
s100.pipeline.stage.duration 0.32 0.24 -23.7%
s100.pipeline.stage.duration 0.05 0.04 -21.0%
s100.pipeline.stage.instructions.count 0.00 0.00 N/A ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.portrayal.cache.hit.count 2.00 2.00 +0.0% ▫️
s100.portrayal.cache.hit.count 595.00 595.00 +0.0% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 16.00 16.00 +0.0% ▫️
s100.render.frame.duration 126.08 124.63 -1.2% ▫️
s100.render.instructions.processed.count 4004.00 4004.00 +0.0% ▫️
s100.render.styles.applied.count 4256.00 4256.00 +0.0% ▫️
s100.symbol.cache.hit.count 448.00 448.00 +0.0% ▫️
s100.symbol.cache.miss.count 14.00 14.00 +0.0% ▫️
s100.symbol.resolve.duration 0.46 0.35 -23.7%
s100.symbol.resolve.duration 2.09 2.20 +5.0%

s101-render-warm

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 234.66 244.06
Baseline MAD (ms) 2.00
Δ median +4.0%
z (Δ/MAD) +4.71

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.lua.execute 5691.65 5910.06 +3.8% ▫️
s100.lua.rule.invoke 5113.87 5285.10 +3.3% ▫️
s100.pipeline.vector.process 5781.21 6007.43 +3.9% ▫️
s100.pipeline.vector.stage.assemble 0.11 0.14 +28.1%
s100.pipeline.vector.stage.feature_xml 74.05 82.07 +10.8%
s100.pipeline.vector.stage.lua 5692.46 5910.91 +3.8% ▫️
s100.pipeline.vector.stage.rule_select 2.15 2.23 +3.4% ▫️
s100.pipeline.vector.stage.sort 8.98 8.59 -4.4% ▫️
s100.pipeline.vector.stage.viewing_groups 10.45 10.03 -4.1% ▫️
s100.pipeline.vector.stage.xslt 0.13 0.15 +12.3%
s100.render.frame 158.46 155.08 -2.1% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.featurecatalogue.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.lua.execute.duration 1619.08 1663.11 +2.7% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 63.00 63.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 42.00 42.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 217.00 217.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 21.00 21.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 49.00 49.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 840.00 840.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 7.00 7.00 +0.0% ▫️
s100.lua.feature.instructions.count 28.00 28.00 +0.0% ▫️
s100.lua.feature.instructions.count 14.00 14.00 +0.0% ▫️
s100.lua.features.count 2478.00 2478.00 +0.0% ▫️
s100.lua.instructions.emitted.count 4004.00 4004.00 +0.0% ▫️
s100.lua.rule.invoke.count 7.00 7.00 +0.0% ▫️
s100.lua.rule.invoke.count 77.00 77.00 +0.0% ▫️
s100.lua.rule.invoke.duration 1433.64 1460.96 +1.9% ▫️
s100.lua.rule.invoke.duration 2.32 1.98 -14.6%
s100.lua.source.cache.hit.count 595.00 595.00 +0.0% ▫️
s100.pattern.cache.hit.count 222.00 222.00 +0.0% ▫️
s100.pattern.cache.miss.count 2.00 2.00 +0.0% ▫️
s100.pipeline.drawinginstructions.out 4004.00 4004.00 +0.0% ▫️
s100.pipeline.duration 1646.40 1690.29 +2.7% ▫️
s100.pipeline.features.in 217.00 217.00 +0.0% ▫️
s100.pipeline.stage.duration 0.02 0.02 +6.2%
s100.pipeline.stage.duration 22.78 23.08 +1.3% ▫️
s100.pipeline.stage.duration 1619.29 1663.37 +2.7% ▫️
s100.pipeline.stage.duration 0.72 0.76 +6.0%
s100.pipeline.stage.duration 2.42 1.73 -28.6%
s100.pipeline.stage.duration 0.28 0.32 +13.7%
s100.pipeline.stage.duration 0.03 0.04 +17.4%
s100.pipeline.stage.instructions.count 0.00 0.00 N/A ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 4004.00 4004.00 +0.0% ▫️
s100.portrayal.cache.hit.count 2.00 2.00 +0.0% ▫️
s100.portrayal.cache.hit.count 595.00 595.00 +0.0% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 16.00 16.00 +0.0% ▫️
s100.render.frame.duration 109.23 109.60 +0.3% ▫️
s100.render.instructions.processed.count 4004.00 4004.00 +0.0% ▫️
s100.render.styles.applied.count 4256.00 4256.00 +0.0% ▫️
s100.symbol.cache.hit.count 448.00 448.00 +0.0% ▫️
s100.symbol.cache.miss.count 14.00 14.00 +0.0% ▫️
s100.symbol.resolve.duration 0.22 0.22 -1.7% ▫️
s100.symbol.resolve.duration 1.13 1.21 +7.6%

s102-coverage

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 1.06 1.07
Baseline MAD (ms) 0.02
Δ median +0.6%
z (Δ/MAD) +0.30

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.pipeline.coverage.process 40.95 42.53 +3.9% ▫️
s100.pipeline.coverage.stage.read 4.94 4.70 -4.8% ▫️
s100.pipeline.coverage.stage.resolve 32.73 34.63 +5.8%
s100.render.coverage.build 79.24 79.10 -0.2% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.coverage.cells 4557.00 4557.00 +0.0% ▫️
s100.hdf5.read.bytes 5208.00 5208.00 +0.0% ▫️
s100.hdf5.read.duration 21.25 21.11 -0.7% ▫️
s100.hdf5.read.duration 29.05 29.28 +0.8% ▫️
s100.hdf5.read.duration 7.40 7.36 -0.5% ▫️
s100.pipeline.duration 7.98 7.80 -2.3% ▫️
s100.pipeline.stage.duration 1.01 0.89 -11.3%
s100.pipeline.stage.duration 6.41 6.47 +0.8% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️

s102-coverage-open

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 2.58 2.74
Baseline MAD (ms) 0.04
Δ median +5.9%
z (Δ/MAD) +3.83

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.dataset.open 73.17 75.50 +3.2% ▫️
s100.hdf5.dataset.read 11.02 11.61 +5.3%
s100.hdf5.file.open 17.72 18.27 +3.1% ▫️
s100.hdf5.open 18.29 18.56 +1.5% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.hdf5.read.bytes 36456.00 36456.00 +0.0% ▫️
s100.hdf5.read.duration 6.44 6.43 -0.1% ▫️
s100.hdf5.read.duration 2.38 2.35 -1.3% ▫️
s100.hdf5.read.duration 4.24 4.23 -0.4% ▫️

s102-coverage-render-large

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 140.21 138.31
Baseline MAD (ms) 1.68
Δ median -1.4%
z (Δ/MAD) -1.14

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.pipeline.coverage.process 176.37 183.27 +3.9% ▫️
s100.pipeline.coverage.stage.read 130.10 131.39 +1.0% ▫️
s100.pipeline.coverage.stage.resolve 43.49 49.13 +13.0%
s100.render.coverage.build 4933.63 4878.35 -1.1% ▫️

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.coverage.cells 7000000.00 7000000.00 +0.0% ▫️
s100.hdf5.read.bytes 8000000.00 8000000.00 +0.0% ▫️
s100.hdf5.read.duration 0.09 0.06 -29.8%
s100.hdf5.read.duration 2.69 2.65 -1.8% ▫️
s100.hdf5.read.duration 1.27 1.16 -8.7% ▫️
s100.pipeline.duration 37.64 35.32 -6.2% ▫️
s100.pipeline.stage.duration 28.32 26.17 -7.6% ▫️
s100.pipeline.stage.duration 8.70 8.66 -0.5% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️

s124-vector

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 0.31 0.35
Baseline MAD (ms) 0.02
Δ median +13.2%
z (Δ/MAD) +2.33

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.pipeline.vector.process 6.68 7.27 +8.8%
s100.pipeline.vector.stage.assemble 0.24 0.27 +11.8%
s100.pipeline.vector.stage.feature_xml 0.97 0.97 +0.1% ▫️
s100.pipeline.vector.stage.rule_select 0.23 0.23 +2.9% ▫️
s100.pipeline.vector.stage.sort 0.16 0.16 +2.5% ▫️
s100.pipeline.vector.stage.viewing_groups 0.37 0.42 +14.9%
s100.pipeline.vector.stage.xslt 3.40 3.62 +6.6%
s100.render.frame 0.81 0.85 +5.0% ▫️
s100.xslt.transform 1.43 1.54 +7.9%

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.featurecatalogue.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.pipeline.drawinginstructions.out 14.00 14.00 +0.0% ▫️
s100.pipeline.duration 52.90 52.77 -0.3% ▫️
s100.pipeline.features.in 7.00 7.00 +0.0% ▫️
s100.pipeline.stage.duration 1.01 1.00 -0.9% ▫️
s100.pipeline.stage.duration 3.17 3.15 -0.6% ▫️
s100.pipeline.stage.duration 1.08 1.06 -1.6% ▫️
s100.pipeline.stage.duration 0.05 0.07 +45.3%
s100.pipeline.stage.duration 0.09 0.07 -14.9%
s100.pipeline.stage.duration 47.15 46.91 -0.5% ▫️
s100.pipeline.stage.instructions.count 14.00 14.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 14.00 14.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 14.00 14.00 +0.0% ▫️
s100.portrayal.cache.hit.count 13.00 13.00 +0.0% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 6.00 6.00 +0.0% ▫️
s100.portrayal.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.portrayal.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.render.frame.duration 2.16 2.40 +11.1%
s100.render.instructions.processed.count 14.00 14.00 +0.0% ▫️
s100.render.styles.applied.count 14.00 14.00 +0.0% ▫️
s100.xslt.transform.duration 10.19 10.14 -0.4% ▫️

s201-vector

Iteration statistics

Stat Baseline Candidate
Samples 20 20
Median (ms) 0.33 0.36
Baseline MAD (ms) 0.02
Δ median +8.2%
z (Δ/MAD) +1.31

Spans (sum of all iterations)

Span Baseline (ms) Candidate (ms) Delta Status
s100.pipeline.vector.process 7.33 7.83 +6.8%
s100.pipeline.vector.stage.assemble 0.18 0.19 +4.6% ▫️
s100.pipeline.vector.stage.feature_xml 0.98 0.96 -2.3% ▫️
s100.pipeline.vector.stage.rule_select 0.29 0.34 +15.5%
s100.pipeline.vector.stage.sort 0.08 0.08 +6.0%
s100.pipeline.vector.stage.viewing_groups 0.33 0.37 +12.3%
s100.pipeline.vector.stage.xslt 3.13 3.36 +7.3%
s100.render.frame 0.71 0.75 +5.7%
s100.xslt.transform 2.02 2.26 +11.6%

Metrics

Metric Baseline Candidate Delta Status
s100.catalogue.match.count 1.00 1.00 +0.0% ▫️
s100.featurecatalogue.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.pipeline.drawinginstructions.out 7.00 7.00 +0.0% ▫️
s100.pipeline.duration 146.50 152.45 +4.1% ▫️
s100.pipeline.features.in 21.00 21.00 +0.0% ▫️
s100.pipeline.stage.duration 0.54 0.54 +0.2% ▫️
s100.pipeline.stage.duration 7.50 7.09 -5.5% ▫️
s100.pipeline.stage.duration 0.11 0.12 +9.2%
s100.pipeline.stage.duration 0.02 0.02 +2.8% ▫️
s100.pipeline.stage.duration 0.06 0.05 -16.3%
s100.pipeline.stage.duration 138.02 144.23 +4.5% ▫️
s100.pipeline.stage.instructions.count 7.00 7.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 7.00 7.00 +0.0% ▫️
s100.pipeline.stage.instructions.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 7.00 7.00 +0.0% ▫️
s100.portrayal.cache.hit.count 6.00 6.00 +0.0% ▫️
s100.portrayal.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.portrayal.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.render.frame.duration 1.07 1.12 +4.7% ▫️
s100.render.instructions.processed.count 7.00 7.00 +0.0% ▫️
s100.render.styles.applied.count 14.00 14.00 +0.0% ▫️
s100.symbol.cache.hit.count 6.00 6.00 +0.0% ▫️
s100.symbol.cache.miss.count 1.00 1.00 +0.0% ▫️
s100.symbol.resolve.duration 0.01 0.01 +61.4%
s100.symbol.resolve.duration 0.75 0.81 +7.5%
s100.xslt.transform.duration 26.07 27.49 +5.5%

Generated by EncDotNet.S100.PerfReport gate command

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.

1 participant