[PATCH v2 0/4] perf timechart: Small optimization for backtrace

Namhyung Kim posted 4 patches 3 days, 8 hours ago
tools/perf/builtin-timechart.c | 107 ++++++++++++++++-----------------
1 file changed, 52 insertions(+), 55 deletions(-)
[PATCH v2 0/4] perf timechart: Small optimization for backtrace
Posted by Namhyung Kim 3 days, 8 hours ago
Hello,

I found an issue int timechart backtrace handling during the last review.
The goal is to reduce unnecessary work in generating backtrace string.

v2 changes)
 * fix memory leaks when backtrace is not used
 * copy backtrace when it's used twice

Thanks,
Namhyung


Namhyung Kim (4):
  perf timechart: Don't pass @event to cat_backtrace()
  perf timechart: Generate backtrace only if needed
  perf timechart: Remove unused backtrace in trace_handler
  perf timechart: Remove unnecessary copy of backtrace

 tools/perf/builtin-timechart.c | 107 ++++++++++++++++-----------------
 1 file changed, 52 insertions(+), 55 deletions(-)

-- 
2.54.0.1032.g2f8565e1d1-goog
Re: [PATCH v2 0/4] perf timechart: Small optimization for backtrace
Posted by Ian Rogers 3 days, 7 hours ago
On Thu, Jun 4, 2026 at 2:49 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> Hello,
>
> I found an issue int timechart backtrace handling during the last review.
> The goal is to reduce unnecessary work in generating backtrace string.
>
> v2 changes)
>  * fix memory leaks when backtrace is not used
>  * copy backtrace when it's used twice

Hi Namhyung,

thanks for cleaning this up and the fixes! Running a build of:
$ make -C tools/perf O=/tmp/perf DEBUG=1
EXTRA_CFLAGS="-fno-omit-frame-pointer -O0 -g -fsanitize=address" clean
all

I get an error but the test harness makes it look like the test is
passing (I added set -x to the test and removed the "> /dev/null
2>&1"):
```
$ sudo /tmp/perf/perf test -vv timechart
136: perf timechart tests
136: perf timechart tests:
---- start ----
test child forked, pid 937043
+ err=0
++ mktemp /tmp/__perf_timechart_test.perf.data.XXXXX
+ perfdata=/tmp/__perf_timechart_test.perf.data.cXMvK
++ mktemp /tmp/__perf_timechart_test.output.XXXXX.svg
+ output=/tmp/__perf_timechart_test.output.xZXfy.svg
+ trap trap_cleanup EXIT TERM INT
+ perf check feature -q libtraceevent
+ test_timechart
+ echo 'Basic perf timechart test'
Basic perf timechart test
+ perf timechart record -o /tmp/__perf_timechart_test.perf.data.cXMvK true
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 4.135 MB
/tmp/__perf_timechart_test.perf.data.cXMvK (748 samples) ]

=================================================================
==937049==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 136 byte(s) in 1 object(s) allocated from:
   #0 0x7fd211119a23 in calloc
../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:74
   #1 0x555c44044416 in timechart__record ~/linux/tools/perf/builtin-timech
art.c:1895
   #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
c:2073
   #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
   #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
98
   #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
   #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
   #7 0x7fd206e29f76 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
   #8 0x7fffcf8a352a  ([stack]+0x2052a)

Direct leak of 10 byte(s) in 2 object(s) allocated from:
   #0 0x7fd211113e20 in strdup
../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
   #1 0x555c440444a1 in timechart__record ~/linux/tools/perf/builtin-timech
art.c:1902
   #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
c:2073
   #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
   #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
98
   #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
   #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
   #7 0x7fd206e29f76 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
   #8 0x7fffcf8a352a  ([stack]+0x2052a)

Indirect leak of 44 byte(s) in 4 object(s) allocated from:
   #0 0x7fd211113e20 in strdup
../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
   #1 0x555c440445ef in timechart__record ~/linux/tools/perf/builtin-timech
art.c:1908
   #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
c:2073
   #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
   #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
98
   #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
   #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
   #7 0x7fd206e29f76 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
   #8 0x7fffcf8a352a  ([stack]+0x2052a)

Indirect leak of 41 byte(s) in 4 object(s) allocated from:
   #0 0x7fd211113e20 in strdup
../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
   #1 0x555c44044696 in timechart__record ~/linux/tools/perf/builtin-timech
art.c:1911
   #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
c:2073
   #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
   #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
98
   #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
   #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
   #7 0x7fd206e29f76 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
   #8 0x7fffcf8a352a  ([stack]+0x2052a)

Indirect leak of 11 byte(s) in 4 object(s) allocated from:
   #0 0x7fd211113e20 in strdup
../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
   #1 0x555c440444a1 in timechart__record ~/linux/tools/perf/builtin-timech
art.c:1902
   #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
c:2073
   #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
   #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
98
   #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
   #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
   #7 0x7fd206e29f76 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
   #8 0x7fffcf8a352a  ([stack]+0x2052a)

SUMMARY: AddressSanitizer: 242 byte(s) leaked in 15 allocation(s).
+ echo 'Basic perf timechart test [Skipped: perf timechart record
failed (permissions/events?)]'
Basic perf timechart test [Skipped: perf timechart record failed
(permissions/events?)]
+ return
+ cleanup
+ rm -f /tmp/__perf_timechart_test.perf.data.cXMvK
+ rm -f /tmp/__perf_timechart_test.output.xZXfy.svg
+ trap - EXIT TERM INT
+ exit 0
---- end(0) ----
136: perf timechart tests
: Ok
```

It was this test that I was trying to make leak sanitizer clean when
doing my fixes.

Thanks,
Ian

> Thanks,
> Namhyung
>
>
> Namhyung Kim (4):
>   perf timechart: Don't pass @event to cat_backtrace()
>   perf timechart: Generate backtrace only if needed
>   perf timechart: Remove unused backtrace in trace_handler
>   perf timechart: Remove unnecessary copy of backtrace
>
>  tools/perf/builtin-timechart.c | 107 ++++++++++++++++-----------------
>  1 file changed, 52 insertions(+), 55 deletions(-)
>
> --
> 2.54.0.1032.g2f8565e1d1-goog
>
Re: [PATCH v2 0/4] perf timechart: Small optimization for backtrace
Posted by Namhyung Kim 3 days, 7 hours ago
Hi Ian,

On Thu, Jun 04, 2026 at 03:38:05PM -0700, Ian Rogers wrote:
> On Thu, Jun 4, 2026 at 2:49 PM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > Hello,
> >
> > I found an issue int timechart backtrace handling during the last review.
> > The goal is to reduce unnecessary work in generating backtrace string.
> >
> > v2 changes)
> >  * fix memory leaks when backtrace is not used
> >  * copy backtrace when it's used twice
> 
> Hi Namhyung,
> 
> thanks for cleaning this up and the fixes! Running a build of:
> $ make -C tools/perf O=/tmp/perf DEBUG=1
> EXTRA_CFLAGS="-fno-omit-frame-pointer -O0 -g -fsanitize=address" clean
> all
> 
> I get an error but the test harness makes it look like the test is
> passing (I added set -x to the test and removed the "> /dev/null
> 2>&1"):
> ```
> $ sudo /tmp/perf/perf test -vv timechart
> 136: perf timechart tests
> 136: perf timechart tests:
> ---- start ----
> test child forked, pid 937043
> + err=0
> ++ mktemp /tmp/__perf_timechart_test.perf.data.XXXXX
> + perfdata=/tmp/__perf_timechart_test.perf.data.cXMvK
> ++ mktemp /tmp/__perf_timechart_test.output.XXXXX.svg
> + output=/tmp/__perf_timechart_test.output.xZXfy.svg
> + trap trap_cleanup EXIT TERM INT
> + perf check feature -q libtraceevent
> + test_timechart
> + echo 'Basic perf timechart test'
> Basic perf timechart test
> + perf timechart record -o /tmp/__perf_timechart_test.perf.data.cXMvK true
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 4.135 MB
> /tmp/__perf_timechart_test.perf.data.cXMvK (748 samples) ]
> 
> =================================================================
> ==937049==ERROR: LeakSanitizer: detected memory leaks
> 
> Direct leak of 136 byte(s) in 1 object(s) allocated from:
>    #0 0x7fd211119a23 in calloc
> ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:74
>    #1 0x555c44044416 in timechart__record ~/linux/tools/perf/builtin-timech
> art.c:1895
>    #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
> c:2073
>    #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
>    #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
> 98
>    #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
>    #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
>    #7 0x7fd206e29f76 in __libc_start_call_main
> ../sysdeps/nptl/libc_start_call_main.h:58
>    #8 0x7fffcf8a352a  ([stack]+0x2052a)
> 
> Direct leak of 10 byte(s) in 2 object(s) allocated from:
>    #0 0x7fd211113e20 in strdup
> ../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
>    #1 0x555c440444a1 in timechart__record ~/linux/tools/perf/builtin-timech
> art.c:1902
>    #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
> c:2073
>    #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
>    #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
> 98
>    #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
>    #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
>    #7 0x7fd206e29f76 in __libc_start_call_main
> ../sysdeps/nptl/libc_start_call_main.h:58
>    #8 0x7fffcf8a352a  ([stack]+0x2052a)
> 
> Indirect leak of 44 byte(s) in 4 object(s) allocated from:
>    #0 0x7fd211113e20 in strdup
> ../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
>    #1 0x555c440445ef in timechart__record ~/linux/tools/perf/builtin-timech
> art.c:1908
>    #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
> c:2073
>    #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
>    #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
> 98
>    #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
>    #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
>    #7 0x7fd206e29f76 in __libc_start_call_main
> ../sysdeps/nptl/libc_start_call_main.h:58
>    #8 0x7fffcf8a352a  ([stack]+0x2052a)
> 
> Indirect leak of 41 byte(s) in 4 object(s) allocated from:
>    #0 0x7fd211113e20 in strdup
> ../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
>    #1 0x555c44044696 in timechart__record ~/linux/tools/perf/builtin-timech
> art.c:1911
>    #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
> c:2073
>    #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
>    #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
> 98
>    #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
>    #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
>    #7 0x7fd206e29f76 in __libc_start_call_main
> ../sysdeps/nptl/libc_start_call_main.h:58
>    #8 0x7fffcf8a352a  ([stack]+0x2052a)
> 
> Indirect leak of 11 byte(s) in 4 object(s) allocated from:
>    #0 0x7fd211113e20 in strdup
> ../../../../src/libsanitizer/asan/asan_interceptors.cpp:593
>    #1 0x555c440444a1 in timechart__record ~/linux/tools/perf/builtin-timech
> art.c:1902
>    #2 0x555c44046c19 in cmd_timechart ~/linux/tools/perf/builtin-timechart.
> c:2073
>    #3 0x555c440828a4 in run_builtin ~/linux/tools/perf/perf.c:348
>    #4 0x555c44082d42 in handle_internal_command ~/linux/tools/perf/perf.c:3
> 98
>    #5 0x555c44083110 in run_argv ~/linux/tools/perf/perf.c:442
>    #6 0x555c44083667 in main ~/linux/tools/perf/perf.c:549
>    #7 0x7fd206e29f76 in __libc_start_call_main
> ../sysdeps/nptl/libc_start_call_main.h:58
>    #8 0x7fffcf8a352a  ([stack]+0x2052a)
> 
> SUMMARY: AddressSanitizer: 242 byte(s) leaked in 15 allocation(s).
> + echo 'Basic perf timechart test [Skipped: perf timechart record
> failed (permissions/events?)]'
> Basic perf timechart test [Skipped: perf timechart record failed
> (permissions/events?)]
> + return
> + cleanup
> + rm -f /tmp/__perf_timechart_test.perf.data.cXMvK
> + rm -f /tmp/__perf_timechart_test.output.xZXfy.svg
> + trap - EXIT TERM INT
> + exit 0
> ---- end(0) ----
> 136: perf timechart tests
> : Ok
> ```
> 
> It was this test that I was trying to make leak sanitizer clean when
> doing my fixes.

I think these leaks are pre-existing.  I don't see where it frees cpu
samples and other events.  I'll take a look and send a fix separately.

Thanks,
Namhyung