Skip to content

Commit a6abe63

Browse files
committed
python: fix performance of ResourceStatus.get_drain_info()
Problem: The ResourceStatus get_drain_info() method is very slow when there are many drained ranks because it uses a linear search. Since it will be called at least once per rank, it causes an exponential performance hit based on the number of drained ranks. Add a mapping from rank to DrainInfo object in the ResourceStatus class and use this instead of a search in get_drain_info(). Fixes #5859
1 parent b0ecae0 commit a6abe63

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

src/bindings/python/flux/resource/status.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,16 @@ def _recalculate(self, include_ranks=None):
108108

109109
# drain_info: ranks, timestamp, reason tuples for all drained resources
110110
self.drain_info = []
111+
self._drain_lookup = {}
111112
for drain_ranks, entry in self.rstatus["drain"].items():
112113
ranks = IDset(drain_ranks)
113114
if include_ranks is not None:
114115
ranks = ranks.intersect(include_ranks)
115116
self.drained += ranks
116117
info = DrainInfo(ranks, entry["timestamp"], entry["reason"])
117118
self.drain_info.append(info)
119+
for rank in ranks:
120+
self._drain_lookup[rank] = info
118121

119122
# create the set of draining ranks as the intersection of
120123
# drained and allocated
@@ -146,7 +149,7 @@ def get_drain_info(self, rank):
146149
"""
147150
if rank not in self.all:
148151
raise ValueError("invalid rank {rank}")
149-
return next((i for i in self.drain_info if rank in i.ranks), None)
152+
return self._drain_lookup.get(rank)
150153

151154

152155
class ResourceStatusRPC:

0 commit comments

Comments
 (0)