perf tools: Store CPU cache details under perf data
Jiri Olsa
reviewercover perf tools: Store CPU cache details under perf data
hi,
adding support to store CPU cache details under perf data.
$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
Plus some libapi additions.
Also available in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/cache
thanks,
jirka
---
Jiri Olsa (5):
tools lib api: Add debug output support
tools lib api fs: Move filename__read_str into api/fs/fs.c tools lib api fs: Add sysfs__read_str function perf tools: Initialize libapi debug output
perf tools: Add perf data cache feature
tools/lib/api/Build | 1 + tools/lib/api/Makefile | 1 + tools/lib/api/debug-internal.h | 20 +++++++++ tools/lib/api/debug.c | 28 +++++++++++++ tools/lib/api/debug.h | 10 +++++ tools/lib/api/fs/fs.c | 64 +++++++++++++++++++++++++++++ tools/lib/api/fs/fs.h | 3 ++ tools/perf/perf.c | 2 + tools/perf/util/debug.c | 21 ++++++++++ tools/perf/util/debug.h | 1 + tools/perf/util/env.c | 13 ++++++ tools/perf/util/env.h | 15 +++++++ tools/perf/util/header.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + tools/perf/util/trace-event.c | 1 + tools/perf/util/util.c | 48 ---------------------- tools/perf/util/util.h | 1 - 17 files changed, 446 insertions(+), 49 deletions(-) create mode 100644 tools/lib/api/debug-internal.h create mode 100644 tools/lib/api/debug.c create mode 100644 tools/lib/api/debug.h
Jiri Olsa
reviewerPATCH 1/5 tools lib api: Add debug output support
Adding support for warning/info/debug output
within libapi code. Adding following macros:
pr_warning(fmt, ...)
pr_info(fmt, ...)
pr_debug(fmt, ...)
Also adding libapi_set_print function to set
above functions. This will be used in perf
to set standard debug handlers for libapi.
Adding 2 header files:
debug.h
- to be used outside libapi, contains
libapi_set_print interface
debug-internal.h
- to be used within libapi, contains
pr_warning/pr_info/pr_debug definitions
--- tools/lib/api/Build | 1 + tools/lib/api/Makefile | 1 + tools/lib/api/debug-internal.h | 20 ++++++++++++++++++++ tools/lib/api/debug.c | 28 ++++++++++++++++++++++++++++ tools/lib/api/debug.h | 10 ++++++++++ 5 files changed, 60 insertions(+) create mode 100644 tools/lib/api/debug-internal.h create mode 100644 tools/lib/api/debug.c create mode 100644 tools/lib/api/debug.h
tools/lib/api/Build +1 -0
@@ -1,3 +1,4 @@ libapi-y += fd/ libapi-y += fs/ libapi-y += cpu.o +libapi-y += debug.o
tools/lib/api/Makefile +1 -0
@@ -18,6 +18,7 @@ LIBFILE = $(OUTPUT)libapi.a CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS += -I$(srctree)/tools/lib/api RM = rm -f
tools/lib/api/debug-internal.h new file +20 -0
@@ -0,0 +1,20 @@ +#ifndef __API_DEBUG_INTERNAL_H__ +#define __API_DEBUG_INTERNAL_H__ + +#include "debug.h" + +#define __pr (func, fmt, ...) \ +do { \ + if ((func)) \ + (func)("libapi: " fmt, ##__VA_ARGS__); \ +} while (0) + +extern libapi_print_fn_t __pr_warning; +extern libapi_print_fn_t __pr_info; +extern libapi_print_fn_t __pr_debug; + +#define pr_warning (fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__) +#define pr_info (fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__) +#define pr_debug (fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__) + +#endif /* __API_DEBUG_INTERNAL_H__ */
tools/lib/api/debug.c new file +28 -0
@@ -0,0 +1,28 @@ +#include <stdio.h> +#include <stdarg.h> +#include "debug.h" +#include "debug-internal.h" + +static int __base_pr (const char *format, ...) +{ +va_list args; +int err; + +va_start (args, format); + err =vfprintf (stderr, format, args); +va_end (args); +return err; +} + +libapi_print_fn_t __pr_warning = __base_pr; +libapi_print_fn_t __pr_info = __base_pr; +libapi_print_fn_t __pr_debug; + +void libapi_set_print (libapi_print_fn_t warn, +libapi_print_fn_t info, +libapi_print_fn_t debug) +{ + __pr_warning = warn; + __pr_info = info; + __pr_debug = debug; +}
tools/lib/api/debug.h new file +10 -0
@@ -0,0 +1,10 @@ +#ifndef __API_DEBUG_H__ +#define __API_DEBUG_H__ + +typedef int (*libapi_print_fn_t )(const char *, ...); + +void libapi_set_print (libapi_print_fn_t warn, +libapi_print_fn_t info, +libapi_print_fn_t debug); + +#endif /* __API_DEBUG_H__ */
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] tools lib api: Add debug output support
tools lib api: Add debug output support
Commit-ID: 975f14fa8f2996604f248552eee4403def34bf5e Gitweb: http://git.kernel.org/tip/975f14fa8f2996604f248552eee4403def34bf5e Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Feb 2016 17:03:42 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Feb 2016 17:12:56 -0300
tools lib api: Add debug output support
Adding support for warning/info/debug output within libapi code. Adding following macros:
pr_warning(fmt, ...)
pr_info(fmt, ...)
pr_debug(fmt, ...)
Also adding libapi_set_print function to set above functions. This will be used in perf to set standard debug handlers for libapi.
Adding 2 header files:
debug.h
- to be used outside libapi, contains
libapi_set_print interface
debug-internal.h
- to be used within libapi, contains
pr_warning/pr_info/pr_debug definitions
--- tools/lib/api/Build | 1 + tools/lib/api/Makefile | 1 + tools/lib/api/debug-internal.h | 20 ++++++++++++++++++++ tools/lib/api/debug.c | 28 ++++++++++++++++++++++++++++ tools/lib/api/debug.h | 10 ++++++++++ 5 files changed, 60 insertions(+)
tools/lib/api/Build +1 -0
@@ -1,3 +1,4 @@ libapi-y += fd/ libapi-y += fs/ libapi-y += cpu.o +libapi-y += debug.o
tools/lib/api/Makefile +1 -0
@@ -18,6 +18,7 @@ LIBFILE = $(OUTPUT)libapi.a CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS += -I$(srctree)/tools/lib/api RM = rm -f
tools/lib/api/debug-internal.h new file +20 -0
@@ -0,0 +1,20 @@ +#ifndef __API_DEBUG_INTERNAL_H__ +#define __API_DEBUG_INTERNAL_H__ + +#include "debug.h" + +#define __pr (func, fmt, ...) \ +do { \ + if ((func)) \ + (func)("libapi: " fmt, ##__VA_ARGS__); \ +} while (0) + +extern libapi_print_fn_t __pr_warning; +extern libapi_print_fn_t __pr_info; +extern libapi_print_fn_t __pr_debug; + +#define pr_warning (fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__) +#define pr_info (fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__) +#define pr_debug (fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__) + +#endif /* __API_DEBUG_INTERNAL_H__ */
tools/lib/api/debug.c new file +28 -0
@@ -0,0 +1,28 @@ +#include <stdio.h> +#include <stdarg.h> +#include "debug.h" +#include "debug-internal.h" + +static int __base_pr (const char *format, ...) +{ +va_list args; +int err; + +va_start (args, format); + err =vfprintf (stderr, format, args); +va_end (args); +return err; +} + +libapi_print_fn_t __pr_warning = __base_pr; +libapi_print_fn_t __pr_info = __base_pr; +libapi_print_fn_t __pr_debug; + +void libapi_set_print (libapi_print_fn_t warn, +libapi_print_fn_t info, +libapi_print_fn_t debug) +{ + __pr_warning = warn; + __pr_info = info; + __pr_debug = debug; +}
tools/lib/api/debug.h new file +10 -0
@@ -0,0 +1,10 @@ +#ifndef __API_DEBUG_H__ +#define __API_DEBUG_H__ + +typedef int (*libapi_print_fn_t )(const char *, ...); + +void libapi_set_print (libapi_print_fn_t warn, +libapi_print_fn_t info, +libapi_print_fn_t debug); + +#endif /* __API_DEBUG_H__ */
Jiri Olsa
reviewerPATCH 2/5 tools lib api fs: Move filename__read_str into api/fs/fs.c
In reply to Jiri OlsaWe already moved similar functions in here,
also it'll be useful for sysfs__read_str
addition in following patch.
--- tools/lib/api/fs/fs.c | 51 +++++++++++++++++++++++++++++++++++++++++++ tools/lib/api/fs/fs.h | 2 ++ tools/perf/util/trace-event.c | 1 + tools/perf/util/util.c | 48 ---------------------------------------- tools/perf/util/util.h | 1 - 5 files changed, 54 insertions(+), 49 deletions(-)
tools/lib/api/fs/fs.c +51 -0
@@ -13,6 +13,7 @@#include <sys/mount.h> #include "fs.h" +#include "debug-internal.h" #define _STR (x) #x#define STR (x) _STR(x)
@@ -300,6 +301,56 @@ int filename__read_ull(const char *filename, unsigned long long *value)return err; } +#define STRERR_BUFSIZE 128/* For the buffer size of strerror_r */ + +int filename__read_str (const char *filename,char **buf,size_t *sizep) +{ +size_t size =0 , alloc_size =0 ; +void *bf =NULL , *nbf; +int fd, n, err =0 ; +char sbuf[STRERR_BUFSIZE ]; + + fd =open (filename,O_RDONLY ); +if (fd <0 ) +return -errno; + +do { +if (size == alloc_size) { + alloc_size +=BUFSIZ ; + nbf =realloc (bf, alloc_size); +if (!nbf) { + err = -ENOMEM ; +break ; + } + + bf = nbf; + } + + n =read (fd, bf + size, alloc_size - size); +if (n <0 ) { +if (size) { +pr_warning ("read failed %d: %s\n" , errno, +strerror_r (errno, sbuf,sizeof (sbuf))); + err =0 ; + }else + err = -errno; + +break ; + } + + size += n; + }while (n >0 ); + +if (!err) { + *sizep = size; + *buf = bf; + }else +free (bf); + +close (fd); +return err; +} +int sysfs__read_ull (const char *entry,unsigned long long *value) {char path[PATH_MAX ];
tools/lib/api/fs/fs.h +2 -0
@@ -2,6 +2,7 @@#define __API_FS__#include <stdbool.h> +#include <unistd.h> /* * On most systems <limits.h> would have given us this, but not on some systems
@@ -26,6 +27,7 @@ FS(tracefs)int filename__read_int (const char *filename,int *value);int filename__read_ull (const char *filename,unsigned long long *value); +int filename__read_str (const char *filename,char **buf,size_t *sizep);int sysctl__read_int (const char *sysctl,int *value);int sysfs__read_int (const char *entry,int *value);
tools/perf/util/trace-event.c +1 -0
@@ -10,6 +10,7 @@#include <linux/err.h> #include <traceevent/event-parse.h> #include <api/fs/tracing_path.h> +#include <api/fs/fs.h> #include "trace-event.h" #include "machine.h" #include "util.h"
tools/perf/util/util.c +0 -48
54 lines not on this page · raw message
tools/perf/util/util.h +0 -1
@@ -303,7 +303,6 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, bool show_sym, bool unwind_inlines);void free_srcline (char *srcline); -int filename__read_str (const char *filename,char **buf,size_t *sizep);int perf_event_paranoid (void );void mem_bswap_64 (void *src,int byte_size);
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] tools lib api fs: Adopt filename__read_str from perf
tools lib api fs: Adopt filename__read_str from perf
Commit-ID: 607bfbd7ffc60156ae0831c917497dc91a57dd8d Gitweb: http://git.kernel.org/tip/607bfbd7ffc60156ae0831c917497dc91a57dd8d Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Feb 2016 17:03:43 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Feb 2016 17:12:56 -0300
tools lib api fs: Adopt filename__read_str from perf
We already moved similar functions in here, also it'll be useful for sysfs__read_str addition in following patch.
--- tools/lib/api/fs/fs.c | 51 +++++++++++++++++++++++++++++++++++++++++++ tools/lib/api/fs/fs.h | 2 ++ tools/perf/util/trace-event.c | 1 + tools/perf/util/util.c | 48 ---------------------------------------- tools/perf/util/util.h | 1 - 5 files changed, 54 insertions(+), 49 deletions(-)
tools/lib/api/fs/fs.c +51 -0
@@ -13,6 +13,7 @@#include <sys/mount.h> #include "fs.h" +#include "debug-internal.h" #define _STR (x) #x#define STR (x) _STR(x)
@@ -300,6 +301,56 @@ int filename__read_ull(const char *filename, unsigned long long *value)return err; } +#define STRERR_BUFSIZE 128/* For the buffer size of strerror_r */ + +int filename__read_str (const char *filename,char **buf,size_t *sizep) +{ +size_t size =0 , alloc_size =0 ; +void *bf =NULL , *nbf; +int fd, n, err =0 ; +char sbuf[STRERR_BUFSIZE ]; + + fd =open (filename,O_RDONLY ); +if (fd <0 ) +return -errno; + +do { +if (size == alloc_size) { + alloc_size +=BUFSIZ ; + nbf =realloc (bf, alloc_size); +if (!nbf) { + err = -ENOMEM ; +break ; + } + + bf = nbf; + } + + n =read (fd, bf + size, alloc_size - size); +if (n <0 ) { +if (size) { +pr_warning ("read failed %d: %s\n" , errno, +strerror_r (errno, sbuf,sizeof (sbuf))); + err =0 ; + }else + err = -errno; + +break ; + } + + size += n; + }while (n >0 ); + +if (!err) { + *sizep = size; + *buf = bf; + }else +free (bf); + +close (fd); +return err; +} +int sysfs__read_ull (const char *entry,unsigned long long *value) {char path[PATH_MAX ];
tools/lib/api/fs/fs.h +2 -0
@@ -2,6 +2,7 @@#define __API_FS__#include <stdbool.h> +#include <unistd.h> /* * On most systems <limits.h> would have given us this, but not on some systems
@@ -26,6 +27,7 @@ FS(tracefs)int filename__read_int (const char *filename,int *value);int filename__read_ull (const char *filename,unsigned long long *value); +int filename__read_str (const char *filename,char **buf,size_t *sizep);int sysctl__read_int (const char *sysctl,int *value);int sysfs__read_int (const char *entry,int *value);
tools/perf/util/trace-event.c +1 -0
@@ -10,6 +10,7 @@#include <linux/err.h> #include <traceevent/event-parse.h> #include <api/fs/tracing_path.h> +#include <api/fs/fs.h> #include "trace-event.h" #include "machine.h" #include "util.h"
tools/perf/util/util.c +0 -48
54 lines not on this page · raw message
tools/perf/util/util.h +0 -1
@@ -303,7 +303,6 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, bool show_sym, bool unwind_inlines);void free_srcline (char *srcline); -int filename__read_str (const char *filename,char **buf,size_t *sizep);int perf_event_paranoid (void );void mem_bswap_64 (void *src,int byte_size);
Jiri Olsa
reviewerPATCH 3/5 tools lib api fs: Add sysfs__read_str function
In reply to Jiri OlsaAdding sysfs__read_str function to ease up reading string files from sysfs. New interface is:
int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
--- tools/lib/api/fs/fs.c | 13 +++++++++++++ tools/lib/api/fs/fs.h | 1 + 2 files changed, 14 insertions(+)
tools/lib/api/fs/fs.c +13 -0
@@ -377,6 +377,19 @@ int sysfs__read_int(const char *entry, int *value)return filename__read_int (path, value); } +int sysfs__read_str (const char *entry,char **buf,size_t *sizep) +{ +char path[PATH_MAX ]; +const char *sysfs =sysfs__mountpoint (); + +if (!sysfs) +return -1 ; + +snprintf (path,sizeof (path),"%s/%s" , sysfs, entry); + +return filename__read_str (path, buf, sizep); +} +int sysctl__read_int (const char *sysctl,int *value) {char path[PATH_MAX ];
tools/lib/api/fs/fs.h +1 -0
@@ -32,4 +32,5 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep);int sysctl__read_int (const char *sysctl,int *value);int sysfs__read_int (const char *entry,int *value);int sysfs__read_ull (const char *entry,unsigned long long *value); +int sysfs__read_str (const char *entry,char **buf,size_t *sizep);#endif /* __API_FS__ */
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] tools lib api fs: Add sysfs__read_str function
tools lib api fs: Add sysfs__read_str function
Commit-ID: 51c0396c600f49de9c3ff8f6fd83055de3709c3d Gitweb: http://git.kernel.org/tip/51c0396c600f49de9c3ff8f6fd83055de3709c3d Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Feb 2016 17:03:44 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Feb 2016 17:12:57 -0300
tools lib api fs: Add sysfs__read_str function
Adding sysfs__read_str function to ease up reading string files from sysfs. New interface is:
int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
--- tools/lib/api/fs/fs.c | 13 +++++++++++++ tools/lib/api/fs/fs.h | 1 + 2 files changed, 14 insertions(+)
tools/lib/api/fs/fs.c +13 -0
@@ -377,6 +377,19 @@ int sysfs__read_int(const char *entry, int *value)return filename__read_int (path, value); } +int sysfs__read_str (const char *entry,char **buf,size_t *sizep) +{ +char path[PATH_MAX ]; +const char *sysfs =sysfs__mountpoint (); + +if (!sysfs) +return -1 ; + +snprintf (path,sizeof (path),"%s/%s" , sysfs, entry); + +return filename__read_str (path, buf, sizep); +} +int sysctl__read_int (const char *sysctl,int *value) {char path[PATH_MAX ];
tools/lib/api/fs/fs.h +1 -0
@@ -32,4 +32,5 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep);int sysctl__read_int (const char *sysctl,int *value);int sysfs__read_int (const char *entry,int *value);int sysfs__read_ull (const char *entry,unsigned long long *value); +int sysfs__read_str (const char *entry,char **buf,size_t *sizep);#endif /* __API_FS__ */
Jiri Olsa
reviewerPATCH 4/5 perf tools: Initialize libapi debug output
In reply to Jiri OlsaSetting libapi debug output functions
to use perf functions.
--- tools/perf/perf.c | 2 ++ tools/perf/util/debug.c | 21 +++++++++++++++++++++ tools/perf/util/debug.h | 1 + 3 files changed, 24 insertions(+)
tools/perf/perf.c +2 -0
@@ -613,6 +613,8 @@ int main(int argc, const char **argv)*/ pthread__block_sigwinch (); +perf_debug_setup (); +while (1 ) {static int done_help;int was_alias =run_argv (&argc, &argv);
tools/perf/util/debug.c +21 -0
@@ -5,6 +5,7 @@#include <string.h> #include <stdarg.h> #include <stdio.h> +#include <api/debug.h> #include "cache.h" #include "color.h"
@@ -192,3 +193,23 @@ int perf_debug_option(const char *str)free (s);return 0 ; } + +#define FUNC (__n, __l) \ +static int pr_ ## __n ## _func(const char *fmt, ...) \ +{ \ + va_list args; \ + int ret; \ + \ + va_start(args, fmt); \ + ret = _eprintf(__l, verbose, fmt, args); \ + va_end(args); \ + return ret; \ +} + +FUNC (warning,0 ); +FUNC (debug,1 ); + +void perf_debug_setup (void ) +{ +libapi_set_print (pr_warning_func, pr_warning_func, pr_debug_func); +}
tools/perf/util/debug.h +1 -0
@@ -53,5 +53,6 @@ int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__(int veprintf (int level,int var,const char *fmt,va_list args);int perf_debug_option (const char *str); +void perf_debug_setup (void );#endif /* __PERF_DEBUG_H */
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Initialize libapi debug output
perf tools: Initialize libapi debug output
Commit-ID: dd629cc0975349c99d5483402bca1ef16313c209 Gitweb: http://git.kernel.org/tip/dd629cc0975349c99d5483402bca1ef16313c209 Author: Jiri Olsa <[email protected]> AuthorDate: Sun, 14 Feb 2016 17:03:45 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Feb 2016 17:12:59 -0300
perf tools: Initialize libapi debug output
Setting libapi debug output functions to use perf functions.
--- tools/perf/perf.c | 2 ++ tools/perf/util/debug.c | 21 +++++++++++++++++++++ tools/perf/util/debug.h | 1 + 3 files changed, 24 insertions(+)
tools/perf/perf.c +2 -0
@@ -613,6 +613,8 @@ int main(int argc, const char **argv)*/ pthread__block_sigwinch (); +perf_debug_setup (); +while (1 ) {static int done_help;int was_alias =run_argv (&argc, &argv);
tools/perf/util/debug.c +21 -0
@@ -5,6 +5,7 @@#include <string.h> #include <stdarg.h> #include <stdio.h> +#include <api/debug.h> #include "cache.h" #include "color.h"
@@ -187,3 +188,23 @@ int perf_debug_option(const char *str)free (s);return 0 ; } + +#define DEBUG_WRAPPER (__n, __l) \ +static int pr_ ## __n ## _wrapper(const char *fmt, ...) \ +{ \ + va_list args; \ + int ret; \ + \ + va_start(args, fmt); \ + ret = veprintf(__l, verbose, fmt, args); \ + va_end(args); \ + return ret; \ +} + +DEBUG_WRAPPER (warning,0 ); +DEBUG_WRAPPER (debug,1 ); + +void perf_debug_setup (void ) +{ +libapi_set_print (pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper); +}
tools/perf/util/debug.h +1 -0
@@ -53,5 +53,6 @@ int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__(int veprintf (int level,int var,const char *fmt,va_list args);int perf_debug_option (const char *str); +void perf_debug_setup (void );#endif /* __PERF_DEBUG_H */
Jiri Olsa
reviewerPATCH 5/5 perf tools: Add perf data cache feature
In reply to Jiri OlsaStoring CPU cache details under perf data. It's stored as new HEADER_CACHE feature and it's displayed under header info with -I option:
$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
All distinct caches are stored/displayed.
--- tools/perf/util/env.c | 13 +++ tools/perf/util/env.h | 15 +++ tools/perf/util/header.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 4 files changed, 294 insertions(+)
tools/perf/util/env.c +13 -0
@@ -6,6 +6,8 @@ struct perf_env perf_env;void perf_env__exit (struct perf_env *env) { +int i; +zfree (&env->hostname);zfree (&env->os_release);zfree (&env->version);
@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)zfree (&env->numa_nodes);zfree (&env->pmu_mappings);zfree (&env->cpu); + +for (i =0 ; i < env->caches_cnt; i++) +cache_level__free (&env->caches[i]); +zfree (&env->caches); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env) env->nr_cpus_avail = nr_cpus;return 0 ; } + +void cache_level__free (struct cache_level *cache) +{ +free (cache->type); +free (cache->map); +free (cache->size); +}
tools/perf/util/env.h +15 -0
@@ -1,11 +1,23 @@ #ifndef __PERF_ENV_H #define __PERF_ENV_H +#include <linux/types.h> + struct cpu_topology_map { int socket_id; int core_id; }; +struct cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + struct perf_env { char *hostname; char *os_release;
@@ -31,6 +43,8 @@ struct perf_env {char *numa_nodes;char *pmu_mappings;struct cpu_topology_map *cpu; +struct cache_level *caches; +int caches_cnt; };extern struct perf_env perf_env;
@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);int perf_env__read_cpu_topology_map (struct perf_env *env); +void cache_level__free (struct cache_level *cache);#endif /* __PERF_ENV_H */
tools/perf/util/header.c +265 -0
295 lines not on this page · raw message
tools/perf/util/header.h +1 -0
@@ -32,6 +32,7 @@ enum {HEADER_GROUP_DESC ,HEADER_AUXTRACE ,HEADER_STAT , +HEADER_CACHE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.4.3
PATCH v2 5/5 perf tools: Add perf data cache feature
Quoted 4 lines · Jiri Olsa
Storing CPU cache details under perf data. It's stored as new
HEADER_CACHEfeature and it's displayed under header info with -I option:
Quoted 12 lines
$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
changing the output based on Ingo's comment
v2 attached, the rest of the patchset stays
my perf/cache branch is updated
thanks,
jirka
---
Storing CPU cache details under perf data. It's stored as new HEADER_CACHE feature and it's displayed under header info with -I option:
$ perf report --header-only -I ... # CPU cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
All distinct caches are stored/displayed.
--- tools/perf/util/env.c | 13 +++ tools/perf/util/env.h | 15 +++ tools/perf/util/header.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 4 files changed, 294 insertions(+)
tools/perf/util/env.c +13 -0
@@ -6,6 +6,8 @@ struct perf_env perf_env;void perf_env__exit (struct perf_env *env) { +int i; +zfree (&env->hostname);zfree (&env->os_release);zfree (&env->version);
@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)zfree (&env->numa_nodes);zfree (&env->pmu_mappings);zfree (&env->cpu); + +for (i =0 ; i < env->caches_cnt; i++) +cache_level__free (&env->caches[i]); +zfree (&env->caches); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env) env->nr_cpus_avail = nr_cpus;return 0 ; } + +void cache_level__free (struct cache_level *cache) +{ +free (cache->type); +free (cache->map); +free (cache->size); +}
tools/perf/util/env.h +15 -0
@@ -1,11 +1,23 @@ #ifndef __PERF_ENV_H #define __PERF_ENV_H +#include <linux/types.h> + struct cpu_topology_map { int socket_id; int core_id; }; +struct cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + struct perf_env { char *hostname; char *os_release;
@@ -31,6 +43,8 @@ struct perf_env {char *numa_nodes;char *pmu_mappings;struct cpu_topology_map *cpu; +struct cache_level *caches; +int caches_cnt; };extern struct perf_env perf_env;
@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);int perf_env__read_cpu_topology_map (struct perf_env *env); +void cache_level__free (struct cache_level *cache);#endif /* __PERF_ENV_H */
tools/perf/util/header.c +265 -0
295 lines not on this page · raw message
tools/perf/util/header.h +1 -0
@@ -32,6 +32,7 @@ enum {HEADER_GROUP_DESC ,HEADER_AUXTRACE ,HEADER_STAT , +HEADER_CACHE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.4.3
Namhyung Kim
maintainerRe: [PATCHv2 5/5] perf tools: Add perf data cache feature
Hi Jiri,
Quoted 49 lines · Jiri Olsa
Quoted 4 lines · Jiri Olsa
Storing CPU cache details under perf data. It's stored as new
HEADER_CACHEfeature and it's displayed under header info with -I option:Quoted 12 lines
$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...changing the output based on Ingo's comment
v2 attached, the rest of the patchset staysmy perf/cache branch is updated
thanks,
jirka---
Storing CPU cache details under perf data. It's stored as newHEADER_CACHEfeature and it's displayed under header info with -I option:$ perf report --header-only -I ... # CPU cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...All distinct caches are stored/displayed.
Signed-off-by Jiri Olsa <[email protected]>---
[SNIP]
Quoted 22 lines
tools/perf/util/header.c +22
-0+static int build_caches (struct cache_level caches[],u32 size,u32 *cntp) +{ +u32 i, cnt =0 ; +long ncpus; +u32 nr, cpu; +u16 level; + + ncpus =sysconf (_SC_NPROCESSORS_CONF); +if (ncpus <0 ) +return -1 ; + + nr = (u32)(ncpus &UINT_MAX ); + +for (cpu =0 ; cpu < nr; cpu++) { +for (level =0 ; level <10 ; level++) { +struct cache_level c; +int err; + + err =cache_level__read (&c, cpu, level); +if (err <0 ) +return err; +
tools/perf/util/header.c static int write_auxtrace(int fd, struct perf_header *h, · line 999
Quoted 10 lines
tools/perf/util/header.c +10
-0+if (err ==1 ) +break ; + +for (i =0 ; i < cnt; i++) { +if (cache_level__cmp (&c, &caches[i])) +break ; + } + +if (i == cnt) + caches[cnt++] = c;
else cache_level__free(&c);
???
Thanks,
Namhyung
Quoted 9 lines
tools/perf/util/header.c +9
-0+ +if (WARN_ONCE (cnt == size,"way too many cpu caches.." )) + goto out; + } + } + out: + *cntp = cnt; +return 0 ; +}
PATCH v3 5/5 perf tools: Add perf data cache feature
On Tue, Feb 16, 2016 at 11:22:19PM +0900, Namhyung Kim wrote:
SNIP
Quoted 37 lines
[SNIP]
Quoted 22 lines
(quoted diff) +22
-0+static int build_caches(struct cache_level caches[], u32 size, u32 *cntp) +{ + u32 i, cnt = 0; + long ncpus; + u32 nr, cpu; + u16 level; + + ncpus = sysconf(_SC_NPROCESSORS_CONF); + if (ncpus < 0) + return -1; + + nr = (u32)(ncpus & UINT_MAX); + + for (cpu = 0; cpu < nr; cpu++) { + for (level = 0; level < 10; level++) { + struct cache_level c; + int err; + + err = cache_level__read(&c, cpu, level); + if (err < 0) + return err; +Review
Quoted 10 lines
(quoted diff) +10
-0+ if (err == 1) + break; + + for (i = 0; i < cnt; i++) { + if (cache_level__cmp(&c, &caches[i])) + break; + } + + if (i == cnt) + caches[cnt++] = c;else cache_level__free(&c);
Quoted 1 line
???
ouch right.. v3 attached
thanks,
jirka
---
Storing CPU cache details under perf data. It's stored as new HEADER_CACHE feature and it's displayed under header info with -I option:
$ perf report --header-only -I ... # CPU cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
All distinct caches are stored/displayed.
--- tools/perf/util/env.c | 13 +++ tools/perf/util/env.h | 15 +++ tools/perf/util/header.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 4 files changed, 296 insertions(+)
tools/perf/util/env.c +13 -0
@@ -6,6 +6,8 @@ struct perf_env perf_env;void perf_env__exit (struct perf_env *env) { +int i; +zfree (&env->hostname);zfree (&env->os_release);zfree (&env->version);
@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)zfree (&env->numa_nodes);zfree (&env->pmu_mappings);zfree (&env->cpu); + +for (i =0 ; i < env->caches_cnt; i++) +cache_level__free (&env->caches[i]); +zfree (&env->caches); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env) env->nr_cpus_avail = nr_cpus;return 0 ; } + +void cache_level__free (struct cache_level *cache) +{ +free (cache->type); +free (cache->map); +free (cache->size); +}
tools/perf/util/env.h +15 -0
@@ -1,11 +1,23 @@ #ifndef __PERF_ENV_H #define __PERF_ENV_H +#include <linux/types.h> + struct cpu_topology_map { int socket_id; int core_id; }; +struct cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + struct perf_env { char *hostname; char *os_release;
@@ -31,6 +43,8 @@ struct perf_env {char *numa_nodes;char *pmu_mappings;struct cpu_topology_map *cpu; +struct cache_level *caches; +int caches_cnt; };extern struct perf_env perf_env;
@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);int perf_env__read_cpu_topology_map (struct perf_env *env); +void cache_level__free (struct cache_level *cache);#endif /* __PERF_ENV_H */
tools/perf/util/header.c +267 -0
297 lines not on this page · raw message
tools/perf/util/header.h +1 -0
@@ -32,6 +32,7 @@ enum {HEADER_GROUP_DESC ,HEADER_AUXTRACE ,HEADER_STAT , +HEADER_CACHE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.4.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCHv3 5/5] perf tools: Add perf data cache feature
Em Tue, Feb 16, 2016 at 04:01:43PM +0100, Jiri Olsa escreveu:
Quoted 413 lines · Namhyung Kim
SNIP
Quoted 37 lines
[SNIP]
Quoted 22 lines
tools/perf/util/header.c +22
-0+static int build_caches (struct cache_level caches[],u32 size,u32 *cntp) +{ +u32 i, cnt =0 ; +long ncpus; +u32 nr, cpu; +u16 level; + + ncpus =sysconf (_SC_NPROCESSORS_CONF); +if (ncpus <0 ) +return -1 ; + + nr = (u32)(ncpus &UINT_MAX ); + +for (cpu =0 ; cpu < nr; cpu++) { +for (level =0 ; level <10 ; level++) { +struct cache_level c; +int err; + + err =cache_level__read (&c, cpu, level); +if (err <0 ) +return err; +tools/perf/util/header.c static int write_auxtrace(int fd, struct perf_header *h, · line 999
Quoted 10 lines
tools/perf/util/header.c +10
-0+if (err ==1 ) +break ; + +for (i =0 ; i < cnt; i++) { +if (cache_level__cmp (&c, &caches[i])) +break ; + } + +if (i == cnt) + caches[cnt++] = c;else cache_level__free(&c);Quoted 1 line
???
ouch right.. v3 attached
thanks,
jirka---
Storing CPU cache details under perf data. It's stored as newHEADER_CACHEfeature and it's displayed under header info with -I option:$ perf report --header-only -I ... # CPU cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...All distinct caches are stored/displayed.
Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/env.c | 13 +++ tools/perf/util/env.h | 15 +++ tools/perf/util/header.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 4 files changed, 296 insertions(+)tools/perf/util/env.c +13
-0@@ -6,6 +6,8 @@ struct perf_env perf_env;void perf_env__exit (struct perf_env *env) { +int i; +zfree (&env->hostname);zfree (&env->os_release);zfree (&env->version);@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)zfree (&env->numa_nodes);zfree (&env->pmu_mappings);zfree (&env->cpu); + +for (i =0 ; i < env->caches_cnt; i++) +cache_level__free (&env->caches[i]); +zfree (&env->caches); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env) env->nr_cpus_avail = nr_cpus;return 0 ; } + +void cache_level__free (struct cache_level *cache) +{ +free (cache->type); +free (cache->map); +free (cache->size); +}tools/perf/util/env.h +15
-0@@ -1,11 +1,23 @@ #ifndef __PERF_ENV_H #define __PERF_ENV_H +#include <linux/types.h> + struct cpu_topology_map { int socket_id; int core_id; }; +struct cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + struct perf_env { char *hostname; char *os_release;@@ -31,6 +43,8 @@ struct perf_env {char *numa_nodes;char *pmu_mappings;struct cpu_topology_map *cpu; +struct cache_level *caches; +int caches_cnt; };extern struct perf_env perf_env;@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);int perf_env__read_cpu_topology_map (struct perf_env *env); +void cache_level__free (struct cache_level *cache);#endif /* __PERF_ENV_H */ tools/perf/util/header.c +229
-0@@ -23,6 +23,8 @@#include "strbuf.h" #include "build-id.h" #include "data.h" +#include <api/fs/fs.h> +#include "asm/bug.h" /* * magic2 = "PERFILE2" @@ -868,6 +870,199 @@ static int write_auxtrace(int fd, struct perf_header *h,return err; } +static int cache_level__sort (const void *a,const void *b) +{ +struct cache_level *cache_a = (struct cache_level *) a; +struct cache_level *cache_b = (struct cache_level *) b; + +return cache_a->level - cache_b->level; +} + +static bool cache_level__cmp (struct cache_level *a,struct cache_level *b) +{ +if (a->level != b->level) +return false; + +if (a->line_size != b->line_size) +return false; + +if (a->sets != b->sets) +return false; + +if (a->ways != b->ways) +return false; + +if (strcmp (a->type, b->type)) +return false; + +if (strcmp (a->size, b->size)) +return false; + +if (strcmp (a->map, b->map)) +return false; + +return true; +} + +static int cache_level__read (struct cache_level *cache,u32 cpu,u16 level) +{ +char path[PATH_MAX ], file[PATH_MAX ]; +struct stat st; +size_t len; + +scnprintf (path,PATH_MAX ,"devices/system/cpu/cpu%d/cache/index%d/" , cpu, level); +scnprintf (file,PATH_MAX ,"%s/%s" ,sysfs__mountpoint (), path); + +if (stat (file, &st)) +return 1 ; + +scnprintf (file,PATH_MAX ,"%s/level" , path); +if (sysfs__read_int (file, (int *) &cache->level)) +return -1 ; + +scnprintf (file,PATH_MAX ,"%s/coherency_line_size" , path); +if (sysfs__read_int (file, (int *) &cache->line_size)) +return -1 ; + +scnprintf (file,PATH_MAX ,"%s/number_of_sets" , path); +if (sysfs__read_int (file, (int *) &cache->sets)) +return -1 ; + +scnprintf (file,PATH_MAX ,"%s/ways_of_associativity" , path); +if (sysfs__read_int (file, (int *) &cache->ways)) +return -1 ; + +scnprintf (file,PATH_MAX ,"%s/type" , path); +if (sysfs__read_str (file, &cache->type, &len)) +return -1 ; + + cache->type[len] =0 ; + cache->type =rtrim (cache->type); + +scnprintf (file,PATH_MAX ,"%s/size" , path); +if (sysfs__read_str (file, &cache->size, &len)) { +free (cache->type); +return -1 ; + } + + cache->size[len] =0 ; + cache->size =rtrim (cache->size); + +scnprintf (file,PATH_MAX ,"%s/shared_cpu_list" , path); +if (sysfs__read_str (file, &cache->map, &len)) { +free (cache->map); +free (cache->type); +return -1 ; + } + + cache->map[len] =0 ; + cache->map =rtrim (cache->map); +return 0 ; +} + +static void cache_level__fprintf (FILE *out,struct cache_level *c) +{ +fprintf (out,"L%d %-15s %8s [%s]\n" , c->level, c->type, c->size, c->map); +} + +static int build_caches (struct cache_level caches[],u32 size,u32 *cntp) +{ +u32 i, cnt =0 ; +long ncpus; +u32 nr, cpu; +u16 level; + + ncpus =sysconf (_SC_NPROCESSORS_CONF); +if (ncpus <0 ) +return -1 ; + + nr = (u32)(ncpus &UINT_MAX ); + +for (cpu =0 ; cpu < nr; cpu++) { +for (level =0 ; level <10 ; level++) { +struct cache_level c; +int err; + + err =cache_level__read (&c, cpu, level); +if (err <0 ) +return err; + +if (err ==1 ) +break ; + +for (i =0 ; i < cnt; i++) { +if (cache_level__cmp (&c, &caches[i])) +break ; + } + +if (i == cnt) + caches[cnt++] = c; +else +cache_level__free (&c); + +if (WARN_ONCE (cnt == size,"way too many cpu caches.." )) + goto out; + } + } + out: + *cntp = cnt; +return 0 ; +} + +#define MAX_CACHES 2000 + +static int write_cache (int fd,struct perf_header *h__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +struct cache_level caches[MAX_CACHES ]; +u32 cnt =0 , i, version =1 ; +int ret; + + ret =build_caches (caches,MAX_CACHES , &cnt); +if (ret) + goto out; + +qsort (&caches, cnt,sizeof (struct cache_level ), cache_level__sort); + + ret =do_write (fd, &version,sizeof (u32)); +if (ret <0 ) + goto out; + + ret =do_write (fd, &cnt,sizeof (u32)); +if (ret <0 ) + goto out; + +for (i =0 ; i < cnt; i++) { +struct cache_level *c = &caches[i]; + +#define _W (v) \ + ret = do_write(fd, &c->v, sizeof(u32)); \ + if (ret < 0) \ + goto out; + + _W(level) + _W(line_size) + _W(sets) + _W(ways) +#undef _W + +#define _W (v) \ + ret = do_write_string(fd, (const char *) c->v); \ + if (ret < 0) \ + goto out; + + _W(type) + _W(size) + _W(map) +#undef _W + } + +out: +for (i =0 ; i < cnt; i++) +cache_level__free (&caches[i]); +return ret; +} +static int write_stat (int fd__maybe_unused ,struct perf_header *h__maybe_unused ,struct perf_evlist *evlist__maybe_unused )@@ -1172,6 +1367,18 @@ static void print_stat(struct perf_header *ph __maybe_unused,fprintf (fp,"# contains stat data\n" ); } +static void print_cache (struct perf_header *ph__maybe_unused , +int fd__maybe_unused ,FILE *fp__maybe_unused ) +{ +int i; + +fprintf (fp,"# CPU cache info:\n" ); +for (i =0 ; i < ph->env.caches_cnt; i++) { +fprintf (fp,"# " ); +cache_level__fprintf (fp, &ph->env.caches[i]); + } +} +static void print_pmu_mappings (struct perf_header *ph,int fd__maybe_unused ,FILE *fp) {@@ -1920,6 +2127,65 @@ static int process_auxtrace(struct perf_file_section *section,return err; } +static int process_cache (struct perf_file_section *section__maybe_unused , +struct perf_header *ph__maybe_unused ,int fd__maybe_unused , +void *data__maybe_unused ) +{ +struct cache_level *caches; +u32 cnt, i, version; + +if (readn (fd, &version,sizeof (version)) !=sizeof (version)) +return -1 ; + +if (ph->needs_swap) + version =bswap_32 (version); + +if (version !=1 ) +return -1 ; + +if (readn (fd, &cnt,sizeof (cnt)) !=sizeof (cnt)) +return -1 ; + +if (ph->needs_swap) + cnt =bswap_32 (cnt); +
tools/perf/util/header.c static int process_auxtrace(struct perf_file_section *section, · line 2161
Quoted 10 lines
tools/perf/util/header.c +10
-0+ caches =zalloc (sizeof (struct cache_level ) * cnt); +if (!caches) +return -1 ; + +for (i =0 ; i < cnt; i++) { +struct cache_level c; + +#define _R (v) \ + if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\ + return -1; \
So in this case that 'caches' variable leaks?
tools/perf/util/header.c static int process_auxtrace(struct perf_file_section *section, · line 2173
Quoted 12 lines
tools/perf/util/header.c +12
-0+if (ph->needs_swap) \ + c.v =bswap_32 (c.v); \ + + _R(level) + _R(line_size) + _R(sets) + _R(ways) +#undef _R + +#define _R (v) \ + c.v = do_read_string(fd, ph); \ + if (!c.v) \
Ditto.
tools/perf/util/header.c static int process_auxtrace(struct perf_file_section *section, · line 2182
Quoted 9 lines
tools/perf/util/header.c +9
-0+return -1 ; + + _R(type) + _R(size) + _R(map) +#undef _R + + caches[i] = c; + }
Because it is only here that you assign it to something outside this function.
Also, as discussed on IRC, please s/cache_level/cpu_cache_level/g, as per Ingo's comment.
- Arnaldo
Quoted 30 lines
tools/perf/util/header.c +6
-0+ ph->env.caches = caches; + ph->env.caches_cnt = cnt; +return 0 ; +} +struct feature_ops {int (*write)(int fd,struct perf_header *h,struct perf_evlist *evlist);void (*print)(struct perf_header *h,int fd,FILE *fp);@@ -1962,6 +2228,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPP (HEADER_GROUP_DESC , group_desc),FEAT_OPP (HEADER_AUXTRACE , auxtrace),FEAT_OPA (HEADER_STAT , stat), + FEAT_OPF(HEADER_CACHE, cache), }; struct header_print_data {tools/perf/util/header.h +1
-0@@ -32,6 +32,7 @@ enum {HEADER_GROUP_DESC ,HEADER_AUXTRACE ,HEADER_STAT , +HEADER_CACHE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };Signature · 1 line
2.4.3
Re: [PATCHv3 5/5] perf tools: Add perf data cache feature
Em Tue, Feb 16, 2016 at 12:29:36PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 14 lines
Em Tue, Feb 16, 2016 at 04:01:43PM +0100, Jiri Olsa escreveu:
tools/perf/util/header.c static int process_auxtrace(struct perf_file_section *section, · line 2161
Quoted 10 lines
tools/perf/util/header.c +10
-0+ caches =zalloc (sizeof (struct cache_level ) * cnt); +if (!caches) +return -1 ; + +for (i =0 ; i < cnt; i++) { +struct cache_level c; + +#define _R (v) \ + if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\ + return -1; \So in this case that 'caches' variable leaks?
Ok, I fixed this and did the rename to cpu_cache_level, tested and merged it, going to the next patchkit.
Thanks! Useful feature, we should use it in other places, like: record same workload in different machines, say Ivy Bridge and Broadwell, do 'perf diff' and see the CPU cache topology difference in addition to other symbolic, per DSO, etc diffs.
- Arnaldo
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Add perf data cache feature
In reply to Jiri Olsaperf tools: Add perf data cache feature
Commit-ID: 720e98b5faf10cfd12b7821dbdcc41c9747bd13e Gitweb: http://git.kernel.org/tip/720e98b5faf10cfd12b7821dbdcc41c9747bd13e Author: Jiri Olsa <[email protected]> AuthorDate: Tue, 16 Feb 2016 16:01:43 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 16 Feb 2016 17:13:00 -0300
perf tools: Add perf data cache feature
Storing CPU cache details under perf data. It's stored as new HEADER_CACHE feature and it's displayed under header info with -I option:
$ perf report --header-only -I ... # CPU cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3] ...
All distinct caches are stored/displayed.
--- tools/perf/util/env.c | 13 +++ tools/perf/util/env.h | 15 +++ tools/perf/util/header.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 1 + 4 files changed, 299 insertions(+)
tools/perf/util/env.c +13 -0
@@ -6,6 +6,8 @@ struct perf_env perf_env;void perf_env__exit (struct perf_env *env) { +int i; +zfree (&env->hostname);zfree (&env->os_release);zfree (&env->version);
@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)zfree (&env->numa_nodes);zfree (&env->pmu_mappings);zfree (&env->cpu); + +for (i =0 ; i < env->caches_cnt; i++) +cpu_cache_level__free (&env->caches[i]); +zfree (&env->caches); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env) env->nr_cpus_avail = nr_cpus;return 0 ; } + +void cpu_cache_level__free (struct cpu_cache_level *cache) +{ +free (cache->type); +free (cache->map); +free (cache->size); +}
tools/perf/util/env.h +15 -0
@@ -1,11 +1,23 @@ #ifndef __PERF_ENV_H #define __PERF_ENV_H +#include <linux/types.h> + struct cpu_topology_map { int socket_id; int core_id; }; +struct cpu_cache_level { + u32 level; + u32 line_size; + u32 sets; + u32 ways; + char *type; + char *size; + char *map; +}; + struct perf_env { char *hostname; char *os_release;
@@ -31,6 +43,8 @@ struct perf_env {char *numa_nodes;char *pmu_mappings;struct cpu_topology_map *cpu; +struct cpu_cache_level *caches; +int caches_cnt; };extern struct perf_env perf_env;
@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);int perf_env__read_cpu_topology_map (struct perf_env *env); +void cpu_cache_level__free (struct cpu_cache_level *cache);#endif /* __PERF_ENV_H */
tools/perf/util/header.c +270 -0
300 lines not on this page · raw message
tools/perf/util/header.h +1 -0
@@ -32,6 +32,7 @@ enum {HEADER_GROUP_DESC ,HEADER_AUXTRACE ,HEADER_STAT , +HEADER_CACHE ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Quoted 13 lines · Jiri Olsa
hi,
adding support to store CPU cache details under perf data.$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3]
Very small UI nit, wouldn't it be nicer if this displayed tabular output, and if numbers were adjusted to their decimal point, i.e. something like:
Quoted 8 lines
# CPU cache info:
# L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3]
(Also note that it says 'CPU cache info' - there are a lot of caches in the system.)
Thanks,
Ingo
Quoted 29 lines · Ingo Molnar
Quoted 13 lines · Jiri Olsa
hi,
adding support to store CPU cache details under perf data.$ perf report --header-only -I ... # cache info: # L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3]Very small UI nit, wouldn't it be nicer if this displayed tabular output, and if numbers were adjusted to their decimal point, i.e. something like:
Quoted 8 lines
# CPU cache info:
# L1 Data 32K [0-1] # L1 Instruction 32K [0-1] # L1 Data 32K [2-3] # L1 Instruction 32K [2-3] # L2 Unified 256K [0-1] # L2 Unified 256K [2-3] # L3 Unified 4096K [0-3]
Quoted 2 lines
(Also note that it says 'CPU cache info' - there are a lot of caches in the system.)
yep, looks better.. will change
thanks,
jirka