* [PATCH] cpuset: Use stride in cpulist_create
@ 2025-07-08 12:20 Jesse Rosenstock
2025-07-14 11:55 ` Karel Zak
0 siblings, 1 reply; 2+ messages in thread
From: Jesse Rosenstock @ 2025-07-08 12:20 UTC (permalink / raw)
To: util-linux
Format cpu lists for `taskset -c`, `lscpu`, etc. using stride. This
usually produces shorter output.
Now:
% ./taskset -c 0-24:2,25-47:4 ./taskset -pc 0
pid 3937653's current affinity list: 0-24:2,25-45:4
Previously:
% ./taskset -c 0-23:2,24-47:4 ./taskset -pc 0
pid 3933321's current affinity list:
0,2,4,6,8,10,12,14,16,18,20,22,24,28,32,36,40,44
The ranges are constructed greedily; in general it is difficult to
construct a minimal list.
% ./taskset -c 0-63:3,0-63:4 ./taskset -pc 0
pid 3926213's current affinity list:
0,3,4-8:2,9-15:3,16-20:2,21-27:3,28-32:2,33-39:3,40-44:2,45
The patch below uses spaces because gmail hates tabs. Tabs are used in the PR.
https://github.com/util-linux/util-linux/pull/3646
Signed-off-by: Jesse Rosenstock <jmr@google.com>
---
lib/cpuset.c | 75 +++++++++++++++++--------
tests/expected/lscpu/lscpu-x86_64-64cpu | 6 +-
tests/expected/misc/bits-list | 2 +-
tests/expected/misc/bits-parse-mask | 2 +-
tests/expected/schedutils/cpuset | 4 +-
5 files changed, 58 insertions(+), 31 deletions(-)
diff --git a/lib/cpuset.c b/lib/cpuset.c
index 533b8ab309b..d6469203092 100644
--- a/lib/cpuset.c
+++ b/lib/cpuset.c
@@ -147,43 +147,70 @@ int __cpuset_count_s(size_t setsize, const cpu_set_t *set)
}
#endif
+/*
+ * Finds the first CPU present after the specified index.
+ *
+ * start: starting index, inclusive.
+ * setsize: size of the set in *bytes*.
+ * set: CPU set to search.
+ *
+ * Return: the index of the first CPU present in `set`, starting at `start`.
+ * If no such CPU exists, returns the size of the set in *bits*.
+ */
+static size_t find_next_cpu(size_t start, size_t setsize, cpu_set_t *set)
+{
+ size_t nbits = cpuset_nbits(setsize);
+ for (; start < nbits; start++)
+ if (CPU_ISSET_S(start, setsize, set))
+ return start;
+ return start;
+}
+
/*
* Returns human readable representation of the cpuset. The output format is
- * a list of CPUs with ranges (for example, "0,1,3-9").
+ * a list of CPUs with ranges (for example, "0,1,3-9:3").
*/
char *cpulist_create(char *str, size_t len,
cpu_set_t *set, size_t setsize)
{
- size_t i;
char *ptr = str;
int entry_made = 0;
size_t max = cpuset_nbits(setsize);
-
- for (i = 0; i < max; i++) {
- if (CPU_ISSET_S(i, setsize, set)) {
- int rlen;
- size_t j, run = 0;
- entry_made = 1;
- for (j = i + 1; j < max; j++) {
- if (CPU_ISSET_S(j, setsize, set))
- run++;
- else
- break;
+ size_t a = 0; /* min for cpu range */
+ size_t next = 0; /* where to start looking for next cpu */
+
+ while ((a = find_next_cpu(next, setsize, set)) < max) {
+ int rlen;
+ next = find_next_cpu(a + 1, setsize, set);
+ if (next == max) {
+ rlen = snprintf(ptr, len, "%zu,", a);
+ } else {
+ /* Extend range as long as we have the same stride. */
+ size_t b = next;
+ size_t s = b - a;
+ while (((next = find_next_cpu(b + 1, setsize, set)) <
+ max) && next - b == s) {
+ b = next;
}
- if (!run)
- rlen = snprintf(ptr, len, "%zu,", i);
- else if (run == 1) {
- rlen = snprintf(ptr, len, "%zu,%zu,", i, i + 1);
- i++;
+ if (b - a == s) {
+ /*
+ * Only print one CPU. Hope the next one can
+ * be put in the next range.
+ */
+ rlen = snprintf(ptr, len, "%zu,", a);
+ next = b;
+ } else if (s == 1) {
+ rlen = snprintf(ptr, len, "%zu-%zu,", a, b);
} else {
- rlen = snprintf(ptr, len, "%zu-%zu,",
i, i + run);
- i += run;
+ rlen = snprintf(ptr, len, "%zu-%zu:%zu,",
+ a, b, s);
}
- if (rlen < 0 || (size_t) rlen >= len)
- return NULL;
- ptr += rlen;
- len -= rlen;
}
+ if (rlen < 0 || (size_t) rlen >= len)
+ return NULL;
+ ptr += rlen;
+ len -= rlen;
+ entry_made = 1;
}
ptr -= entry_made;
*ptr = '\0';
diff --git a/tests/expected/lscpu/lscpu-x86_64-64cpu
b/tests/expected/lscpu/lscpu-x86_64-64cpu
index b5b6c85c322..d359a6875e6 100644
--- a/tests/expected/lscpu/lscpu-x86_64-64cpu
+++ b/tests/expected/lscpu/lscpu-x86_64-64cpu
@@ -21,9 +21,9 @@ L1i cache: 1 MiB (32 instances)
L2 cache: 8 MiB (32 instances)
L3 cache: 72 MiB (4 instances)
NUMA node(s): 3
-NUMA node0 CPU(s):
0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
-NUMA node2 CPU(s): 1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61
-NUMA node3 CPU(s): 3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63
+NUMA node0 CPU(s): 0-62:2
+NUMA node2 CPU(s): 1-61:4
+NUMA node3 CPU(s): 3-63:4
# The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
diff --git a/tests/expected/misc/bits-list b/tests/expected/misc/bits-list
index 7511e5378ea..e6c6d142a2f 100644
--- a/tests/expected/misc/bits-list
+++ b/tests/expected/misc/bits-list
@@ -1 +1 @@
-11,22,33,44
+11-44:11
diff --git a/tests/expected/misc/bits-parse-mask
b/tests/expected/misc/bits-parse-mask
index 59dd4b4c169..37b1257b85e 100644
--- a/tests/expected/misc/bits-parse-mask
+++ b/tests/expected/misc/bits-parse-mask
@@ -1 +1 @@
-1,3,6,7,9,11,14-16,18,19,21,23-25,27
+1,3,6,7-11:2,14-16,18,19-23:2,24,25,27
diff --git a/tests/expected/schedutils/cpuset b/tests/expected/schedutils/cpuset
index 10e17606c0e..695e75dc9f6 100644
--- a/tests/expected/schedutils/cpuset
+++ b/tests/expected/schedutils/cpuset
@@ -8,7 +8,7 @@ masks:
0x00000007 = 7 [0-2]
0x00000008 = 8 [3]
0x00000009 = 9 [0,3]
-0x00005555 = 5555 [0,2,4,6,8,10,12,14]
+0x00005555 = 5555 [0-14:2]
0x00007777 = 7777 [0-2,4-6,8-10,12-14]
strings:
0 = 1 [0]
@@ -20,5 +20,5 @@ strings:
0-2 = 7 [0-2]
3 = 8 [3]
0,3 = 9 [0,3]
-0,2,4,6,8,10,12,14 = 5555 [0,2,4,6,8,10,12,14]
+0,2,4,6,8,10,12,14 = 5555 [0-14:2]
0-2,4-6,8-10,12-14 = 7777 [0-2,4-6,8-10,12-14]
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] cpuset: Use stride in cpulist_create
2025-07-08 12:20 [PATCH] cpuset: Use stride in cpulist_create Jesse Rosenstock
@ 2025-07-14 11:55 ` Karel Zak
0 siblings, 0 replies; 2+ messages in thread
From: Karel Zak @ 2025-07-14 11:55 UTC (permalink / raw)
To: Jesse Rosenstock; +Cc: util-linux
On Tue, Jul 08, 2025 at 02:20:14PM +0200, Jesse Rosenstock wrote:
> Format cpu lists for `taskset -c`, `lscpu`, etc. using stride. This
> usually produces shorter output.
Thanks! It had been missing for years.
> The patch below uses spaces because gmail hates tabs. Tabs are used in the PR.
>
> https://github.com/util-linux/util-linux/pull/3646
Merged from GitHub.
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-07-14 11:55 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-08 12:20 [PATCH] cpuset: Use stride in cpulist_create Jesse Rosenstock
2025-07-14 11:55 ` Karel Zak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).