marker: batch topology dumps in bulk fan-out (per-def on 500+ links was ~1 minute)

Every per-link marker operation (start_marker / stop_marker / update_marker) called Project.dump() -- a full topology serialization + file write. A definition fan-out over 500 links therefore wrote the whole topology 500+ times (each blocking the event loop), which dominated the observed ~1 minute; the NIO round-trips themselves were negligible.

Add a dump: bool = True parameter to the three per-link operations and inherit_marker (matching the existing dump param on Link.add_node). The bulk paths -- definition create fan-out, definition-update sync and re-fan-out, definition-delete cleanup, pause/resume, new-link inheritance -- pass dump=False and their caller dumps once after. apply_defs_to_new_link suppresses per-def dumps too: link create / project open dump once after, so opening a 500-link project with N definitions no longer does 500xN topology writes.
This commit is contained in:
YueGuobin committed 2026-08-08 00:03:30 +08:00
1 parent 078cf92aef
commit ad8bac8328
3 files changed
+41 -17

No files matched your search

+11 -6
View File
@@ -353,7 +353,7 @@ class UDPLink(Link):
# explicitly deletes a marker via the REST API, and a marker is torn
# down automatically only when its link is deleted.
async def start_marker(self, name, bpf, tag=None, direction=None, data_link_type="DLT_EN10MB", capture_node_id=None, color=None, highlight_duration=None, enabled=True, inherited_from=None):
async def start_marker(self, name, bpf, tag=None, direction=None, data_link_type="DLT_EN10MB", capture_node_id=None, color=None, highlight_duration=None, enabled=True, inherited_from=None, dump=True):
"""
Attach a traffic-insight marker to this link.
@@ -412,9 +412,12 @@ class UDPLink(Link):
if self._created:
await self.update()
self._project.emit_notification("link.updated", self.asdict())
self._project.dump()
# Bulk fan-out passes dump=False: N per-link topology writes on a
# 500-link project are the dominant cost — the caller dumps once after.
if dump:
self._project.dump()
async def stop_marker(self, name, inherited=False):
async def stop_marker(self, name, inherited=False, dump=True):
"""
Remove a traffic-insight marker from this link.
@@ -455,9 +458,10 @@ class UDPLink(Link):
except Exception:
pass # best-effort: old compute without the route leaves the file
self._project.emit_notification("link.updated", self.asdict())
self._project.dump()
if dump:
self._project.dump()
async def update_marker(self, name, bpf=None, tag=None, enabled=None, direction=_UNSET, color=None, highlight_duration=None, inherited=False):
async def update_marker(self, name, bpf=None, tag=None, enabled=None, direction=_UNSET, color=None, highlight_duration=None, inherited=False, dump=True):
"""
Update an existing marker's fields and push to uBridge fine-grained — no
full NIO reapply, so sibling markers' pcaps stay open. bpf/tag/direction
@@ -536,4 +540,5 @@ class UDPLink(Link):
# correct in _markers; the next NIO reapply converges uBridge.
pass
self._project.emit_notification("link.updated", self.asdict())
self._project.dump()
if dump:
self._project.dump()