Follow-up from #679.
Res1DReach.__init__ reads reach.length, which goes to mikeio1d's
result_reach.py:_get_total_length. A test user profiled it at ~2.4 s over 8,377 calls on an
EPANET-backed file — ~286 µs per call. On tests/testdata/network.res1d, a MIKE urban model, the
same property costs 2.6 µs. A 100x gap.
The mikeio1d source is:
def _get_total_length(self) -> float:
total_length = 0
try:
for reach in self.reaches:
total_length += reach.Length
return total_length
except Exception as _:
return total_length
The docstring says it returns zero when no length is available. So the likely explanation is that
Length is unavailable on EPANET links, every call raises, and the cost is exception handling
across the pythonnet boundary — which would also mean every reach gets length 0 and the graph edge
lengths are meaningless on those files.
Next step: confirm what reach.length returns on an EPANET link. If it is 0, this belongs upstream
in mikeio1d rather than worked around in modelskill. Deriving length from
end_chainage - start_chainage is tempting but untested and may hit the same path.
Topology reuse (#682) would avoid the cost in the calibration-loop case regardless, since the reach
loop never runs.
Follow-up from #679.
Res1DReach.__init__readsreach.length, which goes to mikeio1d'sresult_reach.py:_get_total_length. A test user profiled it at ~2.4 s over 8,377 calls on anEPANET-backed file — ~286 µs per call. On
tests/testdata/network.res1d, a MIKE urban model, thesame property costs 2.6 µs. A 100x gap.
The mikeio1d source is:
The docstring says it returns zero when no length is available. So the likely explanation is that
Lengthis unavailable on EPANET links, every call raises, and the cost is exception handlingacross the pythonnet boundary — which would also mean every reach gets length 0 and the graph edge
lengths are meaningless on those files.
Next step: confirm what
reach.lengthreturns on an EPANET link. If it is 0, this belongs upstreamin mikeio1d rather than worked around in modelskill. Deriving length from
end_chainage - start_chainageis tempting but untested and may hit the same path.Topology reuse (#682) would avoid the cost in the calibration-loop case regardless, since the reach
loop never runs.