答复: [外部邮件] Re: [PATCH] perf iostat: Do not compute interval deltas a second time
From: Li,Rongqing
Date: Mon Nov 09 2026 - 01:55:57 EST
> -----邮件原件-----
> 发件人: Namhyung Kim <namhyung@xxxxxxxxxx>
> 发送时间: 2026年11月9日 13:26
> 收件人: Li,Rongqing <lirongqing@xxxxxxxxx>
> 抄送: Peter Zijlstra <peterz@xxxxxxxxxxxxx>; Ingo Molnar <mingo@xxxxxxxxxx>;
> Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>; Mark Rutland
> <mark.rutland@xxxxxxx>; Alexander Shishkin
> <alexander.shishkin@xxxxxxxxxxxxxxx>; Jiri Olsa <jolsa@xxxxxxxxxx>; Ian Rogers
> <irogers@xxxxxxxxxx>; Adrian Hunter <adrian.hunter@xxxxxxxxx>; James Clark
> <james.clark@xxxxxxxxxx>; linux-perf-users@xxxxxxxxxxxxxxx;
> linux-kernel@xxxxxxxxxxxxxxx
> 主题: [外部邮件] Re: [PATCH] perf iostat: Do not compute interval deltas a
> second time
>
> On Thu, Nov 05, 2026 at 04:04:29PM +0800, lirongqing wrote:
> > From: Li RongQing <lirongqing@xxxxxxxxx>
> >
> > process_counter_values() now computes deltas directly in evsel->counts
> > for global aggregation too. It saves the current cumulative raw count
> > in prev_raw_counts before iostat prints the interval.
> >
> > Subtracting prev_raw_counts again can therefore underflow the count.
> > Worse, replacing the saved raw count with the interval delta corrupts
> > the baseline used to calculate the next interval.
>
> Can you share example output before and after this change?
>
> Thanks,
> Namhyung
Kernel 7.3 and without this patch:
#perf_before stat --iostat -I 1000 -- dd if=/dev/zero of=/dev/nvme0n1 bs=1M count=8000 oflag=direct
# time port Inbound Read(MB) Inbound Write(MB) Outbound Read(MB) Outbound Write(MB)
1.000646950 0000:03 0 0 0 0
1.000646950 0000:97 0 0 0 0
1.000646950 0000:72 0 0 0 0
1.000646950 0000:b0 0 0 0 0
1.000646950 0000:00 0 0 0 0
1.000646950 0000:00 0 0 0 0
1.000646950 0000:73 0 0 0 0
1.000646950 0000:c9 0 0 0 0
1.000646950 0000:74 0 0 0 0
1.000646950 0000:e2 3427 0 25866 1
1.000646950 0000:00 0 0 0 0
1.000646950 0000:80 0 0 0 0
2.001643938 0000:03 0 0 1 0
2.001643938 0000:97 0 0 0 0
2.001643938 0000:72 0 0 0 0
2.001643938 0000:b0 0 0 0 0
2.001643938 0000:00 0 0 0 0
2.001643938 0000:00 0 0 0 0
2.001643938 0000:73 0 0 0 0
2.001643938 0000:c9 0 0 0 0
2.001643938 0000:74 0 0 0 0
2.001643938 0000:e2 140816099028344 140816099035149 140816098983788 140816099035148 should be overflow
2.001643938 0000:00 0 0 0 140749426818919
2.001643938 0000:80 0 0 0 0
8000+0 records in
8000+0 records out
8388608000 bytes (8.4 GB, 7.8 GiB) copied, 2.26845 s, 3.7 GB/s
2.269193545 0000:03 140933923092740 0 140933923092739 140933923092740
2.269193545 0000:97 0 0 0 0
2.269193545 0000:72 0 0 0 0
2.269193545 0000:b0 0 0 0 0
2.269193545 0000:00 0 0 0 0
2.269193545 0000:00 0 0 0 0
2.269193545 0000:73 0 0 0 0
2.269193545 0000:c9 0 0 0 0
2.269193545 0000:74 0 0 0 0
2.269193545 0000:e2 7789 1 58787 2
2.269193545 0000:00 0 0 0 0
2.269193545 0000:80 0 0 0 0
With this patch
#tools/perf/perf stat --iostat -I 1000 -- dd if=/dev/zero of=/dev/nvme0n1 bs=1M count=8000 oflag=direct
# time port Inbound Read(MB) Inbound Write(MB) Outbound Read(MB) Outbound Write(MB)
1.000654370 0000:03 0 0 1 0
1.000654370 0000:97 0 0 0 0
1.000654370 0000:72 0 0 0 0
1.000654370 0000:b0 0 0 0 0
1.000654370 0000:00 0 0 0 0
1.000654370 0000:00 0 0 0 0
1.000654370 0000:73 0 0 0 0
1.000654370 0000:c9 0 0 0 0
1.000654370 0000:74 0 0 0 0
1.000654370 0000:e2 6916 1 52193 2
1.000654370 0000:00 0 0 0 0
1.000654370 0000:80 0 0 0 0
2.001653075 0000:03 0 0 0 0
2.001653075 0000:97 0 0 0 0
2.001653075 0000:72 0 0 0 0
2.001653075 0000:b0 0 0 0 0
2.001653075 0000:00 0 0 0 0
2.001653075 0000:00 0 0 0 0
2.001653075 0000:73 0 0 0 0
2.001653075 0000:c9 0 0 0 0
2.001653075 0000:74 0 0 0 0
2.001653075 0000:e2 6865 1 51810 2
2.001653075 0000:00 0 0 0 0
2.001653075 0000:80 0 0 0 0
8000+0 records in
8000+0 records out
8388608000 bytes (8.4 GB, 7.8 GiB) copied, 2.27499 s, 3.7 GB/s
2.275740501 0000:03 0 0 0 0
2.275740501 0000:97 0 0 0 0
2.275740501 0000:72 0 0 0 0
2.275740501 0000:b0 0 0 0 0
2.275740501 0000:00 0 0 0 0
2.275740501 0000:00 0 0 0 0
2.275740501 0000:73 0 0 0 0
2.275740501 0000:c9 0 0 0 0
2.275740501 0000:74 0 0 0 0
2.275740501 0000:e2 1774 0 13385 1
2.275740501 0000:00 0 0 0 0
2.275740501 0000:80 0 0 0 0
#
thanks
LiRongQing
>
> >
> > Use the already computed delta and leave prev_raw_counts untouched.
> >
> > Fixes: f976bc6b6bfc ("perf stat: Aggregate events using
> > evsel->stats->aggr")
> > Signed-off-by: Li RongQing <lirongqing@xxxxxxxxx>
> > ---
> > tools/perf/arch/x86/util/iostat.c | 10 +---------
> > 1 file changed, 1 insertion(+), 9 deletions(-)
> >
> > diff --git a/tools/perf/arch/x86/util/iostat.c
> > b/tools/perf/arch/x86/util/iostat.c
> > index 0cf0f93..fac6b4a 100644
> > --- a/tools/perf/arch/x86/util/iostat.c
> > +++ b/tools/perf/arch/x86/util/iostat.c
> > @@ -434,20 +434,12 @@ void iostat_print_metric(struct perf_stat_config
> *config, struct evsel *evsel,
> > struct perf_stat_output_ctx *out) {
> > double iostat_value = 0;
> > - u64 prev_count_val = 0;
> > const char *iostat_metric = iostat_metric_by_idx(evsel->core.idx);
> > u8 die = ((struct iio_root_port *)evsel->priv)->die;
> > struct perf_counts_values *count = perf_counts(evsel->counts, die,
> > 0);
> >
> > if (count && count->run && count->ena) {
> > - if (evsel->prev_raw_counts && !out->force_header) {
> > - struct perf_counts_values *prev_count =
> > - perf_counts(evsel->prev_raw_counts, die, 0);
> > -
> > - prev_count_val = prev_count->val;
> > - prev_count->val = count->val;
> > - }
> > - iostat_value = (count->val - prev_count_val) /
> > + iostat_value = count->val /
> > ((double) count->run / count->ena);
> > }
> > out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN,
> > "%8.0f", iostat_metric,
> > --
> > 2.9.4
> >