From: Tomas Glozar <tglozar@xxxxxxxxxx> Instead of having duplicate code in two functions, one top-level and one member function of CpuList, have only one static function in CpuList. Additionally re-write the implementation to use a more straight forward one-pass algorithm. Signed-off-by: Tomas Glozar <tglozar@xxxxxxxxxx> --- rteval-cmd | 4 +- rteval/modules/loads/__init__.py | 4 +- rteval/modules/measurement/__init__.py | 4 +- rteval/modules/measurement/cyclictest.py | 6 +-- rteval/systopology.py | 68 ++++++++---------------- 5 files changed, 30 insertions(+), 56 deletions(-) diff --git a/rteval-cmd b/rteval-cmd index 6f613a3..7c41429 100755 --- a/rteval-cmd +++ b/rteval-cmd @@ -30,7 +30,7 @@ from rteval import RtEval, rtevalConfig from rteval.modules.loads import LoadModules from rteval.modules.measurement import MeasurementModules from rteval.version import RTEVAL_VERSION -from rteval.systopology import CpuList, SysTopology, collapse_cpulist +from rteval.systopology import CpuList, SysTopology from rteval.modules.loads.kcompile import ModuleParameters compress_cpulist = CpuList.compress_cpulist @@ -211,7 +211,7 @@ def remove_offline(cpulist): """ return cpulist in collapsed compressed form with only online cpus """ tmplist = expand_cpulist(cpulist) tmplist = SysTopology().online_cpulist(tmplist) - return collapse_cpulist(tmplist) + return CpuList.collapse_cpulist(tmplist) if __name__ == '__main__': diff --git a/rteval/modules/loads/__init__.py b/rteval/modules/loads/__init__.py index aca0c9f..13fba1e 100644 --- a/rteval/modules/loads/__init__.py +++ b/rteval/modules/loads/__init__.py @@ -11,7 +11,7 @@ import libxml2 from rteval.Log import Log from rteval.rtevalConfig import rtevalCfgSection from rteval.modules import RtEvalModules, rtevalModulePrototype -from rteval.systopology import collapse_cpulist, CpuList, SysTopology as SysTop +from rteval.systopology import CpuList, SysTopology as SysTop class LoadThread(rtevalModulePrototype): def __init__(self, name, config, logger=None): @@ -120,7 +120,7 @@ class LoadModules(RtEvalModules): cpulist = CpuList(cpulist).cpulist else: cpulist = SysTop().default_cpus() - rep_n.newProp("loadcpus", collapse_cpulist(cpulist)) + rep_n.newProp("loadcpus", CpuList.collapse_cpulist(cpulist)) return rep_n diff --git a/rteval/modules/measurement/__init__.py b/rteval/modules/measurement/__init__.py index 2a0556b..41b8022 100644 --- a/rteval/modules/measurement/__init__.py +++ b/rteval/modules/measurement/__init__.py @@ -5,7 +5,7 @@ import libxml2 from rteval.modules import RtEvalModules, ModuleContainer -from rteval.systopology import collapse_cpulist, CpuList, SysTopology as SysTop +from rteval.systopology import CpuList, SysTopology as SysTop class MeasurementProfile(RtEvalModules): """Keeps and controls all the measurement modules with the same measurement profile""" @@ -187,7 +187,7 @@ measurement profiles, based on their characteristics""" cpulist = CpuList(cpulist).cpulist else: cpulist = SysTop().online_cpus() if run_on_isolcpus else SysTop().default_cpus() - rep_n.newProp("measurecpus", collapse_cpulist(cpulist)) + rep_n.newProp("measurecpus", CpuList.collapse_cpulist(cpulist)) for mp in self.__measureprofiles: mprep_n = mp.MakeReport() diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py index 0af1d31..d865d57 100644 --- a/rteval/modules/measurement/cyclictest.py +++ b/rteval/modules/measurement/cyclictest.py @@ -17,7 +17,7 @@ import libxml2 from rteval.Log import Log from rteval.modules import rtevalModulePrototype from rteval.systopology import cpuinfo -from rteval.systopology import CpuList, SysTopology, collapse_cpulist +from rteval.systopology import CpuList, SysTopology expand_cpulist = CpuList.expand_cpulist @@ -203,7 +203,7 @@ class Cyclictest(rtevalModulePrototype): # Only include online cpus self.__cpus = CpuList(self.__cpus).cpulist # Reset cpulist from the newly calculated self.__cpus - self.__cpulist = collapse_cpulist(self.__cpus) + self.__cpulist = CpuList.collapse_cpulist(self.__cpus) self.__cpus = [str(c) for c in self.__cpus] self.__sparse = True if self.__run_on_isolcpus: @@ -220,7 +220,7 @@ class Cyclictest(rtevalModulePrototype): self.__cpus = [c for c in self.__cpus if c in cpuset or self.__run_on_isolcpus and c in isolcpus] if self.__run_on_isolcpus: self.__sparse = True - self.__cpulist = collapse_cpulist(self.__cpus) + self.__cpulist = CpuList.collapse_cpulist(self.__cpus) # Sort the list of cpus to align with the order reported by cyclictest self.__cpus.sort(key=int) diff --git a/rteval/systopology.py b/rteval/systopology.py index 62ad355..ea8e242 100644 --- a/rteval/systopology.py +++ b/rteval/systopology.py @@ -10,25 +10,6 @@ import os import os.path import glob -# Utility version of collapse_cpulist that doesn't require a CpuList object -def collapse_cpulist(cpulist): - """ Collapse a list of cpu numbers into a string range - of cpus (e.g. 0-5, 7, 9) """ - if len(cpulist) == 0: - return "" - idx = CpuList.longest_sequence(cpulist) - if idx == 0: - seq = str(cpulist[0]) - else: - if idx == 1: - seq = f"{cpulist[0]},{cpulist[idx]}" - else: - seq = f"{cpulist[0]}-{cpulist[idx]}" - - rest = collapse_cpulist(cpulist[idx+1:]) - if rest == "": - return seq - return ",".join((seq, rest)) def sysread(path, obj): """ Helper function for reading system files """ @@ -93,7 +74,7 @@ class CpuList: self.cpulist.sort() def __str__(self): - return self.__collapse_cpulist(self.cpulist) + return self.collapse_cpulist(self.cpulist) def __contains__(self, cpu): return cpu in self.cpulist @@ -114,35 +95,28 @@ class CpuList: return os.path.exists(os.path.join(CpuList.cpupath, "isolated")) @staticmethod - def longest_sequence(cpulist): - """ return index of last element of a sequence that steps by one """ - lim = len(cpulist) - for idx, _ in enumerate(cpulist): - if idx+1 == lim: - break - if int(cpulist[idx+1]) != (int(cpulist[idx])+1): - return idx - return lim - 1 - - def __collapse_cpulist(self, cpulist): - """ Collapse a list of cpu numbers into a string range + def collapse_cpulist(cpulist): + """ + Collapse a list of cpu numbers into a string range of cpus (e.g. 0-5, 7, 9) """ - if len(cpulist) == 0: - return "" - idx = self.longest_sequence(cpulist) - if idx == 0: - seq = str(cpulist[0]) - else: - if idx == 1: - seq = f"{cpulist[0]},{cpulist[idx]}" + cur_range = [None, None] + result = [] + for cpu in cpulist + [None]: + if cur_range[0] is None: + cur_range[0] = cur_range[1] = cpu + continue + if cpu is not None and cpu == cur_range[1] + 1: + # Extend currently processed range + cur_range[1] += 1 else: - seq = f"{cpulist[0]}-{cpulist[idx]}" - - rest = self.__collapse_cpulist(cpulist[idx+1:]) - if rest == "": - return seq - return ",".join((seq, rest)) + # Range processing finished, add range to string + result.append(f"{cur_range[0]}-{cur_range[1]}" + if cur_range[0] != cur_range[1] + else str(cur_range[0])) + # Reset + cur_range[0] = cur_range[1] = cpu + return ",".join(result) @staticmethod def compress_cpulist(cpulist): @@ -428,7 +402,7 @@ if __name__ == "__main__": onlcpus = s.online_cpus() print(f'onlcpus = {onlcpus}') - onlcpus = collapse_cpulist(onlcpus) + onlcpus = CpuList.collapse_cpulist(onlcpus) print(f'onlcpus = {onlcpus}') onlcpus_str = s.online_cpus_str() -- 2.41.0