Skip to content

PhaseContainer may be silently inert when a sub-item (not the container) is demanded #1167

Description

@MaartenHilferink

In the regression suite's own fenced/unfenced A/B (t405_2_NetworkModel_PBL_zonderFence vs
t405_3_NetworkModel_PBL_metFence, NetworkModel_PBL, 12 provinces, one PhaseContainer per
province), the fenced run emits no PhaseContainer(<n>): ... message at all, although that
message is the last statement of a successful PhaseContainerOperator::CalcResult.

This is an observation plus a hypothesis, not a confirmed diagnosis — there is no minimal repro
yet. Filing it because if it holds, a PhaseContainer can be silently inert, which would matter to
users independently of the scheduling work that turned it up.

What was measured

Installed GeoDms 20.10.0.m, GeoDmsRun /S1 /S2 /S3, Windows x64.

  1. The message is absent. Zero matches for PhaseContainer in the fenced run's log.
  2. It is not a log-level artefact. ST_MajorTrace is otherwise present in that same log:
    105 [!][progress], 93 [!][storage read], 36 [!][storage write].
  3. The message argument is not empty, so the if (msgData.size() != 1 || !msgData[0].empty())
    guard in CalcResult is not what suppresses it. The config builds it as
    quote(PhaseString) + quote(regio_name), which parses to Generated output for 'Groningen
    (the doubled quote is an escape, so it is one non-empty literal).
  4. The fenced branch really did run. Its outputs are named from '_FENCE-' + string(/UseFence)
    and all carry FENCE-True.
  5. Results are correct — the paired indicator test t405_3_2 passes.
  6. The fence has no observable effect on execution. Extracting the region segment of every item
    path from both logs, the 12 provinces run strictly sequentially in both variants (~43 s each,
    no overlap; "regions with an open window per 10 s bucket" is max 2 / mean 0.90 in each). Peak
    memory is not lower with the fence: 31 665 MB vs 33 620 MB Highest CommitCharge, and
    Reserved in blocks / Highest freed are byte-identical across the two runs.

Point 6 alone does not prove the fence is inert — that model turns out to be serial for its own
reasons (the demand is driven by an AsList(..., ' + ') reduction over the per-province export
drivers), so there was no concurrency for a fence to remove. It is point 1 combined with 2-4 that
suggests CalcResult never completed.

Hypothesis

CreateResultCaller builds a mirror tree whose sub-items get a SupplCache pointing at the
corresponding source item. The consumer here demands a sub-item of that mirror tree by direct
path reference (<regio>/PublicTransport/Generate_Output_metFence/OUTPUT_Generate_fullOD_long_CSVFiles),
not the container. If that sub-item's update resolves through its SupplCache straight to the
source, the source is calculated and the phase is bypassed — while the hook that actually joins the
phase's OperationContext (TreeItem::DoUpdate, rtc/dll/src/tic/TreeItem.cpp) only fires for an
item whose own GetOrgDC() is the PhaseContainer FuncDC, i.e. for the container itself.

That would explain a fence that costs its bookkeeping, produces correct results, and enforces no
ordering — consistent with everything above.

Suggested next step

A minimal repro rather than more inference: a config with two independent expensive branches behind
one PhaseContainer, a consumer that demands a sub-item of the phase, and a second variant whose
consumer demands the container. Compare whether the PhaseContainer(<n>) message appears and
whether getUniqueLicenseToRun's phase gate (m_PhaseNumber > s_CurrActivePhaseNumber) ever
requeues anything. If the sub-item variant is the inert one, the fix is to make a sub-item demand
join the phase the same way the container demand does.

Possibly related: #1128 (PhaseContainer progress deferred until final consumer joins).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions