2015-11-10 15:51 GMT+01:00 Jan Tluka <jtluka@redhat.com>:
Mon, Nov 09, 2015 at 11:07:44AM CET, jprochaz@redhat.com wrote:
>This patch adds support for measuring both local and remote CPU utilization:
>  New option for netperf client have been added:
>    cpu_util - when set to "local", netperf is run with -c argument, enabling measure of local CPU utilization during run,
>               when set to "remote", netperf is run with -C argument, enabling measure of remote CPU utilization during run,
>               when set to "both", netperf is run with both -c and -C arguments
>
>  Parsing of throughput and confidence interval has been made cleaner:
>    Using omni netperf output, all relevant data are now stored in key=val format,
>    which can be parsed more easily and is the same for all netperf test types.
>
>Changes in v2:
>  Changed format of cpu_util argument (described above)
>
>  Renamed keys in res_val dict to from loc_cpu_util and rem_cpu util
>  to LOCAL_CPU_UTIL and REMOTE_CPU_UTIL
>
>  Fixed incorrect real confidence value, now the touple correctly
>  returns (CONFIDENCE_LEVEL, THROUGHPUT_CONFIDENCE_INTERVAL/2)
>
>Signed-off-by: Jiri Prochazka <jprochaz@redhat.com>
>---
> test_modules/Netperf.py | 87 +++++++++++++++++++++++++------------------------
> 1 file changed, 44 insertions(+), 43 deletions(-)
>
>diff --git a/test_modules/Netperf.py b/test_modules/Netperf.py
>index 868cca0..9a20ad2 100644
>--- a/test_modules/Netperf.py
>+++ b/test_modules/Netperf.py
>@@ -34,6 +34,7 @@ class Netperf(TestGeneric):
>         self._confidence = self.get_opt("confidence")
>         self._bind = self.get_opt("bind", opt_type="addr")
>         self._family = self.get_opt("family")
>+        self._cpu_util = self.get_opt("cpu_util")
>
>         self._runs = self.get_opt("runs", default=1)
>         if self._runs > 1 and self._confidence is not None:
>@@ -61,7 +62,8 @@ class Netperf(TestGeneric):
>         composes commands for netperf and netserver based on xml recipe
>         """
>         if self._role == "client":
>-            cmd = "netperf -H %s -f k" % self._netperf_server
>+            # -P 0 disables banner header of output
>+            cmd = "netperf -H %s -f k -P 0" % self._netperf_server
>             if self._port is not None:
>                 """
>                 client connects on this port
>@@ -89,11 +91,22 @@ class Netperf(TestGeneric):
>                 """
>                 cmd += " -I %s" % self._confidence
>
>+            if self._cpu_util is not None:
>+                if self._cpu_util.lower() == "both":
>+                    cmd += " -c -C"
>+                elif self._cpu_util.lower() == "local":
>+                    cmd += " -c"
>+                elif self._cpu_util.lower() == "remote":
>+                    cmd += " -C"
>+
>             if self._netperf_opts is not None:
>                 """
>                 custom options for netperf
>                 """
>                 cmd += " %s" % self._netperf_opts
>+            # Print only relevant output
>+            cmd += ' -- -k "THROUGHPUT, LOCAL_CPU_UTIL, REMOTE_CPU_UTIL, CONFIDENCE_LEVEL, THROUGHPUT_CONFID"'
>+
>         elif self._role == "server":
>             cmd = "netserver -D"
>             if self._bind is not None:
>@@ -114,58 +127,47 @@ class Netperf(TestGeneric):
>         return cmd
>
>     def _parse_output(self, output):
>-        if self._testname == "UDP_STREAM":
>-            # pattern for UDP_STREAM throughput output
>-            # decimal float decimal (float)
>-            pattern_udp_stream = "\d+\s+\d+\.\d+\s+\d+\s+(\d+(\.\d+){0,1})\n"
>-            r2 = re.search(pattern_udp_stream, output.lower())
>-        elif self._testname == "TCP_STREAM":
>-            # pattern for TCP_STREAM throughput output
>-            # decimal decimal decimal float (float)
>-            pattern_tcp_stream = "\d+\s+\d+\s+\d+\s+\d+\.\d+\s+(\d+(\.\d+){0,1})"
>-            r2 = re.search(pattern_tcp_stream, output.lower())
>-        elif self._testname == "TCP_RR" or self._testname == "UDP_RR"\
>-             or self._testname == "SCTP_RR":
>-            # pattern for TCP_RR, UDP_RR and SCTP_RR throughput output
>-            # decimal decimal decimal decimal float (float)
>-            pattern_tcp_rr = "\d+\s+\d+\s+\d+\s+\d+\s+\d+\.\d+\s+(\d+(\.\d+){0,1})"
>-            r2 = re.search(pattern_tcp_rr, output.lower())
>-        else:
>-            # pattern for SCTP streams and other tests
>-            # decimal decimal decimal float (float)
>-            pattern_sctp = "\d+\s+\d+\s+\d+\s+\d+\.\d+\s+(\d+(\.\d+){0,1})"
>-            r2 = re.search(pattern_sctp, output.lower())
>+        res_val = {}
>
>-        if r2 is None:
>+        pattern_throughput = "THROUGHPUT=(\d+\.\d+)"
>+        throughput = re.search(pattern_throughput, output)
>+
>+        if throughput is None:
>             rate_in_kb = 0.0
>         else:
>-            rate_in_kb = float(r2.group(1))
>+            rate_in_kb = float(throughput.group(1))
>+
>+        res_val["rate"] = rate_in_kb*1000
>+        res_val["unit"] = "bps"
>+
>+        if self._cpu_util is not None:
>+            if self._cpu_util == "local" or self._cpu_util == "both":
>+                pattern_loc_cpu_util = "LOCAL_CPU_UTIL=([-]?\d+\.\d+)"
>+                loc_cpu_util = re.search(pattern_loc_cpu_util, output)
>+                res_val["LOCAL_CPU_UTIL"] = float(loc_cpu_util.group(1))
>+
>+            if self._cpu_util == "remote" or self._cpu_util == "both":
>+                pattern_rem_cpu_util = "REMOTE_CPU_UTIL=([-]?\d+\.\d+)"
>+                rem_cpu_util = re.search(pattern_rem_cpu_util, output)
>+                res_val["REMOTE_CPU_UTIL"] = float(rem_cpu_util.group(1))
>
>         if self._confidence is not None:
>             confidence = self._parse_confidence(output)
>-            return {"rate": rate_in_kb*1000,
>-                    "unit": "bps",
>-                    "confidence": confidence}
>-        else:
>-            return {"rate": rate_in_kb*1000,
>-                    "unit": "bps"}
>+            res_val["confidence"] = confidence
>+
>+        return res_val
>
>     def _parse_confidence(self, output):
>-        normal_pattern = r'\+/-(\d+\.\d*)% @ (\d+)% conf\.'
>-        warning_pattern = r'!!! Confidence intervals: Throughput\s+: (\d+\.\d*)%'
>-        normal_confidence = re.search(normal_pattern, output)
>-        warning_confidence = re.search(warning_pattern, output)
>+        pattern_throughput_confid = "THROUGHPUT_CONFID=([-]?\d+\.\d+)"
>+        pattern_confidence_level = "CONFIDENCE_LEVEL=(\d+)"
>+        throughput_confid = float(re.search(pattern_throughput_confid, output).group(1))
>+        confidence_level = int(re.search(pattern_confidence_level, output).group(1))
>
>-        if normal_confidence is None:
>-            logging.error("Failed to parse confidence!!")
>+        if throughput_confid == -1.00:
                                   ^
What is this magic number? --------'

Omni output selectors return value -1.00 when the actual value is not obtained. 

>+            logging.error("Failed to parse confidence!")
>             return (0, 0.0)
>
>-        if warning_confidence is None:
>-            real_confidence = (float(normal_confidence.group(2)),
>-                               float(normal_confidence.group(1)))
>-        else:
>-            real_confidence = (float(normal_confidence.group(2)),
>-                               float(warning_confidence.group(1))/2)
>+        real_confidence = (confidence_level, throughput_confid/2)
>
>         return real_confidence
>
>@@ -216,7 +218,6 @@ class Netperf(TestGeneric):
>                                   "throughput option"
>                 return (False, res_data)
>             threshold_rate = float(r1.group(1))
>-            threshold_unit_size = ""
>             threshold_unit_type = "tps"
>
>         return {"rate": threshold_rate,
>--
>2.4.3
>
>_______________________________________________
>LNST-developers mailing list
>LNST-developers@lists.fedorahosted.org
>https://lists.fedorahosted.org/mailman/listinfo/lnst-developers



--
​Best regards,​

Jiri Prochazka 
LNST Developer 
+420 532 294 633 | jprochaz@redhat.com
Red Hat Czech | Purkyňova 71/99, 612 00 Brno