mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
mpm: x4xx: cache xport_info to speed up GetDeviceInfo
get_xport_info() enumerates network interfaces via netlink/pyudev on every GetDeviceInfo call (~350ms, non-yielding). Since GetDeviceInfo is unclaimed and gets flooded during discovery, this could starve claimed RPCs past their short deadlines like 2 seconds. Cache the result for 10s (X400_XPORT_INFO_CACHE_TTL); it's stable per session, and init() drops the cache since IPs may change. This turns most GetDeviceInfo calls much faster. Add a dedicated lock for the xport_info_cache so concurrent GetDeviceInfo calls don't race on refresh/invalidations
This commit is contained in:
parent
0b7f642d4a
commit
5745c8a640
@ -11,7 +11,7 @@ import copy
|
||||
import threading
|
||||
from collections import namedtuple
|
||||
from os import path
|
||||
from time import sleep
|
||||
from time import monotonic, sleep
|
||||
|
||||
from usrp_mpm import tlv_eeprom
|
||||
from usrp_mpm.compat_num import CompatNumber
|
||||
@ -47,6 +47,10 @@ X400_DEVICE_DNA_COMPAT = (8, 3)
|
||||
X400_DEFAULT_ENABLE_PPS_EXPORT = True
|
||||
X400_DEFAULT_TRIG_DIRECTION = ClockingAuxBrdControl.DIRECTION_OUTPUT
|
||||
X400_MONITOR_THREAD_INTERVAL = 1.0 # seconds
|
||||
# How long to cache the xport info. The result is stable per session
|
||||
# (init() invalidates it on IP changes), so it can be cached well beyond
|
||||
# the RPC deadline window.
|
||||
X400_XPORT_INFO_CACHE_TTL = 10.0 # seconds
|
||||
QSFPModuleConfig = namedtuple("QSFPModuleConfig", "modprs modsel devsymbol")
|
||||
X400_QSFP_I2C_CONFIGS = [
|
||||
QSFPModuleConfig(modprs="QSFP0_MODPRS", modsel="QSFP0_MODSEL_n", devsymbol="qsfp0_i2c"),
|
||||
@ -307,6 +311,9 @@ class x4xx(ZynqComponents, PeriphManagerBase):
|
||||
self.ctrlport_regs = None
|
||||
self.cpld_control = None
|
||||
self.dio_control = None
|
||||
self._xport_info_cache = None
|
||||
self._xport_info_cache_ts = 0.0
|
||||
self._xport_info_cache_lock = threading.Lock()
|
||||
try:
|
||||
self._init_peripherals(args)
|
||||
self.init_dboards(args)
|
||||
@ -667,6 +674,9 @@ class x4xx(ZynqComponents, PeriphManagerBase):
|
||||
args.get("pps_export", X400_DEFAULT_ENABLE_PPS_EXPORT),
|
||||
args.get("trig_direction", X400_DEFAULT_TRIG_DIRECTION),
|
||||
)
|
||||
# Session init may have (re)assigned interface IPs; drop stale xport info.
|
||||
with self._xport_info_cache_lock:
|
||||
self._xport_info_cache = None
|
||||
return result
|
||||
|
||||
def deinit(self):
|
||||
@ -719,7 +729,7 @@ class x4xx(ZynqComponents, PeriphManagerBase):
|
||||
"""
|
||||
if not self._device_initialized:
|
||||
return {}
|
||||
device_info = self._xport_mgrs["udp"].get_xport_info()
|
||||
device_info = dict(self._get_xport_info_cached())
|
||||
device_info.update(
|
||||
{
|
||||
"fpga_version": "{}.{}".format(*self.mboard_regs_control.get_compat_number()),
|
||||
@ -731,6 +741,35 @@ class x4xx(ZynqComponents, PeriphManagerBase):
|
||||
device_info.update({"device_dna": self._device_dna})
|
||||
return device_info
|
||||
|
||||
def _get_xport_info_cached(self):
|
||||
"""Return CHDR interface/IP info, cached for a short interval.
|
||||
|
||||
get_xport_info() enumerates network interfaces via netlink/pyudev, which
|
||||
is slow and doesn't yield to the gevent loop. GetDeviceInfo is unclaimed
|
||||
and gets flooded during device discovery, so caching this briefly (for
|
||||
X400_XPORT_INFO_CACHE_TTL seconds) keeps it from starving other RPCs and
|
||||
makes device discovery faster.
|
||||
|
||||
gRPC serves RPCs from a thread pool, so concurrent GetDeviceInfo calls
|
||||
can all see a stale cache at once; the lock ensures only one of them
|
||||
redoes the enumeration while the rest wait for that result instead of
|
||||
each redundantly enumerating in parallel.
|
||||
"""
|
||||
now = monotonic()
|
||||
if (
|
||||
self._xport_info_cache is None
|
||||
or now - self._xport_info_cache_ts > X400_XPORT_INFO_CACHE_TTL
|
||||
):
|
||||
with self._xport_info_cache_lock:
|
||||
now = monotonic()
|
||||
if (
|
||||
self._xport_info_cache is None
|
||||
or now - self._xport_info_cache_ts > X400_XPORT_INFO_CACHE_TTL
|
||||
):
|
||||
self._xport_info_cache = self._xport_mgrs["udp"].get_xport_info()
|
||||
self._xport_info_cache_ts = now
|
||||
return self._xport_info_cache
|
||||
|
||||
@no_claim
|
||||
def is_db_gpio_ifc_present(self, db_idx):
|
||||
"""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user