Summary
Several Running refresh paths build a staging config tree (schema resolution, Entry graph, leaf variants), then TreeExport to tree_persist / Intent, then merge into the canonical store syncTree via ImportConfig using ProtoTreeImporter.
That implies extra work: full structure build, export walk, per-leaf protobuf marshal/unmarshal, and import/schema binding again on the destination tree.
The TreeProto step is a good interchange format for persistence, RPC, or tests, but for in-process “staging tree → canonical syncTree” it is largely redundant.
This is not specific to gNMI GET; the same pattern appears wherever staging is filled then handed off through TreeProto, for example:
- gNMI GET sync —
pkg/datastore/target/gnmi/get.go (internalGetSync: notifications → tree → TreeExport → ApplyToRunning + proto.NewProtoTreeImporter)
- gNMI stream sync —
pkg/datastore/target/gnmi/stream.go (same export → ApplyToRunning pattern)
Other southbound paths may already use a different adapter into ApplyToRunning (e.g. NETCONF can return an importer directly); the improvement still applies whenever the handoff is “built api.Entry tree → TreeExport → ProtoTreeImporter” for the same process.
Proposed solution
Pointer hand-off, not TreeProto for in-process handoffs:
- Add an
ImportConfigAdapter whose traversal reads from the existing in-memory tree (api.Entry graph or a thin index), and run ImportConfig once against the datastore syncTree under the existing ApplyToRunning contract (deletes, revert snapshot, processors, locking).
- Keep
TreeExport + ProtoTreeImporter where a serialized Intent is genuinely required (persistence, cross-process, shared contract with intent storage, tests).
Goals
- Drop the encode/decode and second full traversal when source and destination trees live in the same binary and epoch.
- Preserve
ApplyToRunning semantics end-to-end.
References
pkg/datastore/target/gnmi/get.go — GET sync
pkg/datastore/target/gnmi/stream.go — stream sync
pkg/datastore/sync.go — ApplyToRunning / ImportConfig
pkg/datastore/target/netconf/sync.go — calls ApplyToRunning with a target-provided importer (pattern may differ; still the same merge API)
Summary
Several Running refresh paths build a staging config tree (schema resolution,
Entrygraph, leaf variants), thenTreeExporttotree_persist/Intent, then merge into the canonical storesyncTreeviaImportConfigusingProtoTreeImporter.That implies extra work: full structure build, export walk, per-leaf protobuf marshal/unmarshal, and import/schema binding again on the destination tree.
The TreeProto step is a good interchange format for persistence, RPC, or tests, but for in-process “staging tree → canonical
syncTree” it is largely redundant.This is not specific to gNMI GET; the same pattern appears wherever staging is filled then handed off through TreeProto, for example:
pkg/datastore/target/gnmi/get.go(internalGetSync: notifications → tree →TreeExport→ApplyToRunning+proto.NewProtoTreeImporter)pkg/datastore/target/gnmi/stream.go(same export →ApplyToRunningpattern)Other southbound paths may already use a different adapter into
ApplyToRunning(e.g. NETCONF can return an importer directly); the improvement still applies whenever the handoff is “builtapi.Entrytree → TreeExport → ProtoTreeImporter” for the same process.Proposed solution
Pointer hand-off, not TreeProto for in-process handoffs:
ImportConfigAdapterwhose traversal reads from the existing in-memory tree (api.Entrygraph or a thin index), and runImportConfigonce against the datastoresyncTreeunder the existingApplyToRunningcontract (deletes, revert snapshot, processors, locking).TreeExport+ProtoTreeImporterwhere a serializedIntentis genuinely required (persistence, cross-process, shared contract with intent storage, tests).Goals
ApplyToRunningsemantics end-to-end.References
pkg/datastore/target/gnmi/get.go— GET syncpkg/datastore/target/gnmi/stream.go— stream syncpkg/datastore/sync.go—ApplyToRunning/ImportConfigpkg/datastore/target/netconf/sync.go— callsApplyToRunningwith a target-provided importer (pattern may differ; still the same merge API)