Add timerlat as a measurement module
Add timerlat as a measurement module Resolves: RHEL-28058 Signed-off-by: John Kacur <jkacur@redhat.com>
This commit is contained in:
parent
d83dcd1eee
commit
3db03791e8
@ -1,6 +1,6 @@
|
|||||||
--- !Policy
|
--- !Policy
|
||||||
product_versions:
|
product_versions:
|
||||||
- rhel-9
|
- rhel-10
|
||||||
decision_context: osci_compose_gate
|
decision_context: osci_compose_gate
|
||||||
rules:
|
rules:
|
||||||
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
|
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
|
||||||
|
70
rteval-Add-relative-cpulists-for-loads.patch
Normal file
70
rteval-Add-relative-cpulists-for-loads.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
From 636701e66cb98b979948b7a47320809c734e2a9e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tomas Glozar <tglozar@redhat.com>
|
||||||
|
Date: Thu, 4 Apr 2024 10:14:38 +0200
|
||||||
|
Subject: [PATCH] rteval: Add relative cpulists for loads
|
||||||
|
|
||||||
|
Relative cpulists were added for measurements in 64ce7848 ("rteval: Add
|
||||||
|
relative cpulists for measurements"). It was observed since that this
|
||||||
|
feature would also be useful for load cpulists, for example when the
|
||||||
|
measurements are performed externally and rteval is only used to run
|
||||||
|
loads.
|
||||||
|
|
||||||
|
Add support for relative cpulists also for loads. This works the same
|
||||||
|
way as for measurements using parse_cpulist_from_config, only difference
|
||||||
|
is there is no --loads-run-on-isolcpus option. That is, --loads-cpulist
|
||||||
|
now also takes lists with addition (+) and removal (-) of CPUs against
|
||||||
|
the default list, e.g. +0,1,-7,8.
|
||||||
|
|
||||||
|
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval-cmd | 17 ++++++++++-------
|
||||||
|
1 file changed, 10 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval-cmd b/rteval-cmd
|
||||||
|
index ed13af3..c72bc61 100755
|
||||||
|
--- a/rteval-cmd
|
||||||
|
+++ b/rteval-cmd
|
||||||
|
@@ -331,29 +331,32 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
|
ldcfg = config.GetSection('loads')
|
||||||
|
msrcfg = config.GetSection('measurement')
|
||||||
|
+ # Remember if cpulists were explicitly set by the user before running
|
||||||
|
+ # parse_cpulist_from_config, which generates default value for them
|
||||||
|
msrcfg_cpulist_present = msrcfg.cpulist != ""
|
||||||
|
- # Parse measurement cpulist using parse_cpulist_from_config to account for run-on-isolcpus
|
||||||
|
- # and relative cpusets
|
||||||
|
+ ldcfg_cpulist_present = ldcfg.cpulist != ""
|
||||||
|
+ # Parse cpulists using parse_cpulist_from_config to account for
|
||||||
|
+ # run-on-isolcpus and relative cpusets
|
||||||
|
cpulist = parse_cpulist_from_config(msrcfg.cpulist, msrcfg.run_on_isolcpus)
|
||||||
|
if msrcfg_cpulist_present and not cpulist_utils.is_relative(msrcfg.cpulist) and msrcfg.run_on_isolcpus:
|
||||||
|
logger.log(Log.WARN, "ignoring --measurement-run-on-isolcpus, since cpulist is specified")
|
||||||
|
msrcfg.cpulist = collapse_cpulist(cpulist)
|
||||||
|
- if ldcfg.cpulist:
|
||||||
|
- ldcfg.cpulist = remove_offline(ldcfg.cpulist)
|
||||||
|
+ cpulist = parse_cpulist_from_config(ldcfg.cpulist)
|
||||||
|
+ ldcfg.cpulist = collapse_cpulist(cpulist)
|
||||||
|
# if we only specified one set of cpus (loads or measurement)
|
||||||
|
# default the other to the inverse of the specified list
|
||||||
|
- if not ldcfg.cpulist and msrcfg_cpulist_present:
|
||||||
|
+ if not ldcfg_cpulist_present and msrcfg_cpulist_present:
|
||||||
|
tmplist = expand_cpulist(msrcfg.cpulist)
|
||||||
|
tmplist = SysTopology().invert_cpulist(tmplist)
|
||||||
|
tmplist = cpulist_utils.online_cpulist(tmplist)
|
||||||
|
ldcfg.cpulist = collapse_cpulist(tmplist)
|
||||||
|
- if not msrcfg_cpulist_present and ldcfg.cpulist:
|
||||||
|
+ if not msrcfg_cpulist_present and ldcfg_cpulist_present:
|
||||||
|
tmplist = expand_cpulist(ldcfg.cpulist)
|
||||||
|
tmplist = SysTopology().invert_cpulist(tmplist)
|
||||||
|
tmplist = cpulist_utils.online_cpulist(tmplist)
|
||||||
|
msrcfg.cpulist = collapse_cpulist(tmplist)
|
||||||
|
|
||||||
|
- if ldcfg.cpulist:
|
||||||
|
+ if ldcfg_cpulist_present:
|
||||||
|
logger.log(Log.DEBUG, f"loads cpulist: {ldcfg.cpulist}")
|
||||||
|
# if --onlyload is specified msrcfg.cpulist is unused
|
||||||
|
if msrcfg_cpulist_present and not rtevcfg.onlyload:
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
189
rteval-Add-rtla-timerlat-as-a-measurement-module.patch
Normal file
189
rteval-Add-rtla-timerlat-as-a-measurement-module.patch
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
From 393c95ee69ec98816a26aa0583f6b1cac4acb5e7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Fri, 12 Apr 2024 14:40:37 -0400
|
||||||
|
Subject: [PATCH 02/13] rteval: Add rtla timerlat as a measurement module
|
||||||
|
|
||||||
|
This is the first step to adding timerlat as a measurement module
|
||||||
|
With this change you can run timerlat as a standalone rteval file like
|
||||||
|
this (as root)
|
||||||
|
|
||||||
|
python rteval/modules/measurement/timerlat.py
|
||||||
|
|
||||||
|
You can also modify your rteval.conf to list timerlat in the
|
||||||
|
[measurement] section, for example like this
|
||||||
|
|
||||||
|
[measurement]
|
||||||
|
cyclictest: module
|
||||||
|
timerlat: module
|
||||||
|
|
||||||
|
and then both measurement moduels will be run from rteval, for example
|
||||||
|
|
||||||
|
rteval -D -d5m --measurement-cpulist=1-5
|
||||||
|
|
||||||
|
Will run rteval with Debug info, for 5m and cyclictest and timerlat will
|
||||||
|
run on cpus 1-5 and load modules will run on the other available cpus.
|
||||||
|
|
||||||
|
Currently MakeReport just prints to standard out the same information
|
||||||
|
that timerlat outputs, in otherwords, there is no processing into xml
|
||||||
|
yet. Also, there is no way to invoke tracing at the time, but that will
|
||||||
|
be added soon!
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval-cmd | 1 +
|
||||||
|
rteval/modules/measurement/timerlat.py | 131 +++++++++++++++++++++++++
|
||||||
|
2 files changed, 132 insertions(+)
|
||||||
|
create mode 100644 rteval/modules/measurement/timerlat.py
|
||||||
|
|
||||||
|
diff --git a/rteval-cmd b/rteval-cmd
|
||||||
|
index c72bc614ad78..5cb6d7a44523 100755
|
||||||
|
--- a/rteval-cmd
|
||||||
|
+++ b/rteval-cmd
|
||||||
|
@@ -247,6 +247,7 @@ if __name__ == '__main__':
|
||||||
|
if not config.HasSection('measurement'):
|
||||||
|
config.AppendConfig('measurement', {
|
||||||
|
'cyclictest' : 'module',
|
||||||
|
+ 'timerlat' : 'module',
|
||||||
|
'sysstat' : 'module'})
|
||||||
|
|
||||||
|
# Prepare log levels before loading modules, not to have unwanted log messages
|
||||||
|
diff --git a/rteval/modules/measurement/timerlat.py b/rteval/modules/measurement/timerlat.py
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000000..d4e78de8d2a2
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/rteval/modules/measurement/timerlat.py
|
||||||
|
@@ -0,0 +1,131 @@
|
||||||
|
+# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
+#
|
||||||
|
+# Copyright 2024 John Kacur <jkacur@redhat.com>
|
||||||
|
+#
|
||||||
|
+""" timerlat.py - objectd to manage rtla timerlat """
|
||||||
|
+import os
|
||||||
|
+import subprocess
|
||||||
|
+import signal
|
||||||
|
+import time
|
||||||
|
+import tempfile
|
||||||
|
+import libxml2
|
||||||
|
+from rteval.Log import Log
|
||||||
|
+from rteval.modules import rtevalModulePrototype
|
||||||
|
+from rteval.systopology import cpuinfo, SysTopology
|
||||||
|
+from rteval.cpulist_utils import expand_cpulist, collapse_cpulist
|
||||||
|
+
|
||||||
|
+class Timerlat(rtevalModulePrototype):
|
||||||
|
+ """ measurement modules for rteval """
|
||||||
|
+ def __init__(self, config, logger=None):
|
||||||
|
+ rtevalModulePrototype.__init__(self, 'measurement', 'timerlat', logger)
|
||||||
|
+
|
||||||
|
+ self.__cfg = config
|
||||||
|
+
|
||||||
|
+ self.__numanodes = int(self.__cfg.setdefault('numanodes', 0))
|
||||||
|
+ self.__priority = int(self.__cfg.setdefault('priority', 95))
|
||||||
|
+
|
||||||
|
+ self.__cpulist = self.__cfg.setdefault('cpulist', "")
|
||||||
|
+ self.__cpus = [str(c) for c in expand_cpulist(self.__cpulist)]
|
||||||
|
+ self.__numcores = len(self.__cpus)
|
||||||
|
+
|
||||||
|
+ self.__timerlat_out = None
|
||||||
|
+ self.__timerlat_err = None
|
||||||
|
+ self.__started = False
|
||||||
|
+ self._log(Log.DEBUG, f"system using {self.__numcores} cpu cores")
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def _WorkloadSetup(self):
|
||||||
|
+ self.__timerlat_process = None
|
||||||
|
+
|
||||||
|
+ def _WorkloadBuild(self):
|
||||||
|
+ self._setReady()
|
||||||
|
+
|
||||||
|
+ def _WorkloadPrepare(self):
|
||||||
|
+ self.__cmd = ['rtla', 'timerlat', 'hist', '-P', f'f:{int(self.__priority)}', '-u']
|
||||||
|
+ self.__cmd.append(f'-c{self.__cpulist}')
|
||||||
|
+ self._log(Log.DEBUG, f'self.__cmd = {self.__cmd}')
|
||||||
|
+ self.__timerlat_out = tempfile.SpooledTemporaryFile(mode='w+b')
|
||||||
|
+ self.__timerlat_err = tempfile.SpooledTemporaryFile(mode='w+b')
|
||||||
|
+
|
||||||
|
+ def _WorkloadTask(self):
|
||||||
|
+ if self.__started:
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
+ self._log(Log.DEBUG, f'starting with cmd: {" ".join(self.__cmd)}')
|
||||||
|
+
|
||||||
|
+ self.__timerlat_out.seek(0)
|
||||||
|
+ self.__timerlat_err.seek(0)
|
||||||
|
+ try:
|
||||||
|
+ self.__timerlat_process = subprocess.Popen(self.__cmd,
|
||||||
|
+ stdout=self.__timerlat_out,
|
||||||
|
+ stderr=self.__timerlat_err,
|
||||||
|
+ stdin=None)
|
||||||
|
+ self.__started = True
|
||||||
|
+ except OSError:
|
||||||
|
+ self.__started = False
|
||||||
|
+
|
||||||
|
+ def WorkloadAlive(self):
|
||||||
|
+ if self.__started:
|
||||||
|
+ return self.__timerlat_process.poll() is None
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ def _WorkloadCleanup(self):
|
||||||
|
+ if not self.__started:
|
||||||
|
+ return
|
||||||
|
+ while self.__timerlat_process.poll() is None:
|
||||||
|
+ self._log(Log.DEBUG, "Sending SIGINT")
|
||||||
|
+ os.kill(self.__timerlat_process.pid, signal.SIGINT)
|
||||||
|
+ time.sleep(2)
|
||||||
|
+
|
||||||
|
+ self._setFinished()
|
||||||
|
+ self.__started = False
|
||||||
|
+
|
||||||
|
+ def MakeReport(self):
|
||||||
|
+ self.__timerlat_out.seek(0)
|
||||||
|
+ for line in self.__timerlat_out:
|
||||||
|
+ line = bytes.decode(line)
|
||||||
|
+ print(line)
|
||||||
|
+ self.__timerlat_out.close()
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def ModuleInfo():
|
||||||
|
+ """ Required measurement module information """
|
||||||
|
+ return {"parallel": True,
|
||||||
|
+ "loads": True}
|
||||||
|
+
|
||||||
|
+def ModuleParameters():
|
||||||
|
+ """ default parameters """
|
||||||
|
+ return {"priority": {"descr": "Run rtla timerlat with this priority",
|
||||||
|
+ "default": 95,
|
||||||
|
+ "metavar": "PRIO" }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+def create(params, logger):
|
||||||
|
+ """ Instantiate a Timerlat measurement module object"""
|
||||||
|
+ return Timerlat(params, logger)
|
||||||
|
+
|
||||||
|
+if __name__ == '__main__':
|
||||||
|
+ from rteval.rtevalConfig import rtevalConfig
|
||||||
|
+
|
||||||
|
+ l = Log()
|
||||||
|
+ l.SetLogVerbosity(Log.INFO|Log.DEBUG|Log.ERR|Log.WARN)
|
||||||
|
+
|
||||||
|
+ cfg = rtevalConfig({}, logger=l)
|
||||||
|
+ prms = {}
|
||||||
|
+ modprms = ModuleParameters()
|
||||||
|
+ for c, p in list(modprms.items()):
|
||||||
|
+ prms[c] = p['default']
|
||||||
|
+ cfg.AppendConfig('timerlat', prms)
|
||||||
|
+
|
||||||
|
+ cfg_tl = cfg.GetSection('timerlat')
|
||||||
|
+ cfg_tl.cpulist = collapse_cpulist(SysTopology().online_cpus())
|
||||||
|
+
|
||||||
|
+ RUNTIME = 10
|
||||||
|
+
|
||||||
|
+ tl = Timerlat(cfg_tl, l)
|
||||||
|
+ tl._WorkloadSetup()
|
||||||
|
+ tl._WorkloadPrepare()
|
||||||
|
+ tl._WorkloadTask()
|
||||||
|
+ time.sleep(RUNTIME)
|
||||||
|
+ tl._WorkloadCleanup()
|
||||||
|
+ tl.MakeReport()
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
178
rteval-Add-summary-reporting-for-timerlat.patch
Normal file
178
rteval-Add-summary-reporting-for-timerlat.patch
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
From 20fbcc1547d77a77a3e333bac28b7f28632d8707 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Fri, 26 Apr 2024 14:45:48 -0400
|
||||||
|
Subject: [PATCH 08/13] rteval: Add summary reporting for timerlat
|
||||||
|
|
||||||
|
This adds an rteval section to the xsl file and generates a timerlat
|
||||||
|
report at the end of a run. To use it edit your rteval.conf file
|
||||||
|
to comment out cyclictest and uncomment timerlat
|
||||||
|
|
||||||
|
Another interesting thing you can do is uncomment both of them and
|
||||||
|
get a report from both in one run.
|
||||||
|
|
||||||
|
You can also use this with the summary report, for example
|
||||||
|
|
||||||
|
rteval -Z rteval-20240426-3/summary.xml
|
||||||
|
|
||||||
|
will work with timerlat now. (or both cyclictest and timerlat at the
|
||||||
|
same time.)
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval.conf | 1 +
|
||||||
|
rteval/rteval_text.xsl | 103 +++++++++++++++++++++++++++++++++++++++--
|
||||||
|
2 files changed, 100 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval.conf b/rteval.conf
|
||||||
|
index 4c32fcf4d842..601410b51c28 100644
|
||||||
|
--- a/rteval.conf
|
||||||
|
+++ b/rteval.conf
|
||||||
|
@@ -7,6 +7,7 @@ report_interval: 600
|
||||||
|
|
||||||
|
[measurement]
|
||||||
|
cyclictest: module
|
||||||
|
+# timerlat: module
|
||||||
|
|
||||||
|
[loads]
|
||||||
|
kcompile: module
|
||||||
|
diff --git a/rteval/rteval_text.xsl b/rteval/rteval_text.xsl
|
||||||
|
index f526526d4d49..1e9c0f0d26c5 100644
|
||||||
|
--- a/rteval/rteval_text.xsl
|
||||||
|
+++ b/rteval/rteval_text.xsl
|
||||||
|
@@ -201,11 +201,11 @@
|
||||||
|
<!-- -->
|
||||||
|
<!-- select="cyclictest|new_foo_section|another_section" -->
|
||||||
|
<!-- -->
|
||||||
|
- <xsl:apply-templates select="cyclictest|hwlatdetect[@format='1.0']|sysstat"/>
|
||||||
|
+ <xsl:apply-templates select="cyclictest|timerlat|hwlatdetect[@format='1.0']|sysstat"/>
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
- <!-- Format the cyclic test section of the report -->
|
||||||
|
+ <!-- Format the cyclictest section of the report -->
|
||||||
|
<xsl:template match="/rteval/Measurements/Profile/cyclictest">
|
||||||
|
<xsl:text> Latency test </xsl:text>
|
||||||
|
|
||||||
|
@@ -237,7 +237,7 @@
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
- <!-- Format the CPU core section in the cyclict test part -->
|
||||||
|
+ <!-- Format the CPU core section in the cyclictest part -->
|
||||||
|
<xsl:template match="/rteval/Measurements/Profile/cyclictest/core">
|
||||||
|
<xsl:text> CPU core </xsl:text>
|
||||||
|
<xsl:value-of select="@id"/>
|
||||||
|
@@ -300,6 +300,101 @@
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
+ <!-- Format the timerlat section of the report -->
|
||||||
|
+ <xsl:template match="/rteval/Measurements/Profile/timerlat">
|
||||||
|
+ <xsl:text> Latency test </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Started: </xsl:text>
|
||||||
|
+ <xsl:value-of select="timestamps/runloop_start"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Stopped: </xsl:text>
|
||||||
|
+ <xsl:value-of select="timestamps/runloop_stop"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Command: </xsl:text>
|
||||||
|
+ <xsl:value-of select="@command_line"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:apply-templates select="abort_report"/>
|
||||||
|
+
|
||||||
|
+ <xsl:text> System: </xsl:text>
|
||||||
|
+ <xsl:value-of select="system/@description"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Statistics: </xsl:text>
|
||||||
|
+ <xsl:apply-templates select="system/statistics"/>
|
||||||
|
+
|
||||||
|
+ <!-- Add CPU core info and stats-->
|
||||||
|
+ <xsl:apply-templates select="core">
|
||||||
|
+ <xsl:sort select="@id" data-type="number"/>
|
||||||
|
+ </xsl:apply-templates>
|
||||||
|
+ </xsl:template>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ <!-- Format the CPU core section in the timerlat part -->
|
||||||
|
+ <xsl:template match="/rteval/Measurements/Profile/timerlat/core">
|
||||||
|
+ <xsl:text> CPU core </xsl:text>
|
||||||
|
+ <xsl:value-of select="@id"/>
|
||||||
|
+ <xsl:text> Priority: </xsl:text>
|
||||||
|
+ <xsl:value-of select="@priority"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+ <xsl:text> Statistics: </xsl:text>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+ <xsl:apply-templates select="statistics"/>
|
||||||
|
+ </xsl:template>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ <!-- Generic formatting of statistics information -->
|
||||||
|
+ <xsl:template match="/rteval/Measurements/Profile/timerlat/*/statistics">
|
||||||
|
+ <xsl:text> Samples: </xsl:text>
|
||||||
|
+ <xsl:value-of select="samples"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:if test="samples > 0">
|
||||||
|
+ <xsl:text> Mean: </xsl:text>
|
||||||
|
+ <xsl:value-of select="mean"/>
|
||||||
|
+ <xsl:value-of select="mean/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Median: </xsl:text>
|
||||||
|
+ <xsl:value-of select="median"/>
|
||||||
|
+ <xsl:value-of select="median/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Mode: </xsl:text>
|
||||||
|
+ <xsl:value-of select="mode"/>
|
||||||
|
+ <xsl:value-of select="mode/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Range: </xsl:text>
|
||||||
|
+ <xsl:value-of select="range"/>
|
||||||
|
+ <xsl:value-of select="range/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Min: </xsl:text>
|
||||||
|
+ <xsl:value-of select="minimum"/>
|
||||||
|
+ <xsl:value-of select="minimum/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Max: </xsl:text>
|
||||||
|
+ <xsl:value-of select="maximum"/>
|
||||||
|
+ <xsl:value-of select="maximum/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Mean Absolute Dev: </xsl:text>
|
||||||
|
+ <xsl:value-of select="mean_absolute_deviation"/>
|
||||||
|
+ <xsl:value-of select="mean_absolute_deviation/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:text> Std.dev: </xsl:text>
|
||||||
|
+ <xsl:value-of select="standard_deviation"/>
|
||||||
|
+ <xsl:value-of select="standard_deviation/@unit"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+ </xsl:if>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+ </xsl:template>
|
||||||
|
+
|
||||||
|
|
||||||
|
<!-- Format the hwlatdetect test section of the report -->
|
||||||
|
<xsl:template match="/rteval/Measurements/Profile/hwlatdetect[@format='1.0' and not(@aborted)]">
|
||||||
|
@@ -340,7 +435,7 @@
|
||||||
|
<xsl:text>us </xsl:text>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
- <!-- Format the cyclic test section of the report -->
|
||||||
|
+ <!-- Format the cyclictest section of the report -->
|
||||||
|
<xsl:template match="/rteval/Measurements/Profile/sysstat">
|
||||||
|
<xsl:text> sysstat measurements </xsl:text>
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
88
rteval-Cyclictest.py-Make-standalone-file-work-again.patch
Normal file
88
rteval-Cyclictest.py-Make-standalone-file-work-again.patch
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
From ea72c99ead85d1fcf156b9a3825a547ba7f4d0f8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Fri, 12 Apr 2024 14:34:11 -0400
|
||||||
|
Subject: [PATCH 01/13] rteval: Cyclictest.py: Make standalone file work again
|
||||||
|
|
||||||
|
Make standalone Cyclictest.py work again for testing purposes
|
||||||
|
- remove unused parse_cpulist_from_config
|
||||||
|
- Instead of "import as", use "from" and the requested functionality
|
||||||
|
- Obtain the default buckets from the ModuleParameters to use if a
|
||||||
|
number is not otherwise provided
|
||||||
|
- set the cpulist to "" if not otherwise provided
|
||||||
|
- add a few docstrings to functions
|
||||||
|
- obtain a default cpulist from online_cpus for the standalone test
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 19 ++++++++-----------
|
||||||
|
1 file changed, 8 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index 722422589d62..671426e13c4d 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -16,10 +16,8 @@ import math
|
||||||
|
import libxml2
|
||||||
|
from rteval.Log import Log
|
||||||
|
from rteval.modules import rtevalModulePrototype
|
||||||
|
-from rteval.systopology import cpuinfo, parse_cpulist_from_config
|
||||||
|
-import rteval.cpulist_utils as cpulist_utils
|
||||||
|
-
|
||||||
|
-expand_cpulist = cpulist_utils.expand_cpulist
|
||||||
|
+from rteval.systopology import cpuinfo, SysTopology
|
||||||
|
+from rteval.cpulist_utils import expand_cpulist, collapse_cpulist
|
||||||
|
|
||||||
|
class RunData:
|
||||||
|
'''class to keep instance data from a cyclictest run'''
|
||||||
|
@@ -190,10 +188,11 @@ class Cyclictest(rtevalModulePrototype):
|
||||||
|
# Create a RunData object per CPU core
|
||||||
|
self.__numanodes = int(self.__cfg.setdefault('numanodes', 0))
|
||||||
|
self.__priority = int(self.__cfg.setdefault('priority', 95))
|
||||||
|
- self.__buckets = int(self.__cfg.setdefault('buckets', 2000))
|
||||||
|
+ default_buckets = ModuleParameters()["buckets"]["default"]
|
||||||
|
+ self.__buckets = int(self.__cfg.setdefault('buckets', default_buckets))
|
||||||
|
self.__numcores = 0
|
||||||
|
self.__cyclicdata = {}
|
||||||
|
- self.__cpulist = self.__cfg.cpulist
|
||||||
|
+ self.__cpulist = self.__cfg.setdefault('cpulist', "")
|
||||||
|
self.__cpus = [str(c) for c in expand_cpulist(self.__cpulist)]
|
||||||
|
self.__numcores = len(self.__cpus)
|
||||||
|
|
||||||
|
@@ -393,14 +392,13 @@ class Cyclictest(rtevalModulePrototype):
|
||||||
|
return rep_n
|
||||||
|
|
||||||
|
|
||||||
|
-
|
||||||
|
def ModuleInfo():
|
||||||
|
return {"parallel": True,
|
||||||
|
"loads": True}
|
||||||
|
|
||||||
|
|
||||||
|
-
|
||||||
|
def ModuleParameters():
|
||||||
|
+ """ default parameters """
|
||||||
|
return {"interval": {"descr": "Base interval of the threads in microseconds",
|
||||||
|
"default": 100,
|
||||||
|
"metavar": "INTV_US"},
|
||||||
|
@@ -421,6 +419,7 @@ def ModuleParameters():
|
||||||
|
|
||||||
|
|
||||||
|
def create(params, logger):
|
||||||
|
+ """ Instantiate a Cyclictest measurement module object """
|
||||||
|
return Cyclictest(params, logger)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -438,9 +437,7 @@ if __name__ == '__main__':
|
||||||
|
cfg.AppendConfig('cyclictest', prms)
|
||||||
|
|
||||||
|
cfg_ct = cfg.GetSection('cyclictest')
|
||||||
|
- cfg_ct.reportdir = "."
|
||||||
|
- cfg_ct.buckets = 200
|
||||||
|
- # cfg_ct.breaktrace = 30
|
||||||
|
+ cfg_ct.cpulist = collapse_cpulist(SysTopology().online_cpus())
|
||||||
|
|
||||||
|
runtime = 10
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
69
rteval-Generate-raw-histogram-data-for-an-existing-t.patch
Normal file
69
rteval-Generate-raw-histogram-data-for-an-existing-t.patch
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
From 843ff713340ab701aa8859ca8b3d8a776608175c Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Mon, 29 Apr 2024 10:47:41 -0400
|
||||||
|
Subject: [PATCH 09/13] rteval: Generate raw histogram data for an existing
|
||||||
|
timerlat report
|
||||||
|
|
||||||
|
Generate raw histogram data for an existing timerlat report.
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/rteval_histogram_raw.xsl | 29 ++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/rteval_histogram_raw.xsl b/rteval/rteval_histogram_raw.xsl
|
||||||
|
index 038419bf03b7..00b2be34f305 100644
|
||||||
|
--- a/rteval/rteval_histogram_raw.xsl
|
||||||
|
+++ b/rteval/rteval_histogram_raw.xsl
|
||||||
|
@@ -12,15 +12,26 @@
|
||||||
|
|
||||||
|
<!-- Extract overall system histogram data -->
|
||||||
|
<xsl:apply-templates select="Measurements/Profile/cyclictest/system/histogram/bucket">
|
||||||
|
- <xsl:with-param name="label" select="'system'"/>
|
||||||
|
+ <xsl:with-param name="label" select="'system'"/>
|
||||||
|
<xsl:sort select="Measurements/Profile/cyclictest/core/histogram/bucket/@index" data-type="number"/>
|
||||||
|
</xsl:apply-templates>
|
||||||
|
|
||||||
|
+ <xsl:apply-templates select="Measurements/Profile/timerlat/system/histogram/bucket">
|
||||||
|
+ <xsl:with-param name="label" select="'system'"/>
|
||||||
|
+ <xsl:sort select="Measurements/Profile/timerlat/core/histogram/bucket/@index" data-type="number"/>
|
||||||
|
+ </xsl:apply-templates>
|
||||||
|
+
|
||||||
|
<!-- Extract per cpu core histogram data -->
|
||||||
|
<xsl:apply-templates select="Measurements/Profile/cyclictest/core/histogram/bucket">
|
||||||
|
<xsl:sort select="Measurements/Profile/cyclictest/core/@id" data-type="number"/>
|
||||||
|
<xsl:sort select="Measurements/Profile/cyclictest/core/histogram/bucket/@index" data-type="number"/>
|
||||||
|
</xsl:apply-templates>
|
||||||
|
+
|
||||||
|
+ <xsl:apply-templates select="Measurements/Profile/timerlat/core/histogram/bucket">
|
||||||
|
+ <xsl:sort select="Measurements/Profile/timerlat/core/@id" data-type="number"/>
|
||||||
|
+ <xsl:sort select="Measurements/Profile/timerlat/core/histogram/bucket/@index" data-type="number"/>
|
||||||
|
+ </xsl:apply-templates>
|
||||||
|
+
|
||||||
|
</xsl:template>
|
||||||
|
<!-- -->
|
||||||
|
<!-- End of main report framework -->
|
||||||
|
@@ -43,4 +54,20 @@
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
+ <xsl:template match="/rteval/Measurements/Profile/timerlat/*/histogram/bucket">
|
||||||
|
+ <xsl:param name="label"/>
|
||||||
|
+ <xsl:choose>
|
||||||
|
+ <!-- If we don't have a id tag in what should be a 'core' tag, use the given label -->
|
||||||
|
+ <xsl:when test="../../@id"><xsl:value-of select="../../@id"/></xsl:when>
|
||||||
|
+ <xsl:otherwise><xsl:value-of select="$label"/></xsl:otherwise>
|
||||||
|
+ </xsl:choose>
|
||||||
|
+ <xsl:text>	</xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:value-of select="@index"/>
|
||||||
|
+ <xsl:text>	</xsl:text>
|
||||||
|
+
|
||||||
|
+ <xsl:value-of select="@value"/>
|
||||||
|
+ <xsl:text> </xsl:text>
|
||||||
|
+ </xsl:template>
|
||||||
|
+
|
||||||
|
</xsl:stylesheet>
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
60
rteval-Make-output-work-with-new-dmiinfo-format.patch
Normal file
60
rteval-Make-output-work-with-new-dmiinfo-format.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
From 701ab9f5d50fb0e1308ad8ea163d49525d3d90af Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tomas Glozar <tglozar@redhat.com>
|
||||||
|
Date: Mon, 29 Apr 2024 10:47:20 +0200
|
||||||
|
Subject: [PATCH 10/13] rteval: Make output work with new dmiinfo format
|
||||||
|
|
||||||
|
Commit 43c45ba7 ("rteval: Implement initial dmidecode support")
|
||||||
|
re-introduced DMI information into rteval XML summary, but in a
|
||||||
|
different format, which is not correctly picked up in rteval_text.xsl
|
||||||
|
for formatting BIOS and vendor information into rteval text output.
|
||||||
|
|
||||||
|
This lead to the information not being displayed correctly:
|
||||||
|
Model: -
|
||||||
|
BIOS version: (ver: , rev :, release date: )
|
||||||
|
|
||||||
|
Modify the relevant section of rteval_text.xsl to make it understand the
|
||||||
|
new format. Also, adjust the incorrect spacing around "rev".
|
||||||
|
|
||||||
|
New output (in QEMU VM):
|
||||||
|
Model: QEMU - Standard PC (Q35 + ICH9, 2009)
|
||||||
|
BIOS version: SeaBIOS (ver: 1.16.3-1.fc39, rev: 0.0, release date: 04/01/2014)
|
||||||
|
|
||||||
|
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/rteval_text.xsl | 14 +++++++-------
|
||||||
|
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/rteval_text.xsl b/rteval/rteval_text.xsl
|
||||||
|
index 1e9c0f0d26c5..2f03bda0bb55 100644
|
||||||
|
--- a/rteval/rteval_text.xsl
|
||||||
|
+++ b/rteval/rteval_text.xsl
|
||||||
|
@@ -39,18 +39,18 @@
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
|
||||||
|
<xsl:text> Model: </xsl:text>
|
||||||
|
- <xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/GeneralInfo/Manufacturer|HardwareInfo/GeneralInfo/ProductName"/>
|
||||||
|
- <xsl:text> - </xsl:text><xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/GeneralInfo/ProductName|HardwareInfo/GeneralInfo/ProductName"/>
|
||||||
|
+ <xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='System Information']/Field[@Name='Manufacturer']"/>
|
||||||
|
+ <xsl:text> - </xsl:text><xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='System Information']/Field[@Name='Product Name']"/>
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
|
||||||
|
<xsl:text> BIOS version: </xsl:text>
|
||||||
|
- <xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/BIOS|HardwareInfo/BIOS"/>
|
||||||
|
+ <xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='BIOS Information']/Field[@Name='Vendor']"/>
|
||||||
|
<xsl:text> (ver: </xsl:text>
|
||||||
|
- <xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/BIOS/@Version|HardwareInfo/BIOS/@Version"/>
|
||||||
|
- <xsl:text>, rev :</xsl:text>
|
||||||
|
- <xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/BIOS/@BIOSrevision|HardwareInfo/BIOS/@BIOSrevision"/>
|
||||||
|
+ <xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='BIOS Information']/Field[@Name='Version']"/>
|
||||||
|
+ <xsl:text>, rev: </xsl:text>
|
||||||
|
+ <xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='BIOS Information']/Field[@Name='BIOS Revision']"/>
|
||||||
|
<xsl:text>, release date: </xsl:text>
|
||||||
|
- <xsl:value-of select="SystemInfo/DMIinfo/HardwareInfo/BIOS/@ReleaseDate|HardwareInfo/BIOS/@ReleaseDate"/>
|
||||||
|
+ <xsl:value-of select="SystemInfo/DMIinfo/Handle[@name='BIOS Information']/Field[@Name='Release Date']"/>
|
||||||
|
<xsl:text>)</xsl:text>
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
45
rteval-Use-get-instead-of-setdefault-for-calculating.patch
Normal file
45
rteval-Use-get-instead-of-setdefault-for-calculating.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
From a5f3289e2ee6577cbbb78661bea58b821942ba56 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Thu, 2 May 2024 13:09:01 -0400
|
||||||
|
Subject: [PATCH 12/13] rteval: Use get instead of setdefault for calculating
|
||||||
|
range
|
||||||
|
|
||||||
|
As Crystal Wood <crwood@redhat.com> points out, there is no
|
||||||
|
need to setdefault when calculating the range, just use get
|
||||||
|
if there is no value.
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 2 +-
|
||||||
|
rteval/modules/measurement/timerlat.py | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index 925065367eaf..3301e1b45e11 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -115,7 +115,7 @@ class RunData:
|
||||||
|
low = i
|
||||||
|
break
|
||||||
|
high = keys[-1]
|
||||||
|
- while high and self.__samples.setdefault(high, 0) == 0:
|
||||||
|
+ while high and self.__samples.get(high, 0) == 0:
|
||||||
|
high -= 1
|
||||||
|
self.__range = high - low
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/timerlat.py b/rteval/modules/measurement/timerlat.py
|
||||||
|
index 9fa931043e40..e8345fab1ad7 100644
|
||||||
|
--- a/rteval/modules/measurement/timerlat.py
|
||||||
|
+++ b/rteval/modules/measurement/timerlat.py
|
||||||
|
@@ -106,7 +106,7 @@ class TLRunData:
|
||||||
|
low = i
|
||||||
|
break
|
||||||
|
high = keys[-1]
|
||||||
|
- while high and self.__samples.setdefault(high, 0) == 0:
|
||||||
|
+ while high and self.__samples.get(high, 0) == 0:
|
||||||
|
high -= 1
|
||||||
|
self.__range = high - low
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
45
rteval-cyclictest.py-Fix-the-description-in-the-xml-.patch
Normal file
45
rteval-cyclictest.py-Fix-the-description-in-the-xml-.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
From 0a431278cc681270b54efea4eebce9571c237624 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 12:39:33 -0400
|
||||||
|
Subject: [PATCH 03/13] rteval: cyclictest.py: Fix the description in the xml
|
||||||
|
report
|
||||||
|
|
||||||
|
If the __type is 'system' we should add the description to the xml
|
||||||
|
The output should be something like this
|
||||||
|
|
||||||
|
<system description="(12 cores) Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz">
|
||||||
|
|
||||||
|
Before this fix it was
|
||||||
|
|
||||||
|
<system description="">
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index 671426e13c4d..48b86a03cbfc 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -25,7 +25,7 @@ class RunData:
|
||||||
|
self.__id = coreid
|
||||||
|
self.__type = datatype
|
||||||
|
self.__priority = int(priority)
|
||||||
|
- self.__description = ''
|
||||||
|
+ self.description = ''
|
||||||
|
# histogram of data
|
||||||
|
self.__samples = {}
|
||||||
|
self.__numsamples = 0
|
||||||
|
@@ -130,7 +130,7 @@ class RunData:
|
||||||
|
def MakeReport(self):
|
||||||
|
rep_n = libxml2.newNode(self.__type)
|
||||||
|
if self.__type == 'system':
|
||||||
|
- rep_n.newProp('description', self.__description)
|
||||||
|
+ rep_n.newProp('description', self.description)
|
||||||
|
else:
|
||||||
|
rep_n.newProp('id', str(self.__id))
|
||||||
|
rep_n.newProp('priority', str(self.__priority))
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
60
rteval-cyclictest.py-Fix-the-median-calculation.patch
Normal file
60
rteval-cyclictest.py-Fix-the-median-calculation.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
From 071bd1be404f1b5c71f8b2f2d9fa1a85bd485ce9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Thu, 25 Apr 2024 13:48:05 -0400
|
||||||
|
Subject: [PATCH 05/13] rteval: cyclictest.py: Fix the median calculation
|
||||||
|
|
||||||
|
Fix the calculation of the median in rteval for cyclictest
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 20 ++++++++++++++------
|
||||||
|
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index 1ba8b8b2323c..cef73abd1b4b 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -80,26 +80,34 @@ class RunData:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._log(Log.INFO, f"reducing {self.__id}")
|
||||||
|
- total = 0
|
||||||
|
+ total = 0 # total number of samples
|
||||||
|
+ total_us = 0
|
||||||
|
keys = list(self.__samples.keys())
|
||||||
|
keys.sort()
|
||||||
|
|
||||||
|
- mid = self.__numsamples / 2
|
||||||
|
+ # if numsamples is odd, then + 1 gives us the actual mid
|
||||||
|
+ # if numsamples is even, we avg mid and mid + 1, so we actually
|
||||||
|
+ # want to know mid + 1 since we will combine it with mid and
|
||||||
|
+ # the lastkey if the last key is at the end of a previous bucket
|
||||||
|
+ mid = int(self.__numsamples / 2) + 1
|
||||||
|
|
||||||
|
# mean, mode, and median
|
||||||
|
occurances = 0
|
||||||
|
lastkey = -1
|
||||||
|
for i in keys:
|
||||||
|
- if mid > total and mid <= (total + self.__samples[i]):
|
||||||
|
- if self.__numsamples & 1 and mid == total+1:
|
||||||
|
+ if mid > total and mid <= total + self.__samples[i]:
|
||||||
|
+ # Test if numsamples is even and if mid+1 is the next bucket
|
||||||
|
+ if self.__numsamples & 1 != 0 and mid == total+1:
|
||||||
|
self.__median = (lastkey + i) / 2
|
||||||
|
else:
|
||||||
|
self.__median = i
|
||||||
|
- total += (i * self.__samples[i])
|
||||||
|
+ lastkey = i
|
||||||
|
+ total += self.__samples[i]
|
||||||
|
+ total_us += (i * self.__samples[i])
|
||||||
|
if self.__samples[i] > occurances:
|
||||||
|
occurances = self.__samples[i]
|
||||||
|
self.__mode = i
|
||||||
|
- self.__mean = float(total) / float(self.__numsamples)
|
||||||
|
+ self.__mean = float(total_us) / float(self.__numsamples)
|
||||||
|
|
||||||
|
# range
|
||||||
|
for i in keys:
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
32
rteval-cyclictest.py-Remove-unused-method-sample.patch
Normal file
32
rteval-cyclictest.py-Remove-unused-method-sample.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From 6a185e50bb9b0903e034a2361456b5742e60c47b Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Fri, 19 Apr 2024 12:17:31 -0400
|
||||||
|
Subject: [PATCH 04/13] rteval: cyclictest.py: Remove unused method sample
|
||||||
|
|
||||||
|
Remove the unused method sample() in class RunData
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 6 ------
|
||||||
|
1 file changed, 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index 48b86a03cbfc..1ba8b8b2323c 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -61,12 +61,6 @@ class RunData:
|
||||||
|
if value < self.__min:
|
||||||
|
self.__min = value
|
||||||
|
|
||||||
|
- def sample(self, value):
|
||||||
|
- self.__samples[value] += self.__samples.setdefault(value, 0) + 1
|
||||||
|
- self.update_max(value)
|
||||||
|
- self.update_min(value)
|
||||||
|
- self.__numsamples += 1
|
||||||
|
-
|
||||||
|
def bucket(self, index, value):
|
||||||
|
self.__samples[index] = self.__samples.setdefault(index, 0) + value
|
||||||
|
if value:
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
35
rteval-cyclictest.py-reduce-Fix-exception-with-missi.patch
Normal file
35
rteval-cyclictest.py-reduce-Fix-exception-with-missi.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
From eb344bffd1525bbb8cd95fb4f4501e467cdc21ce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Crystal Wood <crwood@redhat.com>
|
||||||
|
Date: Wed, 1 May 2024 15:09:22 -0500
|
||||||
|
Subject: [PATCH 11/13] rteval: cyclictest.py: reduce: Fix exception with
|
||||||
|
missing samples
|
||||||
|
|
||||||
|
If cyclictest omits a line of zeroes rather than printing it,
|
||||||
|
__samples[high] will not exist (rather than be zero). Handle this
|
||||||
|
in preparation for cyclictest doing this.
|
||||||
|
|
||||||
|
Note that get() seems more suitable than setdefault(), but the latter
|
||||||
|
is used in order to match the code in timerlat.py.
|
||||||
|
|
||||||
|
Signed-off-by: Crystal Wood <crwood@redhat.com>
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/cyclictest.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
|
||||||
|
index cef73abd1b4b..925065367eaf 100644
|
||||||
|
--- a/rteval/modules/measurement/cyclictest.py
|
||||||
|
+++ b/rteval/modules/measurement/cyclictest.py
|
||||||
|
@@ -115,7 +115,7 @@ class RunData:
|
||||||
|
low = i
|
||||||
|
break
|
||||||
|
high = keys[-1]
|
||||||
|
- while high and self.__samples[high] == 0:
|
||||||
|
+ while high and self.__samples.setdefault(high, 0) == 0:
|
||||||
|
high -= 1
|
||||||
|
self.__range = high - low
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
358
rteval-timerlat.py-Add-statistics-and-generate-xml.patch
Normal file
358
rteval-timerlat.py-Add-statistics-and-generate-xml.patch
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
From 53248cbad7b0b353e31a18b40181f38da0a721aa Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Kacur <jkacur@redhat.com>
|
||||||
|
Date: Thu, 25 Apr 2024 13:59:27 -0400
|
||||||
|
Subject: [PATCH 06/13] rteval: timerlat.py Add statistics and generate xml
|
||||||
|
|
||||||
|
This adds calculating statitics such as samples (count), min, max, mean,
|
||||||
|
median, mode, range, absolute and standard deviations to xml
|
||||||
|
|
||||||
|
Currently it combines the kernel thread, IRQs and userspace threads into
|
||||||
|
one statistic like it does with cyclictest, but in the future we can
|
||||||
|
separate this out too.
|
||||||
|
|
||||||
|
To see this functioning from git, do this,
|
||||||
|
|
||||||
|
su -c 'python rteval/modules/measurement/timerlat.py '
|
||||||
|
|
||||||
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
||||||
|
---
|
||||||
|
rteval/modules/measurement/timerlat.py | 266 ++++++++++++++++++++++++-
|
||||||
|
1 file changed, 259 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/rteval/modules/measurement/timerlat.py b/rteval/modules/measurement/timerlat.py
|
||||||
|
index d4e78de8d2a2..9fa931043e40 100644
|
||||||
|
--- a/rteval/modules/measurement/timerlat.py
|
||||||
|
+++ b/rteval/modules/measurement/timerlat.py
|
||||||
|
@@ -8,12 +8,170 @@ import subprocess
|
||||||
|
import signal
|
||||||
|
import time
|
||||||
|
import tempfile
|
||||||
|
+import math
|
||||||
|
+import sys
|
||||||
|
import libxml2
|
||||||
|
from rteval.Log import Log
|
||||||
|
from rteval.modules import rtevalModulePrototype
|
||||||
|
from rteval.systopology import cpuinfo, SysTopology
|
||||||
|
from rteval.cpulist_utils import expand_cpulist, collapse_cpulist
|
||||||
|
|
||||||
|
+class TLRunData:
|
||||||
|
+ ''' class to store instance data from a timerlat run '''
|
||||||
|
+ def __init__(self, coreid, datatype, priority, logfnc):
|
||||||
|
+ self.__id = coreid
|
||||||
|
+ self.__type = datatype
|
||||||
|
+ self.__priority = int(priority)
|
||||||
|
+ self.description = ''
|
||||||
|
+ self._log = logfnc
|
||||||
|
+ self.duration = ''
|
||||||
|
+ # histogram data, irqs, kernel threads and user threads per core
|
||||||
|
+ self.irqs = {}
|
||||||
|
+ self.thrs = {}
|
||||||
|
+ self.usrs = {}
|
||||||
|
+ self.__samples = {}
|
||||||
|
+ self.__numsamples = 0
|
||||||
|
+ self.min = 100000000
|
||||||
|
+ self.max = 0
|
||||||
|
+ self.__stddev = 0.0
|
||||||
|
+ self.__mean = 0.0
|
||||||
|
+ self.__mode = 0.0
|
||||||
|
+ self.__median = 0.0
|
||||||
|
+ self.__range = 0.0
|
||||||
|
+
|
||||||
|
+ def update_max(self, value):
|
||||||
|
+ """ highest bucket with a value """
|
||||||
|
+ if value > self.max:
|
||||||
|
+ self.max = value
|
||||||
|
+
|
||||||
|
+ def update_min(self, value):
|
||||||
|
+ """ lowest bucket with a value """
|
||||||
|
+ if value < self.min:
|
||||||
|
+ self.min = value
|
||||||
|
+
|
||||||
|
+ def bucket(self, index, val1, val2, val3):
|
||||||
|
+ """ Store results index=bucket number, val1=IRQ, val2=thr, val3=usr """
|
||||||
|
+ values = val1 + val2 + val3
|
||||||
|
+ self.__samples[index] = self.__samples.setdefault(index, 0) + values
|
||||||
|
+ self.irqs[index] = val1
|
||||||
|
+ self.thrs[index] = val2
|
||||||
|
+ self.usrs[index] = val3
|
||||||
|
+ if values:
|
||||||
|
+ self.update_max(index)
|
||||||
|
+ self.update_min(index)
|
||||||
|
+ self.__numsamples += values
|
||||||
|
+
|
||||||
|
+ def reduce(self):
|
||||||
|
+ """ Calculate statistics """
|
||||||
|
+ # Check to see if we have any samples. If there are 1 or 0, return
|
||||||
|
+ if self.__numsamples <= 1:
|
||||||
|
+ self._log(Log.DEBUG, f"skipping {self.__id} ({self.__numsamples} sampples)")
|
||||||
|
+ self.__mad = 0
|
||||||
|
+ self.__stddev = 0
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
+ self._log(Log.INFO, f"reducing {self.__id}")
|
||||||
|
+ total = 0 # total number of samples
|
||||||
|
+ total_us = 0
|
||||||
|
+ keys = list(self.__samples.keys())
|
||||||
|
+ keys.sort()
|
||||||
|
+
|
||||||
|
+ # if numsamples is odd, then + 1 gives us the actual mid
|
||||||
|
+ # if numsamples is even, we avg mid and mid + 1, so we actually
|
||||||
|
+ # want to know mid + 1 since we will combine it with mid and
|
||||||
|
+ # the lastkey if the last key is at the end of a previous bucket
|
||||||
|
+ mid = int(self.__numsamples / 2) + 1
|
||||||
|
+
|
||||||
|
+ # mean, mode and median
|
||||||
|
+ occurances = 0
|
||||||
|
+ lastkey = -1
|
||||||
|
+ for i in keys:
|
||||||
|
+ if mid > total and mid <= total + self.__samples[i]:
|
||||||
|
+ # Test if numsamples is even and if mid+1 is the next bucket
|
||||||
|
+ if self.__numsamples & 1 != 0 and mid == total+1:
|
||||||
|
+ self.__median = (lastkey + i) / 2
|
||||||
|
+ else:
|
||||||
|
+ self.__median = i
|
||||||
|
+ lastkey = i
|
||||||
|
+ total += self.__samples[i]
|
||||||
|
+ total_us += i * self.__samples[i]
|
||||||
|
+ if self.__samples[i] > occurances:
|
||||||
|
+ occurances = self.__samples[i]
|
||||||
|
+ self.__mode = i
|
||||||
|
+ self.__mean = float(total_us) / float(self.__numsamples)
|
||||||
|
+
|
||||||
|
+ # range
|
||||||
|
+ for i in keys:
|
||||||
|
+ if self.__samples[i]:
|
||||||
|
+ low = i
|
||||||
|
+ break
|
||||||
|
+ high = keys[-1]
|
||||||
|
+ while high and self.__samples.setdefault(high, 0) == 0:
|
||||||
|
+ high -= 1
|
||||||
|
+ self.__range = high - low
|
||||||
|
+
|
||||||
|
+ # Mean Absolute Deviation and Standard Deviation
|
||||||
|
+ madsum = 0
|
||||||
|
+ varsum = 0
|
||||||
|
+ for i in keys:
|
||||||
|
+ madsum += float(abs(float(i) - self.__mean) * self.__samples[i])
|
||||||
|
+ varsum += float(((float(i) - self.__mean) ** 2) * self.__samples[i])
|
||||||
|
+ self.__mad = madsum / self.__numsamples
|
||||||
|
+ self.__stddev = math.sqrt(varsum / (self.__numsamples - 1))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def MakeReport(self):
|
||||||
|
+ rep_n = libxml2.newNode(self.__type)
|
||||||
|
+
|
||||||
|
+ if self.__type == 'system':
|
||||||
|
+ rep_n.newProp('description', self.description)
|
||||||
|
+ else:
|
||||||
|
+ rep_n.newProp('id', str(self.__id))
|
||||||
|
+ rep_n.newProp('priority', str(self.__priority))
|
||||||
|
+
|
||||||
|
+ stat_n = rep_n.newChild(None, 'statistics', None)
|
||||||
|
+ stat_n.newTextChild(None, 'samples', str(self.__numsamples))
|
||||||
|
+
|
||||||
|
+ if self.__numsamples > 0:
|
||||||
|
+ n = stat_n.newTextChild(None, 'minimum', str(self.min))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'maximum', str(self.max))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'median', str(self.__median))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'mode', str(self.__mode))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'range', str(self.__range))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'mean', str(self.__mean))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'mean_absolute_deviation', str(self.__mad))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ n = stat_n.newTextChild(None, 'standard_deviation', str(self.__stddev))
|
||||||
|
+ n.newProp('unit', 'us')
|
||||||
|
+
|
||||||
|
+ hist_n = rep_n.newChild(None, 'histogram', None)
|
||||||
|
+ hist_n.newProp('nbuckets', str(len(self.__samples)))
|
||||||
|
+
|
||||||
|
+ keys = list(self.__samples.keys())
|
||||||
|
+ keys.sort()
|
||||||
|
+ for k in keys:
|
||||||
|
+ if self.__samples[k] == 0:
|
||||||
|
+ # Don't report buckets without any samples
|
||||||
|
+ continue
|
||||||
|
+ b_n = hist_n.newChild(None, 'bucket', None)
|
||||||
|
+ b_n.newProp('index', str(k))
|
||||||
|
+ b_n.newProp('value', str(self.__samples[k]))
|
||||||
|
+
|
||||||
|
+ return rep_n
|
||||||
|
+
|
||||||
|
class Timerlat(rtevalModulePrototype):
|
||||||
|
""" measurement modules for rteval """
|
||||||
|
def __init__(self, config, logger=None):
|
||||||
|
@@ -23,6 +181,8 @@ class Timerlat(rtevalModulePrototype):
|
||||||
|
|
||||||
|
self.__numanodes = int(self.__cfg.setdefault('numanodes', 0))
|
||||||
|
self.__priority = int(self.__cfg.setdefault('priority', 95))
|
||||||
|
+ default_buckets = ModuleParameters()["buckets"]["default"]
|
||||||
|
+ self.__buckets = int(self.__cfg.setdefault('buckets', default_buckets))
|
||||||
|
|
||||||
|
self.__cpulist = self.__cfg.setdefault('cpulist', "")
|
||||||
|
self.__cpus = [str(c) for c in expand_cpulist(self.__cpulist)]
|
||||||
|
@@ -31,6 +191,20 @@ class Timerlat(rtevalModulePrototype):
|
||||||
|
self.__timerlat_out = None
|
||||||
|
self.__timerlat_err = None
|
||||||
|
self.__started = False
|
||||||
|
+
|
||||||
|
+ # Create a TLRunData object for each core we'll measure
|
||||||
|
+ info = cpuinfo()
|
||||||
|
+ self.__timerlatdata = {}
|
||||||
|
+ for core in self.__cpus:
|
||||||
|
+ self.__timerlatdata[core] = TLRunData(core, 'core', self.__priority,
|
||||||
|
+ logfnc=self._log)
|
||||||
|
+ self.__timerlatdata[core].description = info[core]['model name']
|
||||||
|
+
|
||||||
|
+ # Create a TLRunData object for the overall system
|
||||||
|
+ self.__timerlatdata['system'] = TLRunData('system', 'system',
|
||||||
|
+ self.__priority,
|
||||||
|
+ logfnc=self._log)
|
||||||
|
+ self.__timerlatdata['system'].description = (f"({self.__numcores} cores) ") + info['0']['model name']
|
||||||
|
self._log(Log.DEBUG, f"system using {self.__numcores} cpu cores")
|
||||||
|
|
||||||
|
|
||||||
|
@@ -43,6 +217,7 @@ class Timerlat(rtevalModulePrototype):
|
||||||
|
def _WorkloadPrepare(self):
|
||||||
|
self.__cmd = ['rtla', 'timerlat', 'hist', '-P', f'f:{int(self.__priority)}', '-u']
|
||||||
|
self.__cmd.append(f'-c{self.__cpulist}')
|
||||||
|
+ self.__cmd.append(f'-E{self.__buckets}')
|
||||||
|
self._log(Log.DEBUG, f'self.__cmd = {self.__cmd}')
|
||||||
|
self.__timerlat_out = tempfile.SpooledTemporaryFile(mode='w+b')
|
||||||
|
self.__timerlat_err = tempfile.SpooledTemporaryFile(mode='w+b')
|
||||||
|
@@ -77,16 +252,82 @@ class Timerlat(rtevalModulePrototype):
|
||||||
|
os.kill(self.__timerlat_process.pid, signal.SIGINT)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
- self._setFinished()
|
||||||
|
- self.__started = False
|
||||||
|
-
|
||||||
|
- def MakeReport(self):
|
||||||
|
+ # Parse histogram output
|
||||||
|
self.__timerlat_out.seek(0)
|
||||||
|
for line in self.__timerlat_out:
|
||||||
|
line = bytes.decode(line)
|
||||||
|
- print(line)
|
||||||
|
+
|
||||||
|
+ # Skip any blank lines
|
||||||
|
+ if not line:
|
||||||
|
+ continue
|
||||||
|
+
|
||||||
|
+ if line.startswith('#'):
|
||||||
|
+ if line.startswith('# Duration:'):
|
||||||
|
+ duration = line.split()[2]
|
||||||
|
+ duration += line.split()[3]
|
||||||
|
+ self.__timerlatdata['system'].duration = duration
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('Index'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('over:'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('count:'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('min:'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('avg:'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ elif line.startswith('max:'):
|
||||||
|
+ #print(line)
|
||||||
|
+ continue
|
||||||
|
+ else:
|
||||||
|
+ pass
|
||||||
|
+ #print(line)
|
||||||
|
+
|
||||||
|
+ vals = line.split()
|
||||||
|
+ if not vals:
|
||||||
|
+ # If we don't have any values, don't try parsing
|
||||||
|
+ continue
|
||||||
|
+ try:
|
||||||
|
+ # The index corresponds to the bucket number
|
||||||
|
+ index = int(vals[0])
|
||||||
|
+ except:
|
||||||
|
+ self._log(Log.DEBUG, f'timerlat: unexpected output: {line}')
|
||||||
|
+ continue
|
||||||
|
+
|
||||||
|
+ for i, core in enumerate(self.__cpus):
|
||||||
|
+ self.__timerlatdata[core].bucket(index, int(vals[i*3+1]),
|
||||||
|
+ int(vals[i*3+2]),
|
||||||
|
+ int(vals[i*3+3]))
|
||||||
|
+ self.__timerlatdata['system'].bucket(index, int(vals[i*3+1]),
|
||||||
|
+ int(vals[i*3+2]),
|
||||||
|
+ int(vals[i*3+3]))
|
||||||
|
+ # Generate statistics for each RunData object
|
||||||
|
+ for n in list(self.__timerlatdata.keys()):
|
||||||
|
+ self.__timerlatdata[n].reduce()
|
||||||
|
+
|
||||||
|
self.__timerlat_out.close()
|
||||||
|
|
||||||
|
+ self._setFinished()
|
||||||
|
+ self.__started = False
|
||||||
|
+
|
||||||
|
+ def MakeReport(self):
|
||||||
|
+ rep_n = libxml2.newNode('timerlat')
|
||||||
|
+ rep_n.newProp('command_line', ' '.join(self.__cmd))
|
||||||
|
+
|
||||||
|
+ rep_n.addChild(self.__timerlatdata['system'].MakeReport())
|
||||||
|
+ for thr in self.__cpus:
|
||||||
|
+ if str(thr) not in self.__timerlatdata:
|
||||||
|
+ continue
|
||||||
|
+ rep_n.addChild(self.__timerlatdata[str(thr)].MakeReport())
|
||||||
|
+
|
||||||
|
+ return rep_n
|
||||||
|
+
|
||||||
|
|
||||||
|
def ModuleInfo():
|
||||||
|
""" Required measurement module information """
|
||||||
|
@@ -97,7 +338,10 @@ def ModuleParameters():
|
||||||
|
""" default parameters """
|
||||||
|
return {"priority": {"descr": "Run rtla timerlat with this priority",
|
||||||
|
"default": 95,
|
||||||
|
- "metavar": "PRIO" }
|
||||||
|
+ "metavar": "PRIO" },
|
||||||
|
+ "buckets": {"descr": "Number of buckets",
|
||||||
|
+ "default": 3500,
|
||||||
|
+ "metavar": "NUM"}
|
||||||
|
}
|
||||||
|
|
||||||
|
def create(params, logger):
|
||||||
|
@@ -107,6 +351,10 @@ def create(params, logger):
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from rteval.rtevalConfig import rtevalConfig
|
||||||
|
|
||||||
|
+ if os.getuid() != 0:
|
||||||
|
+ print("Must be root to run timerlat!")
|
||||||
|
+ sys.exit(1)
|
||||||
|
+
|
||||||
|
l = Log()
|
||||||
|
l.SetLogVerbosity(Log.INFO|Log.DEBUG|Log.ERR|Log.WARN)
|
||||||
|
|
||||||
|
@@ -128,4 +376,8 @@ if __name__ == '__main__':
|
||||||
|
tl._WorkloadTask()
|
||||||
|
time.sleep(RUNTIME)
|
||||||
|
tl._WorkloadCleanup()
|
||||||
|
- tl.MakeReport()
|
||||||
|
+ rep_n = tl.MakeReport()
|
||||||
|
+
|
||||||
|
+ xml = libxml2.newDoc('1.0')
|
||||||
|
+ xml.setRootElement(rep_n)
|
||||||
|
+ xml.saveFormatFileEnc('-', 'UTF-8', 1)
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
33
rteval.spec
33
rteval.spec
@ -1,6 +1,6 @@
|
|||||||
Name: rteval
|
Name: rteval
|
||||||
Version: 3.7
|
Version: 3.7
|
||||||
Release: 5%{?dist}
|
Release: 6%{?dist}
|
||||||
Summary: Utility to evaluate system suitability for RT Linux
|
Summary: Utility to evaluate system suitability for RT Linux
|
||||||
|
|
||||||
Group: Development/Tools
|
Group: Development/Tools
|
||||||
@ -41,7 +41,18 @@ Patch6: rteval-Minor-improvements-to-CpuList-class.patch
|
|||||||
Patch7: rteval-Convert-CpuList-class-to-a-module.patch
|
Patch7: rteval-Convert-CpuList-class-to-a-module.patch
|
||||||
Patch8: rteval-Add-relative-cpulists-for-measurements.patch
|
Patch8: rteval-Add-relative-cpulists-for-measurements.patch
|
||||||
Patch9: rteval-Implement-initial-dmidecode-support.patch
|
Patch9: rteval-Implement-initial-dmidecode-support.patch
|
||||||
|
Patch10: rteval-Add-relative-cpulists-for-loads.patch
|
||||||
|
Patch11: rteval-Cyclictest.py-Make-standalone-file-work-again.patch
|
||||||
|
Patch12: rteval-Add-rtla-timerlat-as-a-measurement-module.patch
|
||||||
|
Patch13: rteval-cyclictest.py-Fix-the-description-in-the-xml-.patch
|
||||||
|
Patch14: rteval-cyclictest.py-Remove-unused-method-sample.patch
|
||||||
|
Patch15: rteval-cyclictest.py-Fix-the-median-calculation.patch
|
||||||
|
Patch16: rteval-timerlat.py-Add-statistics-and-generate-xml.patch
|
||||||
|
Patch17: rteval-Add-summary-reporting-for-timerlat.patch
|
||||||
|
Patch18: rteval-Generate-raw-histogram-data-for-an-existing-t.patch
|
||||||
|
Patch19: rteval-Make-output-work-with-new-dmiinfo-format.patch
|
||||||
|
Patch20: rteval-cyclictest.py-reduce-Fix-exception-with-missi.patch
|
||||||
|
Patch21: rteval-Use-get-instead-of-setdefault-for-calculating.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
The rteval script is a utility for measuring various aspects of
|
The rteval script is a utility for measuring various aspects of
|
||||||
@ -63,6 +74,18 @@ to the screen.
|
|||||||
%patch 7 -p1
|
%patch 7 -p1
|
||||||
%patch 8 -p1
|
%patch 8 -p1
|
||||||
%patch 9 -p1
|
%patch 9 -p1
|
||||||
|
%patch 10 -p1
|
||||||
|
%patch 11 -p1
|
||||||
|
%patch 12 -p1
|
||||||
|
%patch 13 -p1
|
||||||
|
%patch 14 -p1
|
||||||
|
%patch 15 -p1
|
||||||
|
%patch 16 -p1
|
||||||
|
%patch 17 -p1
|
||||||
|
%patch 18 -p1
|
||||||
|
%patch 19 -p1
|
||||||
|
%patch 20 -p1
|
||||||
|
%patch 21 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%{__python3} setup.py build
|
%{__python3} setup.py build
|
||||||
@ -83,7 +106,11 @@ to the screen.
|
|||||||
%{_bindir}/rteval
|
%{_bindir}/rteval
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Apr 05 2024 Tomas Glozar <tglozar@redhat.com> - 3.7-5
|
* Mon May 06 2024 John Kacur <jkacur@redhat.com> - 3.7-6
|
||||||
|
- Add timerlat as a measurement module
|
||||||
|
Resolves: RHEL-28058
|
||||||
|
|
||||||
|
* Thu Apr 04 2024 Tomas Glozar <tglozar@redhat.com> - 3.7-5
|
||||||
- Replace python-dmidecode with initial dmidecode output parsing
|
- Replace python-dmidecode with initial dmidecode output parsing
|
||||||
Resolves: RHEL-30158
|
Resolves: RHEL-30158
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user