From nobody Tue Sep 9 16:39:59 2025 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D72B1C5F10; Sat, 6 Sep 2025 16:12:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175148; cv=none; b=Ugz6qql01v2HF52ZgNJ5JmMtZxreRhySJWXMk3XxdJyBd0yiWbLKsboCUeM+frCXxCxfzPbUacp/LInqBphY2ks2gytVm4B9UESBKtfgxrsRUg5tsUB4+GFzbh2PQN/RmnEDcANPI+QlDNup69jbViQ05oK/X1cjmBQMhcWdWD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175148; c=relaxed/simple; bh=LmI7AEFb+MJHqjsE5/o117SBbAvFLlBYg+pRzcMvKJU=; h=Date:Message-ID:In-Reply-To:References:Mime-Version:From:To:Cc: Subject:Content-Type; b=cLrq4uc53Y6PvTdCKBoAon0eS5QCKuyBK9UXaV8njkPJsiKXZ+54m49bb+v2WTMc2AuxACy+DRamN0ik9sjxV0uy3HQMN+FSRNfRSDNdqmXewxJ0c+fnecWwCwGeUADbqUFLzU/ntvo6pJKTkR0aLrO4UEXKe4MlFHG4SETMhco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4cJysX5B47z5PM38; Sun, 07 Sep 2025 00:12:16 +0800 (CST) Received: from xaxapp02.zte.com.cn ([10.88.97.241]) by mse-fl2.zte.com.cn with SMTP id 586GC3oG010567; Sun, 7 Sep 2025 00:12:03 +0800 (+08) (envelope-from fan.yu9@zte.com.cn) Received: from mapi (xaxapp02[null]) by mapi (Zmail) with MAPI id mid32; Sun, 7 Sep 2025 00:12:05 +0800 (CST) Date: Sun, 7 Sep 2025 00:12:05 +0800 (CST) X-Zmail-TransId: 2afa68bc5d550ee-400f9 X-Mailer: Zmail v1.0 Message-ID: <20250907001205573L3XpsQMIQnLgDqiiKYd3H@zte.com.cn> In-Reply-To: <20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn> References: 20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , Cc: , , , Subject: =?UTF-8?B?W1BBVENIdjIgbGludXgtbmV4dCAxLzVdIHRvb2xzL2RlbGF5dG9wOiBhZGQgZmxleGlibGUgc29ydGluZyBieSBkZWxheSBmaWVsZA==?= X-MAIL: mse-fl2.zte.com.cn 586GC3oG010567 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: fan.yu9@zte.com.cn X-SPF: None X-SOURCE-IP: 10.5.228.133 unknown Sun, 07 Sep 2025 00:12:16 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 68BC5D60.001/4cJysX5B47z5PM38 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fan Yu The delaytop tool only supported sorting by CPU delay, which limited its usefulness when users needed to identify bottlenecks in other subsystems. Users had no way to sort processes by IO, IRQ, or other delay types to quickly pinpoint specific performance issues. Add -s/--sort option to allow sorting by different delay types. Users can now quickly identify bottlenecks in specific subsystems by sorting processes by the relevant delay metric. Signed-off-by: Fan Yu Reviewed-by: xu xin --- tools/accounting/delaytop.c | 153 ++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 32 deletions(-) diff --git a/tools/accounting/delaytop.c b/tools/accounting/delaytop.c index 9afb1ffc00ba..52718714496b 100644 --- a/tools/accounting/delaytop.c +++ b/tools/accounting/delaytop.c @@ -42,6 +42,7 @@ #include #include #include +#include #define PSI_CPU_SOME "/proc/pressure/cpu" #define PSI_CPU_FULL "/proc/pressure/cpu" @@ -61,6 +62,7 @@ #define TASK_COMM_LEN 16 #define MAX_MSG_SIZE 1024 #define MAX_TASKS 1000 +#define MAX_BUF_LEN 256 #define SET_TASK_STAT(task_count, field) tasks[task_count].field =3D stats= .field #define BOOL_FPRINT(stream, fmt, ...) \ ({ \ @@ -68,17 +70,11 @@ ret >=3D 0; \ }) #define PSI_LINE_FORMAT "%-12s %6.1f%%/%6.1f%%/%6.1f%%/%8llu(ms)\n" - -/* Program settings structure */ -struct config { - int delay; /* Update interval in seconds */ - int iterations; /* Number of iterations, 0 =3D=3D infinite */ - int max_processes; /* Maximum number of processes to show */ - char sort_field; /* Field to sort by */ - int output_one_time; /* Output once and exit */ - int monitor_pid; /* Monitor specific PID */ - char *container_path; /* Path to container cgroup */ -}; +#define SORT_FIELD(name) \ + {#name, \ + offsetof(struct task_info, name##_delay_total), \ + offsetof(struct task_info, name##_count)} +#define END_FIELD {NULL, 0, 0} /* PSI statistics structure */ struct psi_stats { @@ -130,6 +126,24 @@ struct container_stats { int nr_io_wait; /* Number of processes in IO wait */ }; +/* Delay field structure */ +struct field_desc { + const char *name; /* Field name for cmdline argument */ + unsigned long total_offset; /* Offset of total delay in task_info */ + unsigned long count_offset; /* Offset of count in task_info */ +}; + +/* Program settings structure */ +struct config { + int delay; /* Update interval in seconds */ + int iterations; /* Number of iterations, 0 =3D=3D infinite */ + int max_processes; /* Maximum number of processes to show */ + int output_one_time; /* Output once and exit */ + int monitor_pid; /* Monitor specific PID */ + char *container_path; /* Path to container cgroup */ + const struct field_desc *sort_field; /* Current sort field */ +}; + /* Global variables */ static struct config cfg; static struct psi_stats psi; @@ -137,6 +151,17 @@ static struct task_info tasks[MAX_TASKS]; static int task_count; static int running =3D 1; static struct container_stats container_stats; +static const struct field_desc sort_fields[] =3D { + SORT_FIELD(cpu), + SORT_FIELD(blkio), + SORT_FIELD(irq), + SORT_FIELD(swapin), + SORT_FIELD(freepages), + SORT_FIELD(thrashing), + SORT_FIELD(compact), + SORT_FIELD(wpcopy), + END_FIELD +}; /* Netlink socket variables */ static int nl_sd =3D -1; @@ -158,18 +183,59 @@ static void disable_raw_mode(void) tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); } +/* Find field descriptor by name with string comparison */ +static const struct field_desc *get_field_by_name(const char *name) +{ + const struct field_desc *field; + size_t field_len; + + for (field =3D sort_fields; field->name !=3D NULL; field++) { + field_len =3D strlen(field->name); + if (field_len !=3D strlen(name)) + continue; + if (strncmp(field->name, name, field_len) =3D=3D 0) + return field; + } + + return NULL; +} + +/* Find display name for a field descriptor */ +static const char *get_name_by_field(const struct field_desc *field) +{ + return field ? field->name : "UNKNOWN"; +} + +/* Generate string of available field names */ +static void display_available_fields(void) +{ + const struct field_desc *field; + char buf[MAX_BUF_LEN]; + + buf[0] =3D '\0'; + + for (field =3D sort_fields; field->name !=3D NULL; field++) { + strncat(buf, "|", MAX_BUF_LEN - strlen(buf) - 1); + strncat(buf, field->name, MAX_BUF_LEN - strlen(buf) - 1); + buf[MAX_BUF_LEN - 1] =3D '\0'; + } + + fprintf(stderr, "Available fields: %s\n", buf); +} + /* Display usage information and command line options */ static void usage(void) { printf("Usage: delaytop [Options]\n" "Options:\n" - " -h, --help Show this help message and exit\n" - " -d, --delay=3DSECONDS Set refresh interval (default: 2 seconds, min:= 1)\n" - " -n, --iterations=3DCOUNT Set number of updates (default: 0 =3D infinit= e)\n" - " -P, --processes=3DNUMBER Set maximum number of processes to show (defa= ult: 20, max: 1000)\n" - " -o, --once Display once and exit\n" - " -p, --pid=3DPID Monitor only the specified PID\n" - " -C, --container=3DPATH Monitor the container at specified cgroup path= \n"); + " -h, --help Show this help message and exit\n" + " -d, --delay=3DSECONDS Set refresh interval (default: 2 seconds, m= in: 1)\n" + " -n, --iterations=3DCOUNT Set number of updates (default: 0 =3D infin= ite)\n" + " -P, --processes=3DNUMBER Set maximum number of processes to show (de= fault: 20, max: 1000)\n" + " -o, --once Display once and exit\n" + " -p, --pid=3DPID Monitor only the specified PID\n" + " -C, --container=3DPATH Monitor the container at specified cgroup p= ath\n" + " -s, --sort=3DFIELD Sort by delay field (default: cpu)\n"); exit(0); } @@ -177,6 +243,7 @@ static void usage(void) static void parse_args(int argc, char **argv) { int c; + const struct field_desc *field; struct option long_options[] =3D { {"help", no_argument, 0, 'h'}, {"delay", required_argument, 0, 'd'}, @@ -184,6 +251,7 @@ static void parse_args(int argc, char **argv) {"pid", required_argument, 0, 'p'}, {"once", no_argument, 0, 'o'}, {"processes", required_argument, 0, 'P'}, + {"sort", required_argument, 0, 's'}, {"container", required_argument, 0, 'C'}, {0, 0, 0, 0} }; @@ -192,7 +260,7 @@ static void parse_args(int argc, char **argv) cfg.delay =3D 2; cfg.iterations =3D 0; cfg.max_processes =3D 20; - cfg.sort_field =3D 'c'; /* Default sort by CPU delay */ + cfg.sort_field =3D &sort_fields[0]; /* Default sorted by CPU delay */ cfg.output_one_time =3D 0; cfg.monitor_pid =3D 0; /* 0 means monitor all PIDs */ cfg.container_path =3D NULL; @@ -200,7 +268,7 @@ static void parse_args(int argc, char **argv) while (1) { int option_index =3D 0; - c =3D getopt_long(argc, argv, "hd:n:p:oP:C:", long_options, &option_inde= x); + c =3D getopt_long(argc, argv, "hd:n:p:oP:C:s:", long_options, &option_in= dex); if (c =3D=3D -1) break; @@ -247,6 +315,22 @@ static void parse_args(int argc, char **argv) case 'C': cfg.container_path =3D strdup(optarg); break; + case 's': + if (strlen(optarg) =3D=3D 0) { + fprintf(stderr, "Error: empty sort field\n"); + exit(1); + } + + field =3D get_field_by_name(optarg); + /* Show available fields if invalid option provided */ + if (!field) { + fprintf(stderr, "Error: invalid sort field '%s'\n", optarg); + display_available_fields(); + exit(1); + } + + cfg.sort_field =3D field; + break; default: fprintf(stderr, "Try 'delaytop --help' for more information.\n"); exit(1); @@ -587,19 +671,23 @@ static int compare_tasks(const void *a, const void *b) { const struct task_info *t1 =3D (const struct task_info *)a; const struct task_info *t2 =3D (const struct task_info *)b; + unsigned long long total1; + unsigned long long total2; + unsigned long count1; + unsigned long count2; double avg1, avg2; - switch (cfg.sort_field) { - case 'c': /* CPU */ - avg1 =3D average_ms(t1->cpu_delay_total, t1->cpu_count); - avg2 =3D average_ms(t2->cpu_delay_total, t2->cpu_count); - if (avg1 !=3D avg2) - return avg2 > avg1 ? 1 : -1; - return t2->cpu_delay_total > t1->cpu_delay_total ? 1 : -1; + total1 =3D *(unsigned long long *)((char *)t1 + cfg.sort_field->total_off= set); + total2 =3D *(unsigned long long *)((char *)t2 + cfg.sort_field->total_off= set); + count1 =3D *(unsigned long *)((char *)t1 + cfg.sort_field->count_offset); + count2 =3D *(unsigned long *)((char *)t2 + cfg.sort_field->count_offset); - default: - return t2->cpu_delay_total > t1->cpu_delay_total ? 1 : -1; - } + avg1 =3D average_ms(total1, count1); + avg2 =3D average_ms(total2, count2); + if (avg1 !=3D avg2) + return avg2 > avg1 ? 1 : -1; + + return 0; } /* Sort tasks by selected field */ @@ -738,8 +826,9 @@ static void display_results(void) container_stats.nr_stopped, container_stats.nr_uninterruptible, container_stats.nr_io_wait); } - suc &=3D BOOL_FPRINT(out, "Top %d processes (sorted by CPU delay):\n", - cfg.max_processes); + /* Task delay output */ + suc &=3D BOOL_FPRINT(out, "Top %d processes (sorted by %s delay):\n", + cfg.max_processes, get_name_by_field(cfg.sort_field)); suc &=3D BOOL_FPRINT(out, "%5s %5s %-17s", "PID", "TGID", "COMMAND"); suc &=3D BOOL_FPRINT(out, "%7s %7s %7s %7s %7s %7s %7s %7s\n", "CPU(ms)", "IO(ms)", "SWAP(ms)", "RCL(ms)", --=20 2.25.1 From nobody Tue Sep 9 16:39:59 2025 Received: from mxct.zte.com.cn (mxct.zte.com.cn [58.251.27.85]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 52C1924728E; Sat, 6 Sep 2025 16:19:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=58.251.27.85 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175594; cv=none; b=mfyDrnuFzYJsJigaBsSBy+6h9mO+v6MUja6By6m7aJ159dwH8ylfBUXMFJnSIaQ/mX/MYQhHdTTjl+tFe9tK6q3X4uOaQpS7TzQbDnIAa2zqC7YIPjycv2VBBA4FrUgoSdzYm7CyhzwCWWmthqjOZmNv+VQNp+TW3tik/7xYSh8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175594; c=relaxed/simple; bh=eaB9N8EWHxHf2EroKxZ/EgJX0a80wrpJveqhMT3h9a8=; h=Date:Message-ID:In-Reply-To:References:Mime-Version:From:To:Cc: Subject:Content-Type; b=BrZsvK8yHcU3VDL04/ZM/AqZAFLpRnVk5Gfy7/+n2iGfI5v7hduYooLsGdkEO8p0L/tJExr2uOFtmb8xwv3kt6uoQIqI3yVMis4BwvSz6eoNW+q+8lpo4j7kzJl39HwQGSAEcQNELJV+3+z3QXnORZadsaBqT5ClgpQNADmxp/0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=58.251.27.85 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mxde.zte.com.cn (unknown [10.35.20.121]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4cJytc6CBPz7PJx; Sun, 07 Sep 2025 00:13:12 +0800 (CST) Received: from mxhk.zte.com.cn (unknown [192.168.250.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxde.zte.com.cn (FangMail) with ESMTPS id 4cJytW38yzzBQkJn; Sun, 07 Sep 2025 00:13:07 +0800 (CST) Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4cJytF3c8Fz8Xs6w; Sun, 07 Sep 2025 00:12:53 +0800 (CST) Received: from xaxapp04.zte.com.cn ([10.99.98.157]) by mse-fl1.zte.com.cn with SMTP id 586GCmEV034748; Sun, 7 Sep 2025 00:12:49 +0800 (+08) (envelope-from fan.yu9@zte.com.cn) Received: from mapi (xaxapp04[null]) by mapi (Zmail) with MAPI id mid32; Sun, 7 Sep 2025 00:12:52 +0800 (CST) Date: Sun, 7 Sep 2025 00:12:52 +0800 (CST) X-Zmail-TransId: 2afb68bc5d84ead-35ec3 X-Mailer: Zmail v1.0 Message-ID: <202509070012527934u0ySb3teQ4gOYKnocyNO@zte.com.cn> In-Reply-To: <20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn> References: 20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , Cc: , , , Subject: =?UTF-8?B?W1BBVENIdjIgbGludXgtbmV4dCAyLzVdIHRvb2xzL2RlbGF5dG9wOiBhZGQgbWVtb3J5IHZlcmJvc2UgbW9kZSBzdXBwb3J0?= X-MAIL: mse-fl1.zte.com.cn 586GCmEV034748 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: fan.yu9@zte.com.cn X-SPF: None X-SOURCE-IP: 10.35.20.121 unknown Sun, 07 Sep 2025 00:13:13 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 68BC5D97.000/4cJytc6CBPz7PJx Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fan Yu The original delaytop tool always displayed detailed memory subsystem breakdown, which could be overwhelming for users who only need high-level overview. Add flexible display control allowing users to choose their preferred information granularity. The new flexibility provides: 1) For quick monitoring: use normal mode to reduce visual clutter 2) For deep analysis: use verbose mode to see all memory subsystem details Signed-off-by: Fan Yu Reviewed-by: xu xin --- tools/accounting/delaytop.c | 128 +++++++++++++++++++++++++++--------- 1 file changed, 98 insertions(+), 30 deletions(-) diff --git a/tools/accounting/delaytop.c b/tools/accounting/delaytop.c index 52718714496b..30dc95fb531a 100644 --- a/tools/accounting/delaytop.c +++ b/tools/accounting/delaytop.c @@ -69,13 +69,22 @@ int ret =3D fprintf(stream, fmt, ##__VA_ARGS__); \ ret >=3D 0; \ }) +#define TASK_AVG(task, field) average_ms((task).field##_delay_total, (task= ).field##_count) #define PSI_LINE_FORMAT "%-12s %6.1f%%/%6.1f%%/%6.1f%%/%8llu(ms)\n" -#define SORT_FIELD(name) \ +#define DELAY_FMT_DEFAULT "%8.2f %8.2f %8.2f %8.2f\n" +#define DELAY_FMT_MEMVERBOSE "%8.2f %8.2f %8.2f %8.2f %8.2f %8.2f\n" +#define SORT_FIELD(name, modes) \ {#name, \ offsetof(struct task_info, name##_delay_total), \ - offsetof(struct task_info, name##_count)} + offsetof(struct task_info, name##_count), \ + modes} #define END_FIELD {NULL, 0, 0} +/* Display mode types */ +#define MODE_TYPE_ALL (0xFFFFFFFF) +#define MODE_DEFAULT (1 << 0) +#define MODE_MEMVERBOSE (1 << 1) + /* PSI statistics structure */ struct psi_stats { double cpu_some_avg10, cpu_some_avg60, cpu_some_avg300; @@ -115,6 +124,8 @@ struct task_info { unsigned long long wpcopy_delay_total; unsigned long long irq_count; unsigned long long irq_delay_total; + unsigned long long mem_count; + unsigned long long mem_delay_total; }; /* Container statistics structure */ @@ -131,6 +142,7 @@ struct field_desc { const char *name; /* Field name for cmdline argument */ unsigned long total_offset; /* Offset of total delay in task_info */ unsigned long count_offset; /* Offset of count in task_info */ + size_t supported_modes; /* Supported display modes */ }; /* Program settings structure */ @@ -142,6 +154,7 @@ struct config { int monitor_pid; /* Monitor specific PID */ char *container_path; /* Path to container cgroup */ const struct field_desc *sort_field; /* Current sort field */ + size_t display_mode; /* Current display mode */ }; /* Global variables */ @@ -152,14 +165,15 @@ static int task_count; static int running =3D 1; static struct container_stats container_stats; static const struct field_desc sort_fields[] =3D { - SORT_FIELD(cpu), - SORT_FIELD(blkio), - SORT_FIELD(irq), - SORT_FIELD(swapin), - SORT_FIELD(freepages), - SORT_FIELD(thrashing), - SORT_FIELD(compact), - SORT_FIELD(wpcopy), + SORT_FIELD(cpu, MODE_DEFAULT), + SORT_FIELD(blkio, MODE_DEFAULT), + SORT_FIELD(irq, MODE_DEFAULT), + SORT_FIELD(mem, MODE_DEFAULT | MODE_MEMVERBOSE), + SORT_FIELD(swapin, MODE_MEMVERBOSE), + SORT_FIELD(freepages, MODE_MEMVERBOSE), + SORT_FIELD(thrashing, MODE_MEMVERBOSE), + SORT_FIELD(compact, MODE_MEMVERBOSE), + SORT_FIELD(wpcopy, MODE_MEMVERBOSE), END_FIELD }; @@ -207,7 +221,7 @@ static const char *get_name_by_field(const struct field= _desc *field) } /* Generate string of available field names */ -static void display_available_fields(void) +static void display_available_fields(size_t mode) { const struct field_desc *field; char buf[MAX_BUF_LEN]; @@ -215,6 +229,8 @@ static void display_available_fields(void) buf[0] =3D '\0'; for (field =3D sort_fields; field->name !=3D NULL; field++) { + if (!(field->supported_modes & mode)) + continue; strncat(buf, "|", MAX_BUF_LEN - strlen(buf) - 1); strncat(buf, field->name, MAX_BUF_LEN - strlen(buf) - 1); buf[MAX_BUF_LEN - 1] =3D '\0'; @@ -235,7 +251,8 @@ static void usage(void) " -o, --once Display once and exit\n" " -p, --pid=3DPID Monitor only the specified PID\n" " -C, --container=3DPATH Monitor the container at specified cgroup p= ath\n" - " -s, --sort=3DFIELD Sort by delay field (default: cpu)\n"); + " -s, --sort=3DFIELD Sort by delay field (default: cpu)\n" + " -M, --memverbose Display memory detailed information\n"); exit(0); } @@ -253,6 +270,7 @@ static void parse_args(int argc, char **argv) {"processes", required_argument, 0, 'P'}, {"sort", required_argument, 0, 's'}, {"container", required_argument, 0, 'C'}, + {"memverbose", no_argument, 0, 'M'}, {0, 0, 0, 0} }; @@ -264,11 +282,12 @@ static void parse_args(int argc, char **argv) cfg.output_one_time =3D 0; cfg.monitor_pid =3D 0; /* 0 means monitor all PIDs */ cfg.container_path =3D NULL; + cfg.display_mode =3D MODE_DEFAULT; while (1) { int option_index =3D 0; - c =3D getopt_long(argc, argv, "hd:n:p:oP:C:s:", long_options, &option_in= dex); + c =3D getopt_long(argc, argv, "hd:n:p:oP:C:s:M", long_options, &option_i= ndex); if (c =3D=3D -1) break; @@ -325,12 +344,16 @@ static void parse_args(int argc, char **argv) /* Show available fields if invalid option provided */ if (!field) { fprintf(stderr, "Error: invalid sort field '%s'\n", optarg); - display_available_fields(); + display_available_fields(MODE_TYPE_ALL); exit(1); } cfg.sort_field =3D field; break; + case 'M': + cfg.display_mode =3D MODE_MEMVERBOSE; + cfg.sort_field =3D get_field_by_name("mem"); + break; default: fprintf(stderr, "Try 'delaytop --help' for more information.\n"); exit(1); @@ -338,6 +361,25 @@ static void parse_args(int argc, char **argv) } } +/* Calculate average delay in milliseconds for overall memory */ +static void set_mem_delay_total(struct task_info *t) +{ + t->mem_delay_total =3D t->swapin_delay_total + + t->freepages_delay_total + + t->thrashing_delay_total + + t->compact_delay_total + + t->wpcopy_delay_total; +} + +static void set_mem_count(struct task_info *t) +{ + t->mem_count =3D t->swapin_count + + t->freepages_count + + t->thrashing_count + + t->compact_count + + t->wpcopy_count; +} + /* Create a raw netlink socket and bind */ static int create_nl_socket(void) { @@ -611,6 +653,8 @@ static void fetch_and_fill_task_info(int pid, const cha= r *comm) SET_TASK_STAT(task_count, wpcopy_delay_total); SET_TASK_STAT(task_count, irq_count); SET_TASK_STAT(task_count, irq_delay_total); + set_mem_count(&tasks[task_count]); + set_mem_delay_total(&tasks[task_count]); task_count++; } break; @@ -829,27 +873,44 @@ static void display_results(void) /* Task delay output */ suc &=3D BOOL_FPRINT(out, "Top %d processes (sorted by %s delay):\n", cfg.max_processes, get_name_by_field(cfg.sort_field)); - suc &=3D BOOL_FPRINT(out, "%5s %5s %-17s", "PID", "TGID", "COMMAND"); - suc &=3D BOOL_FPRINT(out, "%7s %7s %7s %7s %7s %7s %7s %7s\n", - "CPU(ms)", "IO(ms)", "SWAP(ms)", "RCL(ms)", - "THR(ms)", "CMP(ms)", "WP(ms)", "IRQ(ms)"); - suc &=3D BOOL_FPRINT(out, "----------------------------------------------= -"); - suc &=3D BOOL_FPRINT(out, "----------------------------------------------= \n"); + suc &=3D BOOL_FPRINT(out, "%8s %8s %-17s", "PID", "TGID", "COMMAND"); + if (cfg.display_mode =3D=3D MODE_MEMVERBOSE) { + suc &=3D BOOL_FPRINT(out, "%8s %8s %8s %8s %8s %8s\n", + "MEM(ms)", "SWAP(ms)", "RCL(ms)", + "THR(ms)", "CMP(ms)", "WP(ms)"); + suc &=3D BOOL_FPRINT(out, "-----------------------"); + suc &=3D BOOL_FPRINT(out, "-----------------------"); + suc &=3D BOOL_FPRINT(out, "-----------------------"); + suc &=3D BOOL_FPRINT(out, "---------------------\n"); + } else { + suc &=3D BOOL_FPRINT(out, "%8s %8s %8s %8s\n", + "CPU(ms)", "IO(ms)", "IRQ(ms)", "MEM(ms)"); + suc &=3D BOOL_FPRINT(out, "-----------------------"); + suc &=3D BOOL_FPRINT(out, "-----------------------"); + suc &=3D BOOL_FPRINT(out, "--------------------------\n"); + } + count =3D task_count < cfg.max_processes ? task_count : cfg.max_processes; for (i =3D 0; i < count; i++) { - suc &=3D BOOL_FPRINT(out, "%5d %5d %-15s", + suc &=3D BOOL_FPRINT(out, "%8d %8d %-15s", tasks[i].pid, tasks[i].tgid, tasks[i].command); - suc &=3D BOOL_FPRINT(out, "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.= 2f\n", - average_ms(tasks[i].cpu_delay_total, tasks[i].cpu_count), - average_ms(tasks[i].blkio_delay_total, tasks[i].blkio_count), - average_ms(tasks[i].swapin_delay_total, tasks[i].swapin_count), - average_ms(tasks[i].freepages_delay_total, tasks[i].freepages_count), - average_ms(tasks[i].thrashing_delay_total, tasks[i].thrashing_count), - average_ms(tasks[i].compact_delay_total, tasks[i].compact_count), - average_ms(tasks[i].wpcopy_delay_total, tasks[i].wpcopy_count), - average_ms(tasks[i].irq_delay_total, tasks[i].irq_count)); + if (cfg.display_mode =3D=3D MODE_MEMVERBOSE) { + suc &=3D BOOL_FPRINT(out, DELAY_FMT_MEMVERBOSE, + TASK_AVG(tasks[i], mem), + TASK_AVG(tasks[i], swapin), + TASK_AVG(tasks[i], freepages), + TASK_AVG(tasks[i], thrashing), + TASK_AVG(tasks[i], compact), + TASK_AVG(tasks[i], wpcopy)); + } else { + suc &=3D BOOL_FPRINT(out, DELAY_FMT_DEFAULT, + TASK_AVG(tasks[i], cpu), + TASK_AVG(tasks[i], blkio), + TASK_AVG(tasks[i], irq), + TASK_AVG(tasks[i], mem)); + } } suc &=3D BOOL_FPRINT(out, "\n"); @@ -891,6 +952,13 @@ int main(int argc, char **argv) /* Main loop */ while (running) { + /* Exit when sort field do not match display mode */ + if (!(cfg.sort_field->supported_modes & cfg.display_mode)) { + fprintf(stderr, "Sort field not supported in this mode\n"); + display_available_fields(cfg.display_mode); + break; + } + /* Read PSI statistics */ read_psi_stats(); --=20 2.25.1 From nobody Tue Sep 9 16:39:59 2025 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49F321C863B; Sat, 6 Sep 2025 16:13:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175229; cv=none; b=lPGyWnIR+nEKPwfbFqtxMfDAevHi6k5YUYepPpThhCNcZPhCQ3Tw9gAv2+mSSXUj1zNaN3B8dw8jzY6N1kDBW5LiVNSxY7Qlx+rOnfPF5TxUeh5gDNJJoADlqUvYaHs81JedCVNVbxzBUKB0Jol5a2M8oKgNYiflTzmaJwlTW9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175229; c=relaxed/simple; bh=qjIAY2ocBBeJktL3RCCX7Wqjw7fa4i517ZZ8/TPxJJ0=; h=Date:Message-ID:In-Reply-To:References:Mime-Version:From:To:Cc: Subject:Content-Type; b=ql4RdRGjL47kHjME8GgXe1OHo//uNqOtCpBAwXR5nJCd4INPepdVPpBXERuBeX+rxKot69vAHJSiu0UuJF2wwUnMiZ5aIQnADWlxXH26Q6CgnFmr35LPUuod1UCAvZGo9cBkx06g/1xj0S6Pv9ucXGpyNul8UHAcVa5hfd3QGLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4cJyvD1w0qz5BNRd; Sun, 07 Sep 2025 00:13:44 +0800 (CST) Received: from xaxapp02.zte.com.cn ([10.88.97.241]) by mse-fl2.zte.com.cn with SMTP id 586GDaGH010892; Sun, 7 Sep 2025 00:13:37 +0800 (+08) (envelope-from fan.yu9@zte.com.cn) Received: from mapi (xaxapp04[null]) by mapi (Zmail) with MAPI id mid32; Sun, 7 Sep 2025 00:13:38 +0800 (CST) Date: Sun, 7 Sep 2025 00:13:38 +0800 (CST) X-Zmail-TransId: 2afb68bc5db267c-36691 X-Mailer: Zmail v1.0 Message-ID: <20250907001338580EURha20BxWFmBSrUpS8D1@zte.com.cn> In-Reply-To: <20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn> References: 20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , Cc: , , , Subject: =?UTF-8?B?W1BBVENIdjIgbGludXgtbmV4dCAzLzVdIHRvb2xzL2RlbGF5dG9wOiBhZGQgaW50ZXJhY3RpdmUgbW9kZSB3aXRoIGtleWJvYXJkIGNvbnRyb2xz?= X-MAIL: mse-fl2.zte.com.cn 586GDaGH010892 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: fan.yu9@zte.com.cn X-SPF: None X-SOURCE-IP: 10.5.228.133 unknown Sun, 07 Sep 2025 00:13:44 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 68BC5DB8.000/4cJyvD1w0qz5BNRd Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fan Yu The original delaytop only supported static output with limited interaction. Users had to restart the tool with different command-line options to change sorting or display modes, which disrupted continuous monitoring and reduced productivity during performance investigations. Adds real-time interactive controls through keyboard input: 1) Add interactive menu system with visual prompts 2) Support dynamic sorting changes without restarting 3) Enable toggle of memory verbose mode with 'M' key The interactive mode transforms delaytop from a static monitoring tool into a dynamic investigation platform, allowing users to adapt the view in real-time based on observed performance patterns. Signed-off-by: Fan Yu Reviewed-by: xu xin --- tools/accounting/delaytop.c | 166 ++++++++++++++++++++++++++---------- 1 file changed, 121 insertions(+), 45 deletions(-) diff --git a/tools/accounting/delaytop.c b/tools/accounting/delaytop.c index 30dc95fb531a..7bd1a1eeb354 100644 --- a/tools/accounting/delaytop.c +++ b/tools/accounting/delaytop.c @@ -73,8 +73,8 @@ #define PSI_LINE_FORMAT "%-12s %6.1f%%/%6.1f%%/%6.1f%%/%8llu(ms)\n" #define DELAY_FMT_DEFAULT "%8.2f %8.2f %8.2f %8.2f\n" #define DELAY_FMT_MEMVERBOSE "%8.2f %8.2f %8.2f %8.2f %8.2f %8.2f\n" -#define SORT_FIELD(name, modes) \ - {#name, \ +#define SORT_FIELD(name, cmd, modes) \ + {#name, #cmd, \ offsetof(struct task_info, name##_delay_total), \ offsetof(struct task_info, name##_count), \ modes} @@ -140,6 +140,7 @@ struct container_stats { /* Delay field structure */ struct field_desc { const char *name; /* Field name for cmdline argument */ + const char *cmd_char; /* Interactive command */ unsigned long total_offset; /* Offset of total delay in task_info */ unsigned long count_offset; /* Offset of count in task_info */ size_t supported_modes; /* Supported display modes */ @@ -165,17 +166,18 @@ static int task_count; static int running =3D 1; static struct container_stats container_stats; static const struct field_desc sort_fields[] =3D { - SORT_FIELD(cpu, MODE_DEFAULT), - SORT_FIELD(blkio, MODE_DEFAULT), - SORT_FIELD(irq, MODE_DEFAULT), - SORT_FIELD(mem, MODE_DEFAULT | MODE_MEMVERBOSE), - SORT_FIELD(swapin, MODE_MEMVERBOSE), - SORT_FIELD(freepages, MODE_MEMVERBOSE), - SORT_FIELD(thrashing, MODE_MEMVERBOSE), - SORT_FIELD(compact, MODE_MEMVERBOSE), - SORT_FIELD(wpcopy, MODE_MEMVERBOSE), + SORT_FIELD(cpu, c, MODE_DEFAULT), + SORT_FIELD(blkio, i, MODE_DEFAULT), + SORT_FIELD(irq, q, MODE_DEFAULT), + SORT_FIELD(mem, m, MODE_DEFAULT | MODE_MEMVERBOSE), + SORT_FIELD(swapin, s, MODE_MEMVERBOSE), + SORT_FIELD(freepages, r, MODE_MEMVERBOSE), + SORT_FIELD(thrashing, t, MODE_MEMVERBOSE), + SORT_FIELD(compact, p, MODE_MEMVERBOSE), + SORT_FIELD(wpcopy, w, MODE_MEMVERBOSE), END_FIELD }; +static int sort_selected; /* Netlink socket variables */ static int nl_sd =3D -1; @@ -197,6 +199,19 @@ static void disable_raw_mode(void) tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); } +/* Find field descriptor by command line */ +static const struct field_desc *get_field_by_cmd_char(char ch) +{ + const struct field_desc *field; + + for (field =3D sort_fields; field->name !=3D NULL; field++) { + if (field->cmd_char[0] =3D=3D ch) + return field; + } + + return NULL; +} + /* Find field descriptor by name with string comparison */ static const struct field_desc *get_field_by_name(const char *name) { @@ -870,6 +885,18 @@ static void display_results(void) container_stats.nr_stopped, container_stats.nr_uninterruptible, container_stats.nr_io_wait); } + + /* Interacive command */ + suc &=3D BOOL_FPRINT(out, "[o]sort [M]memverbose [q]quit\n"); + if (sort_selected) { + if (cfg.display_mode =3D=3D MODE_MEMVERBOSE) + suc &=3D BOOL_FPRINT(out, + "sort selection: [m]MEM [r]RCL [t]THR [p]CMP [w]WP\n"); + else + suc &=3D BOOL_FPRINT(out, + "sort selection: [c]CPU [i]IO [m]MEM [q]IRQ\n"); + } + /* Task delay output */ suc &=3D BOOL_FPRINT(out, "Top %d processes (sorted by %s delay):\n", cfg.max_processes, get_name_by_field(cfg.sort_field)); @@ -919,11 +946,78 @@ static void display_results(void) perror("Error writing to output"); } +/* Check for keyboard input with timeout based on cfg.delay */ +static char check_for_keypress(void) +{ + struct timeval tv =3D {cfg.delay, 0}; + fd_set readfds; + char ch =3D 0; + + FD_ZERO(&readfds); + FD_SET(STDIN_FILENO, &readfds); + int r =3D select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv); + + if (r > 0 && FD_ISSET(STDIN_FILENO, &readfds)) { + read(STDIN_FILENO, &ch, 1); + return ch; + } + + return 0; +} + +#define MAX_MODE_SIZE 2 +static void toggle_display_mode(void) +{ + static const size_t modes[MAX_MODE_SIZE] =3D {MODE_DEFAULT, MODE_MEMVERBO= SE}; + static size_t cur_index; + + cur_index =3D (cur_index + 1) % MAX_MODE_SIZE; + cfg.display_mode =3D modes[cur_index]; +} + +/* Handle keyboard input: sorting selection, mode toggle, or quit */ +static void handle_keypress(char ch, int *running) +{ + const struct field_desc *field; + + /* Change sort field */ + if (sort_selected) { + field =3D get_field_by_cmd_char(ch); + if (field && (field->supported_modes & cfg.display_mode)) + cfg.sort_field =3D field; + + sort_selected =3D 0; + /* Handle mode changes or quit */ + } else { + switch (ch) { + case 'o': + sort_selected =3D 1; + break; + case 'M': + toggle_display_mode(); + for (field =3D sort_fields; field->name !=3D NULL; field++) { + if (field->supported_modes & cfg.display_mode) { + cfg.sort_field =3D field; + break; + } + } + break; + case 'q': + case 'Q': + *running =3D 0; + break; + default: + break; + } + } +} + /* Main function */ int main(int argc, char **argv) { + const struct field_desc *field; int iterations =3D 0; - int use_q_quit =3D 0; + char keypress; /* Parse command line arguments */ parse_args(argc, argv); @@ -943,20 +1037,20 @@ int main(int argc, char **argv) exit(1); } - if (!cfg.output_one_time) { - use_q_quit =3D 1; - enable_raw_mode(); - printf("Press 'q' to quit.\n"); - fflush(stdout); - } + /* Set terminal to non-canonical mode for interaction */ + enable_raw_mode(); /* Main loop */ while (running) { - /* Exit when sort field do not match display mode */ + /* Auto-switch sort field when not matching display mode */ if (!(cfg.sort_field->supported_modes & cfg.display_mode)) { - fprintf(stderr, "Sort field not supported in this mode\n"); - display_available_fields(cfg.display_mode); - break; + for (field =3D sort_fields; field->name !=3D NULL; field++) { + if (field->supported_modes & cfg.display_mode) { + cfg.sort_field =3D field; + printf("Auto-switched sort field to: %s\n", field->name); + break; + } + } } /* Read PSI statistics */ @@ -983,32 +1077,14 @@ int main(int argc, char **argv) if (cfg.output_one_time) break; - /* Check for 'q' key to quit */ - if (use_q_quit) { - struct timeval tv =3D {cfg.delay, 0}; - fd_set readfds; - - FD_ZERO(&readfds); - FD_SET(STDIN_FILENO, &readfds); - int r =3D select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv); - - if (r > 0 && FD_ISSET(STDIN_FILENO, &readfds)) { - char ch =3D 0; - - read(STDIN_FILENO, &ch, 1); - if (ch =3D=3D 'q' || ch =3D=3D 'Q') { - running =3D 0; - break; - } - } - } else { - sleep(cfg.delay); - } + /* Keypress for interactive usage */ + keypress =3D check_for_keypress(); + if (keypress) + handle_keypress(keypress, &running); } /* Restore terminal mode */ - if (use_q_quit) - disable_raw_mode(); + disable_raw_mode(); /* Cleanup */ close(nl_sd); --=20 2.25.1 From nobody Tue Sep 9 16:39:59 2025 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DF041DDE9; Sat, 6 Sep 2025 16:14:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.35 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175281; cv=none; b=Okt23ikyQyiBgcMZJm9nYf10lM9C9TzUGOE1Ziy+SVGdAjTEBpLXwr+m1dEiTOLV5Urd0v8JG5TMKwE8E3dKapFzfzhuCO0plO+06E/Q7a5ZrzJbj6yaO+rZGAini1SEKew36LU24UXyR5Te6jkceRAYj6lJlQKYqm/ag1u2ANE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175281; c=relaxed/simple; bh=gYjed6G+nWlzA/HwYJOGqC15hyaQB/MDxR31cpFhYg4=; h=Date:Message-ID:In-Reply-To:References:Mime-Version:From:To:Cc: Subject:Content-Type; b=jFe8pXoB+Gg9+ZWLICiF8xTd3rwG4Y1ULOhBRrVUctwq/IUxWi9MOnoapMs71uh0wddh8cJ1q4Cl7vIfpEpAKgL5Ck9GEdruc/zi3X2dIg52RQTYV+OUaoQ/2q7Mw4qW2+7BOQAvJEtoY3ZHAhPsO2in8El2bZvmSy8CYM1VMW8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.35 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4cJyw800xBz8Xs6w; Sun, 07 Sep 2025 00:14:32 +0800 (CST) Received: from xaxapp05.zte.com.cn ([10.99.98.109]) by mse-fl1.zte.com.cn with SMTP id 586GEDBJ035044; Sun, 7 Sep 2025 00:14:13 +0800 (+08) (envelope-from fan.yu9@zte.com.cn) Received: from mapi (xaxapp05[null]) by mapi (Zmail) with MAPI id mid32; Sun, 7 Sep 2025 00:14:17 +0800 (CST) Date: Sun, 7 Sep 2025 00:14:17 +0800 (CST) X-Zmail-TransId: 2afc68bc5dd9d62-30d7d X-Mailer: Zmail v1.0 Message-ID: <20250907001417537vSx6nUsb3ILqI0iQ-WnGp@zte.com.cn> In-Reply-To: <20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn> References: 20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , Cc: , , , Subject: =?UTF-8?B?W1BBVENIdjIgbGludXgtbmV4dCA0LzVdIHRvb2xzL2RlbGF5dG9wOiBJbXByb3ZlIGVycm9yIGhhbmRsaW5nIGZvciBtaXNzaW5nIFBTSSBzdXBwb3J0?= X-MAIL: mse-fl1.zte.com.cn 586GEDBJ035044 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: fan.yu9@zte.com.cn X-SPF: None X-SOURCE-IP: 10.5.228.132 unknown Sun, 07 Sep 2025 00:14:32 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 68BC5DE7.001/4cJyw800xBz8Xs6w Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fan Yu Enhanced display logic to conditionally show PSI information only when successfully read, with helpful guidance for users to enable PSI support (psi=3D1 cmdline parameter). Signed-off-by: Fan Yu Reviewed-by: xu xin --- tools/accounting/delaytop.c | 182 +++++++++++++++++++++++------------- 1 file changed, 116 insertions(+), 66 deletions(-) diff --git a/tools/accounting/delaytop.c b/tools/accounting/delaytop.c index 7bd1a1eeb354..72cc500b44b1 100644 --- a/tools/accounting/delaytop.c +++ b/tools/accounting/delaytop.c @@ -44,13 +44,11 @@ #include #include -#define PSI_CPU_SOME "/proc/pressure/cpu" -#define PSI_CPU_FULL "/proc/pressure/cpu" -#define PSI_MEMORY_SOME "/proc/pressure/memory" -#define PSI_MEMORY_FULL "/proc/pressure/memory" -#define PSI_IO_SOME "/proc/pressure/io" -#define PSI_IO_FULL "/proc/pressure/io" -#define PSI_IRQ_FULL "/proc/pressure/irq" +#define PSI_PATH "/proc/pressure" +#define PSI_CPU_PATH "/proc/pressure/cpu" +#define PSI_MEMORY_PATH "/proc/pressure/memory" +#define PSI_IO_PATH "/proc/pressure/io" +#define PSI_IRQ_PATH "/proc/pressure/irq" #define NLA_NEXT(na) ((struct nlattr *)((char *)(na) + NLA_ALIGN((na)->n= la_len))) #define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN)) @@ -499,87 +497,134 @@ static int get_family_id(int sd) return id; } -static void read_psi_stats(void) +static int read_psi_stats(void) { FILE *fp; char line[256]; int ret =3D 0; + int error_count =3D 0; + + /* Check if PSI path exists */ + if (access(PSI_PATH, F_OK) !=3D 0) { + fprintf(stderr, "Error: PSI interface not found at %s\n", PSI_PATH); + fprintf(stderr, "Please ensure your kernel supports PSI (Pressure Stall = Information)\n"); + return -1; + } + /* Zero all fields */ memset(&psi, 0, sizeof(psi)); + /* CPU pressure */ - fp =3D fopen(PSI_CPU_SOME, "r"); + fp =3D fopen(PSI_CPU_PATH, "r"); if (fp) { while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "some", 4) =3D=3D 0) { ret =3D sscanf(line, "some avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.cpu_some_avg10, &psi.cpu_some_avg60, &psi.cpu_some_avg300, &psi.cpu_some_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse CPU some PSI data\n"); + error_count++; + } } else if (strncmp(line, "full", 4) =3D=3D 0) { ret =3D sscanf(line, "full avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.cpu_full_avg10, &psi.cpu_full_avg60, &psi.cpu_full_avg300, &psi.cpu_full_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse CPU full PSI data\n"); + error_count++; + } } } fclose(fp); + } else { + fprintf(stderr, "Warning: Failed to open %s\n", PSI_CPU_PATH); + error_count++; } + /* Memory pressure */ - fp =3D fopen(PSI_MEMORY_SOME, "r"); + fp =3D fopen(PSI_MEMORY_PATH, "r"); if (fp) { while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "some", 4) =3D=3D 0) { ret =3D sscanf(line, "some avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.memory_some_avg10, &psi.memory_some_avg60, &psi.memory_some_avg300, &psi.memory_some_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse Memory some PSI data\n"); + error_count++; + } } else if (strncmp(line, "full", 4) =3D=3D 0) { ret =3D sscanf(line, "full avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.memory_full_avg10, &psi.memory_full_avg60, &psi.memory_full_avg300, &psi.memory_full_total); - } - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse Memory full PSI data\n"); + error_count++; + } + } } fclose(fp); + } else { + fprintf(stderr, "Warning: Failed to open %s\n", PSI_MEMORY_PATH); + error_count++; } + /* IO pressure */ - fp =3D fopen(PSI_IO_SOME, "r"); + fp =3D fopen(PSI_IO_PATH, "r"); if (fp) { while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "some", 4) =3D=3D 0) { ret =3D sscanf(line, "some avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.io_some_avg10, &psi.io_some_avg60, &psi.io_some_avg300, &psi.io_some_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse IO some PSI data\n"); + error_count++; + } } else if (strncmp(line, "full", 4) =3D=3D 0) { ret =3D sscanf(line, "full avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.io_full_avg10, &psi.io_full_avg60, &psi.io_full_avg300, &psi.io_full_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse IO full PSI data\n"); + error_count++; + } } } fclose(fp); + } else { + fprintf(stderr, "Warning: Failed to open %s\n", PSI_IO_PATH); + error_count++; } + /* IRQ pressure (only full) */ - fp =3D fopen(PSI_IRQ_FULL, "r"); + fp =3D fopen(PSI_IRQ_PATH, "r"); if (fp) { while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "full", 4) =3D=3D 0) { ret =3D sscanf(line, "full avg10=3D%lf avg60=3D%lf avg300=3D%lf total= =3D%llu", &psi.irq_full_avg10, &psi.irq_full_avg60, &psi.irq_full_avg300, &psi.irq_full_total); - if (ret !=3D 4) + if (ret !=3D 4) { fprintf(stderr, "Failed to parse IRQ full PSI data\n"); + error_count++; + } } } fclose(fp); + } else { + fprintf(stderr, "Warning: Failed to open %s\n", PSI_IRQ_PATH); + error_count++; } + + /* Return error count: 0 means success, >0 means warnings, -1 means fatal= error */ + if (error_count > 0) { + fprintf(stderr, "PSI stats reading completed with %d warnings\n", error_= count); + return error_count; + } + + return 0; } static int read_comm(int pid, char *comm_buf, size_t buf_size) @@ -820,7 +865,7 @@ static void get_container_stats(void) } /* Display results to stdout or log file */ -static void display_results(void) +static void display_results(int psi_ret) { time_t now =3D time(NULL); struct tm *tm_now =3D localtime(&now); @@ -833,49 +878,53 @@ static void display_results(void) suc &=3D BOOL_FPRINT(out, "\033[H\033[J"); /* PSI output (one-line, no cat style) */ - suc &=3D BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60/avg3= 00/total)\n"); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "CPU some:", - psi.cpu_some_avg10, - psi.cpu_some_avg60, - psi.cpu_some_avg300, - psi.cpu_some_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "CPU full:", - psi.cpu_full_avg10, - psi.cpu_full_avg60, - psi.cpu_full_avg300, - psi.cpu_full_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "Memory full:", - psi.memory_full_avg10, - psi.memory_full_avg60, - psi.memory_full_avg300, - psi.memory_full_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "Memory some:", - psi.memory_some_avg10, - psi.memory_some_avg60, - psi.memory_some_avg300, - psi.memory_some_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "IO full:", - psi.io_full_avg10, - psi.io_full_avg60, - psi.io_full_avg300, - psi.io_full_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "IO some:", - psi.io_some_avg10, - psi.io_some_avg60, - psi.io_some_avg300, - psi.io_some_total / 1000); - suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, - "IRQ full:", - psi.irq_full_avg10, - psi.irq_full_avg60, - psi.irq_full_avg300, - psi.irq_full_total / 1000); + suc &=3D BOOL_FPRINT(out, "System Pressure Information: (avg10/avg60vg300= /total)\n"); + if (psi_ret) { + suc &=3D BOOL_FPRINT(out, " PSI not found: check if psi=3D1 enabled in = cmdline\n"); + } else { + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "CPU some:", + psi.cpu_some_avg10, + psi.cpu_some_avg60, + psi.cpu_some_avg300, + psi.cpu_some_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "CPU full:", + psi.cpu_full_avg10, + psi.cpu_full_avg60, + psi.cpu_full_avg300, + psi.cpu_full_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "Memory full:", + psi.memory_full_avg10, + psi.memory_full_avg60, + psi.memory_full_avg300, + psi.memory_full_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "Memory some:", + psi.memory_some_avg10, + psi.memory_some_avg60, + psi.memory_some_avg300, + psi.memory_some_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "IO full:", + psi.io_full_avg10, + psi.io_full_avg60, + psi.io_full_avg300, + psi.io_full_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "IO some:", + psi.io_some_avg10, + psi.io_some_avg60, + psi.io_some_avg300, + psi.io_some_total / 1000); + suc &=3D BOOL_FPRINT(out, PSI_LINE_FORMAT, + "IRQ full:", + psi.irq_full_avg10, + psi.irq_full_avg60, + psi.irq_full_avg300, + psi.irq_full_total / 1000); + } if (cfg.container_path) { suc &=3D BOOL_FPRINT(out, "Container Information (%s):\n", cfg.container= _path); @@ -1017,6 +1066,7 @@ int main(int argc, char **argv) { const struct field_desc *field; int iterations =3D 0; + int psi_ret =3D 0; char keypress; /* Parse command line arguments */ @@ -1054,7 +1104,7 @@ int main(int argc, char **argv) } /* Read PSI statistics */ - read_psi_stats(); + psi_ret =3D read_psi_stats(); /* Get container stats if container path provided */ if (cfg.container_path) @@ -1067,7 +1117,7 @@ int main(int argc, char **argv) sort_tasks(); /* Display results to stdout or log file */ - display_results(); + display_results(psi_ret); /* Check for iterations */ if (cfg.iterations > 0 && ++iterations >=3D cfg.iterations) --=20 2.25.1 From nobody Tue Sep 9 16:39:59 2025 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBC2C241CB7; Sat, 6 Sep 2025 16:15:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175303; cv=none; b=hzMXybNwEGS4IWbpkijHuK1aQDVXtFbe5qLLCxg+WZUyKh9L6Zh0lLcX9UIfui6ZEqBEB96LV/VWBMAopnEUZLpscGaeKHpoRdEMfQOzKZKoZhiOTiFHoR15RVaFJP+lnMqEWpEz2aeIQk+wi95NM0eYIW5XHPyTvU0G+1NxqSk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757175303; c=relaxed/simple; bh=TYB/E2tIkzgU/+Rq74o3mefWv478pIKXjHznT5IMLJc=; h=Date:Message-ID:In-Reply-To:References:Mime-Version:From:To:Cc: Subject:Content-Type; b=GS3IeLj/xuiYWCdWNrx3/C9m/YRjzRa7mPl+RBKpIe01B6Dmqpblo28/jRG2pNYy+F8QOCRz/gXFq4eua6WXe56GdIrqupircMBHYd/bhYtgsswTSfU6GrJihwsF/Sqe1yEGkFoYlyx2nOUVhlPGP0UM5Ow/nb1QlaSekun/tjg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4cJywg6Y88z5PM32; Sun, 07 Sep 2025 00:14:59 +0800 (CST) Received: from xaxapp02.zte.com.cn ([10.88.97.241]) by mse-fl1.zte.com.cn with SMTP id 586GEtTv035356; Sun, 7 Sep 2025 00:14:55 +0800 (+08) (envelope-from fan.yu9@zte.com.cn) Received: from mapi (xaxapp02[null]) by mapi (Zmail) with MAPI id mid32; Sun, 7 Sep 2025 00:14:57 +0800 (CST) Date: Sun, 7 Sep 2025 00:14:57 +0800 (CST) X-Zmail-TransId: 2afa68bc5e01e95-41e9f X-Mailer: Zmail v1.0 Message-ID: <20250907001457696qAqUGGkV1VfEO6OkVMovW@zte.com.cn> In-Reply-To: <20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn> References: 20250907001101305vrTGnXaRNvtmsGkp-Ljk_@zte.com.cn Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 From: To: , , Cc: , , , Subject: =?UTF-8?B?W1BBVENIdjIgbGludXgtbmV4dCA1LzVdIGRvY3M6IHVwZGF0ZSBkZWxheXRvcCBkb2N1bWVudGF0aW9uIGZvciBuZXcgaW50ZXJhY3RpdmUgZmVhdHVyZXM=?= X-MAIL: mse-fl1.zte.com.cn 586GEtTv035356 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: fan.yu9@zte.com.cn X-SPF: None X-SOURCE-IP: 10.5.228.132 unknown Sun, 07 Sep 2025 00:14:59 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 68BC5E03.000/4cJywg6Y88z5PM32 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fan Yu This commit updates the delaytop documentation to reflect the newly added features: 1) Added comprehensive description of interactive keyboard controls 2) Documented all available sort fields 3) Added examples for advanced usage scenarios 4) Included PSI availability note Signed-off-by: Fan Yu Reviewed-by: xu xin --- Documentation/accounting/delay-accounting.rst | 91 ++++++++++++------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/Documentation/accounting/delay-accounting.rst b/Documentation/= accounting/delay-accounting.rst index 8ccc5af5ea1e..7cca536d2c4c 100644 --- a/Documentation/accounting/delay-accounting.rst +++ b/Documentation/accounting/delay-accounting.rst @@ -134,47 +134,72 @@ The above command can be used with -v to get more deb= ug information. After the system starts, use `delaytop` to get the system-wide delay infor= mation, which includes system-wide PSI information and Top-N high-latency tasks. +Note: PSI support requires `CONFIG_PSI=3Dy` and `psi=3D1` for full functio= nality. -`delaytop` supports sorting by CPU latency in descending order by default, -displays the top 20 high-latency tasks by default, and refreshes the laten= cy -data every 2 seconds by default. +`delaytop` is an interactive tool for monitoring system pressure and task = delays. +It supports multiple sorting options, display modes, and real-time keyboar= d controls. -Get PSI information and Top-N tasks delay, since system boot:: +Basic usage with default settings (sorts by CPU delay, shows top 20 tasks,= refreshes every 2 seconds):: bash# ./delaytop - System Pressure Information: (avg10/avg60/avg300/total) - CPU some: 0.0%/ 0.0%/ 0.0%/ 345(ms) + System Pressure Information: (avg10/avg60vg300/total) + CPU some: 0.0%/ 0.0%/ 0.0%/ 106137(ms) CPU full: 0.0%/ 0.0%/ 0.0%/ 0(ms) Memory full: 0.0%/ 0.0%/ 0.0%/ 0(ms) Memory some: 0.0%/ 0.0%/ 0.0%/ 0(ms) - IO full: 0.0%/ 0.0%/ 0.0%/ 65(ms) - IO some: 0.0%/ 0.0%/ 0.0%/ 79(ms) + IO full: 0.0%/ 0.0%/ 0.0%/ 2240(ms) + IO some: 0.0%/ 0.0%/ 0.0%/ 2783(ms) IRQ full: 0.0%/ 0.0%/ 0.0%/ 0(ms) - Top 20 processes (sorted by CPU delay): - PID TGID COMMAND CPU(ms) IO(ms) SWAP(ms) RCL(ms) THR(ms) C= MP(ms) WP(ms) IRQ(ms) - -------------------------------------------------------------------------= --------------------- - 161 161 zombie_memcg_re 1.40 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 130 130 blkcg_punt_bio 1.37 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 444 444 scsi_tmf_0 0.73 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 1280 1280 rsyslogd 0.53 0.04 0.00 0.00 0.00 0= .00 0.00 0.00 - 12 12 ksoftirqd/0 0.47 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 1277 1277 nbd-server 0.44 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 308 308 kworker/2:2-sys 0.41 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 55 55 netns 0.36 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 1187 1187 acpid 0.31 0.03 0.00 0.00 0.00 0= .00 0.00 0.00 - 6184 6184 kworker/1:2-sys 0.24 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 186 186 kaluad 0.24 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 18 18 ksoftirqd/1 0.24 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 185 185 kmpath_rdacd 0.23 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 190 190 kstrp 0.23 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 2759 2759 agetty 0.20 0.03 0.00 0.00 0.00 0= .00 0.00 0.00 - 1190 1190 kworker/0:3-sys 0.19 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 1272 1272 sshd 0.15 0.04 0.00 0.00 0.00 0= .00 0.00 0.00 - 1156 1156 license 0.15 0.11 0.00 0.00 0.00 0= .00 0.00 0.00 - 134 134 md 0.13 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - 6142 6142 kworker/3:2-xfs 0.13 0.00 0.00 0.00 0.00 0= .00 0.00 0.00 - -Dynamic interactive interface of delaytop:: + [o]sort [M]memverbose [q]quit + Top 20 processes (sorted by cpu delay): + PID TGID COMMAND CPU(ms) IO(ms) IRQ(ms) MEM(ms) + ------------------------------------------------------------------------ + 110 110 kworker/15:0H-s 27.91 0.00 0.00 0.00 + 57 57 cpuhp/7 3.18 0.00 0.00 0.00 + 99 99 cpuhp/14 2.97 0.00 0.00 0.00 + 51 51 cpuhp/6 0.90 0.00 0.00 0.00 + 44 44 kworker/4:0H-sy 0.80 0.00 0.00 0.00 + 60 60 ksoftirqd/7 0.74 0.00 0.00 0.00 + 76 76 idle_inject/10 0.31 0.00 0.00 0.00 + 100 100 idle_inject/14 0.30 0.00 0.00 0.00 + 1309 1309 systemsettings 0.29 0.00 0.00 0.00 + 45 45 cpuhp/5 0.22 0.00 0.00 0.00 + 63 63 cpuhp/8 0.20 0.00 0.00 0.00 + 87 87 cpuhp/12 0.18 0.00 0.00 0.00 + 93 93 cpuhp/13 0.17 0.00 0.00 0.00 + 1265 1265 acpid 0.17 0.00 0.00 0.00 + 1552 1552 sshd 0.17 0.00 0.00 0.00 + 2584 2584 sddm-helper 0.16 0.00 0.00 0.00 + 1284 1284 rtkit-daemon 0.15 0.00 0.00 0.00 + 1326 1326 nde-netfilter 0.14 0.00 0.00 0.00 + 27 27 cpuhp/2 0.13 0.00 0.00 0.00 + 631 631 kworker/11:2-rc 0.11 0.00 0.00 0.00 + +Interactive keyboard controls during runtime:: + + o - Select sort field (CPU, IO, IRQ, Memory, etc.) + M - Toggle display mode (Default/Memory Verbose) + q - Quit + +Available sort fields(use -s/--sort or interactive command):: + + cpu(c) - CPU delay + blkio(i) - I/O delay=20 + irq(q) - IRQ delay + mem(m) - Total memory delay + swapin(s) - Swapin delay (memory verbose mode only) + freepages(r) - Freepages reclaim delay (memory verbose mode only) + thrashing(t) - Thrashing delay (memory verbose mode only) + compact(p) - Compaction delay (memory verbose mode only) + wpcopy(w) - Write page copy delay (memory verbose mode only) + +Advanced usage examples:: + + # ./delaytop -s blkio + Sorted by IO delay + + # ./delaytop -s mem -M + Sorted by memory delay in memory verbose mode # ./delaytop -p pid Print delayacct stats --=20 2.25.1