🎈 perf: 增加自定义tuned profile
This commit is contained in:
@@ -180,6 +180,7 @@
|
||||
- {role: tsg-os-logo, tags: tsg-os-logo}
|
||||
- {role: cm-cache, tags: cm-cache}
|
||||
- {role: exporter, tags: exporter}
|
||||
- {role: tuned, tags: tuned}
|
||||
|
||||
- hosts: TSG-X-NXR620G40-R01-P0906-init
|
||||
remote_user: root
|
||||
|
||||
173
ansible/roles/tuned/files/371.patch
Normal file
173
ansible/roles/tuned/files/371.patch
Normal file
@@ -0,0 +1,173 @@
|
||||
From 4daf99fc2cb6d873e804d24d56ddd849fc4e514b Mon Sep 17 00:00:00 2001
|
||||
From: Adriaan Schmidt <adriaan.schmidt@siemens.com>
|
||||
Date: Wed, 10 Aug 2022 05:05:03 +0000
|
||||
Subject: [PATCH] feat(scheduler): match thread names in addition to process
|
||||
names
|
||||
|
||||
This is a first try at matching thread names (comm) in addition to
|
||||
the process cmdline for changing scheduling policies and priorities
|
||||
with the `scheduler` plugin.
|
||||
|
||||
It adds an optional second regex field to the end of `group.*`
|
||||
options (defaults to ".*"). The first regex is to match the
|
||||
process cmdline, the second one is used to match the thread's
|
||||
comm. If both match, scheduling options are applied.
|
||||
|
||||
Note that you can have multiple `group.*` options with the
|
||||
same process regex and different thread regexes. You can even have
|
||||
one rule to match a specific thread name, and another with no thread
|
||||
regex (matching all threads). In this case you need to assign rule
|
||||
priorities (higher number -> higher priority).
|
||||
|
||||
Signed-off-by: Adriaan Schmidt <adriaan.schmidt@siemens.com>
|
||||
---
|
||||
profiles/realtime-virtual-guest/tuned.conf | 2 +-
|
||||
profiles/realtime-virtual-host/tuned.conf | 2 +-
|
||||
tuned/plugins/plugin_scheduler.py | 67 ++++++++++++++++------
|
||||
3 files changed, 50 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/profiles/realtime-virtual-guest/tuned.conf b/profiles/realtime-virtual-guest/tuned.conf
|
||||
index a381f413..288f9d03 100644
|
||||
--- a/profiles/realtime-virtual-guest/tuned.conf
|
||||
+++ b/profiles/realtime-virtual-guest/tuned.conf
|
||||
@@ -22,7 +22,7 @@ non_isolated_cores=${f:cpulist_invert:${isolated_cores}}
|
||||
assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
|
||||
|
||||
[scheduler]
|
||||
-# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex
|
||||
+# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex[:thread_name_regex]
|
||||
# for i in `pgrep ksoftirqd` ; do grep Cpus_allowed_list /proc/$i/status ; done
|
||||
group.ksoftirqd=0:f:2:*:^\[ksoftirqd
|
||||
group.ktimers=0:f:2:*:^\[ktimers
|
||||
diff --git a/profiles/realtime-virtual-host/tuned.conf b/profiles/realtime-virtual-host/tuned.conf
|
||||
index b0e8846c..0f520dfe 100644
|
||||
--- a/profiles/realtime-virtual-host/tuned.conf
|
||||
+++ b/profiles/realtime-virtual-host/tuned.conf
|
||||
@@ -27,7 +27,7 @@ non_isolated_cores=${f:cpulist_invert:${isolated_cores}}
|
||||
assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
|
||||
|
||||
[scheduler]
|
||||
-# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex
|
||||
+# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex[:thread_name_regex]
|
||||
# for i in `pgrep ksoftirqd` ; do grep Cpus_allowed_list /proc/$i/status ; done
|
||||
group.ksoftirqd=0:f:2:*:^\[ksoftirqd
|
||||
group.ktimers=0:f:2:*:^\[ktimers
|
||||
diff --git a/tuned/plugins/plugin_scheduler.py b/tuned/plugins/plugin_scheduler.py
|
||||
index 10ff4e7a..74678d99 100644
|
||||
--- a/tuned/plugins/plugin_scheduler.py
|
||||
+++ b/tuned/plugins/plugin_scheduler.py
|
||||
@@ -565,10 +565,11 @@ def _get_cmdline(self, process):
|
||||
if not isinstance(process, procfs.process):
|
||||
pid = process
|
||||
process = procfs.process(pid)
|
||||
- cmdline = procfs.process_cmdline(process)
|
||||
+ cmd = procfs.process_cmdline(process)
|
||||
+ comm = process['stat']['comm']
|
||||
if self._is_kthread(process):
|
||||
- cmdline = "[" + cmdline + "]"
|
||||
- return cmdline
|
||||
+ return "[" + cmd + "]", "[" + comm + "]"
|
||||
+ return cmd, comm
|
||||
|
||||
# Raises OSError, IOError
|
||||
def get_processes(self):
|
||||
@@ -582,7 +583,7 @@ def get_processes(self):
|
||||
processes[pid] = cmd
|
||||
if "threads" in proc:
|
||||
for pid in proc["threads"].keys():
|
||||
- cmd = self._get_cmdline(proc)
|
||||
+ cmd = self._get_cmdline(pid)
|
||||
processes[pid] = cmd
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT \
|
||||
@@ -817,7 +818,16 @@ def _convert_sched_cfg(self, vals):
|
||||
(scheduler, priority) = self._convert_sched_params(
|
||||
scheduler, priority)
|
||||
affinity = self._convert_affinity(affinity)
|
||||
- return (rule_prio, scheduler, priority, affinity, regex)
|
||||
+ # split regex into two, one to match the cmdline, and one the comm
|
||||
+ # if there is only one regex for the cmdline, then the comm is matched by ".*"
|
||||
+ # allow escaping of colons in regexes (-> '\:' is not a delimiter in the split)
|
||||
+ regexes = re.split(r'(?<!\\):', regex, 1)
|
||||
+ r1 = regexes[0].replace(r'\:', ':')
|
||||
+ try:
|
||||
+ r2 = regexes[1].replace(r'\:', ':')
|
||||
+ except IndexError:
|
||||
+ r2 = ".*"
|
||||
+ return (rule_prio, scheduler, priority, affinity, r1, r2)
|
||||
|
||||
def _cgroup_create_group(self, cgroup):
|
||||
path = "%s/%s" % (self._cgroup_mount_point, cgroup)
|
||||
@@ -934,24 +944,34 @@ def _instance_apply_static(self, instance):
|
||||
sched_cfg = sorted(buf, key=lambda option_vals: option_vals[1][0])
|
||||
sched_all = dict()
|
||||
# for runtime tuning
|
||||
+ # _sched_lookup is a dict mapping a cmdline regex to a list of scheduling
|
||||
+ # parameters, each with a secondary regex to match the comm, sorted from lowest
|
||||
+ # to highest priority
|
||||
instance._sched_lookup = {}
|
||||
- for option, (rule_prio, scheduler, priority, affinity, regex) \
|
||||
+ for option, (rule_prio, scheduler, priority, affinity, regex, regex2) \
|
||||
in sched_cfg:
|
||||
try:
|
||||
- r = re.compile(regex)
|
||||
+ r1 = re.compile(regex)
|
||||
except re.error as e:
|
||||
log.error("error compiling regular expression: '%s'" % str(regex))
|
||||
continue
|
||||
- processes = [(pid, cmd) for pid, cmd in ps.items() if re.search(r, cmd) is not None]
|
||||
+ try:
|
||||
+ r2 = re.compile(regex2)
|
||||
+ except re.error as e:
|
||||
+ log.error("error compiling regular expression: '%s'" % str(regex2))
|
||||
+ continue
|
||||
+ processes = [(pid, cmd) for pid, cmd in ps.items() if re.search(r1, cmd[0]) is not None and re.search(r2, cmd[1]) is not None]
|
||||
#cmd - process name, option - group name
|
||||
- sched = dict([(pid, (cmd, option, scheduler, priority, affinity, regex))
|
||||
+ sched = dict([(pid, (cmd, option, scheduler, priority, affinity))
|
||||
for pid, cmd in processes])
|
||||
sched_all.update(sched)
|
||||
# make any contained regexes non-capturing: replace "(" with "(?:",
|
||||
# unless the "(" is preceded by "\" or followed by "?"
|
||||
regex = re.sub(r"(?<!\\)\((?!\?)", "(?:", str(regex))
|
||||
- instance._sched_lookup[regex] = [scheduler, priority, affinity]
|
||||
- for pid, (cmd, option, scheduler, priority, affinity, regex) \
|
||||
+ if not regex in instance._sched_lookup:
|
||||
+ instance._sched_lookup[regex] = []
|
||||
+ instance._sched_lookup[regex].append([scheduler, priority, affinity, r2])
|
||||
+ for pid, (cmd, option, scheduler, priority, affinity) \
|
||||
in sched_all.items():
|
||||
self._tune_process(pid, cmd, scheduler,
|
||||
priority, affinity)
|
||||
@@ -1060,14 +1080,23 @@ def _add_pid(self, instance, pid, r):
|
||||
log.error("Failed to get cmdline of PID %d: %s"
|
||||
% (pid, e))
|
||||
return
|
||||
- v = self._cmd.re_lookup(instance._sched_lookup, cmd, r)
|
||||
- if v is not None and not pid in self._scheduler_original:
|
||||
- log.debug("tuning new process '%s' with PID '%d' by '%s'" % (cmd, pid, str(v)))
|
||||
- (sched, prio, affinity) = v
|
||||
- self._tune_process(pid, cmd, sched, prio,
|
||||
- affinity)
|
||||
- self._storage.set(self._scheduler_storage_key,
|
||||
- self._scheduler_original)
|
||||
+ # first match against cmdline, uses the optimized re_lookup
|
||||
+ vs = self._cmd.re_lookup(instance._sched_lookup, cmd[0], r)
|
||||
+ if vs is not None and not pid in self._scheduler_original:
|
||||
+ tune_v = None
|
||||
+ # second match against comm, reversed to start with the highest priority
|
||||
+ for v in reversed(vs):
|
||||
+ if re.search(v[3], cmd[1]) is not None:
|
||||
+ tune_v = v[:3]
|
||||
+ break
|
||||
+
|
||||
+ if tune_v is not None:
|
||||
+ log.debug("tuning new process '%s' with PID '%d' by '%s'" % (cmd, pid, str(tune_v)))
|
||||
+ (sched, prio, affinity) = tune_v
|
||||
+ self._tune_process(pid, cmd, sched, prio,
|
||||
+ affinity)
|
||||
+ self._storage.set(self._scheduler_storage_key,
|
||||
+ self._scheduler_original)
|
||||
|
||||
def _remove_pid(self, instance, pid):
|
||||
if pid in self._scheduler_original:
|
||||
12
ansible/roles/tuned/files/tuned.conf
Normal file
12
ansible/roles/tuned/files/tuned.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
[main]
|
||||
include=cpu-partitioning
|
||||
summary=Optimize for tsg-os device CPU partitioning
|
||||
|
||||
[scheduler]
|
||||
group.default=0:*:0:${not_isolated_cpumask}:.*:.*
|
||||
group.isolate=1:*:0:*:.*:^(telegraf|sapp_marsio_.*|sce:worker-.*|lcore-worker-.*|.*pmd.*|.*PMD.*|DPDK|.*qemu-kvm.*|contrail-vroute|lcore-slave-.*|rte_mp_handle|rte_mp_async|eal-intr-thread)$
|
||||
isolated_cores=${isolated_cores}
|
||||
ps_blacklist=^telegraf;^sapp_marsio_.*;^sce:worker-.*;^lcore-worker-.*;.*pmd.*;.*PMD.*;^DPDK;.*qemu-kvm.*;^contrail-vroute$;^lcore-slave-.*;^rte_mp_handle$;^rte_mp_async$;^eal-intr-thread$
|
||||
perf_process_fork=True
|
||||
perf_mmap_pages=4096
|
||||
runtime=1
|
||||
35
ansible/roles/tuned/tasks/main.yml
Normal file
35
ansible/roles/tuned/tasks/main.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
- name: "Tuned: copy patch file to dest"
|
||||
copy:
|
||||
src: "{{ role_path }}/files/{{ item }}"
|
||||
dest: /tmp
|
||||
mode: 0755
|
||||
with_items:
|
||||
- 371.patch
|
||||
when: runtime_env == 'TSG-X-P0906'
|
||||
|
||||
|
||||
- name: "Create /etc/tuned/tsg-os-cpu-partitioning directory if it does not exist"
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
with_items:
|
||||
- /etc/tuned/tsg-os-cpu-partitioning
|
||||
|
||||
- name: "Tuned: copy patch file to dest"
|
||||
copy:
|
||||
src: "{{ role_path }}/files/{{ item }}"
|
||||
dest: /etc/tuned/tsg-os-cpu-partitioning/tuned.conf
|
||||
mode: 0755
|
||||
with_items:
|
||||
- tuned.conf
|
||||
when: runtime_env == 'TSG-X-P0906'
|
||||
|
||||
|
||||
- name: "patch plugin_scheduler.py"
|
||||
shell: cd /usr/lib/python3.6/site-packages && patch -p1 -t < /tmp/371.patch || true
|
||||
when: runtime_env == 'TSG-X-P0906'
|
||||
|
||||
- name: "apply tsg-os-cpu-partitioning profile"
|
||||
shell: echo tsg-os-cpu-partitioning >/etc/tuned/active_profile
|
||||
when: runtime_env == 'TSG-X-P0906'
|
||||
Reference in New Issue
Block a user