diff options
Diffstat (limited to 'tools/perf/util/hist.h')
| -rw-r--r-- | tools/perf/util/hist.h | 343 | 
1 files changed, 271 insertions, 72 deletions
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 587d375d343..742f49a8572 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -2,39 +2,25 @@  #define __PERF_HIST_H  #include <linux/types.h> +#include <pthread.h>  #include "callchain.h" +#include "header.h" +#include "color.h" +#include "ui/progress.h"  extern struct callchain_param callchain_param;  struct hist_entry;  struct addr_location;  struct symbol; -struct rb_root; -struct objdump_line { -	struct list_head node; -	s64		 offset; -	char		 *line; -}; - -void objdump_line__free(struct objdump_line *self); -struct objdump_line *objdump__get_next_ip_line(struct list_head *head, -					       struct objdump_line *pos); - -struct sym_hist { -	u64		sum; -	u64		ip[0]; -}; - -struct sym_ext { -	struct rb_node	node; -	double		percent; -	char		*path; -}; - -struct sym_priv { -	struct sym_hist	*hist; -	struct sym_ext	*ext; +enum hist_filter { +	HIST_FILTER__DSO, +	HIST_FILTER__THREAD, +	HIST_FILTER__PARENT, +	HIST_FILTER__SYMBOL, +	HIST_FILTER__GUEST, +	HIST_FILTER__HOST,  };  /* @@ -51,9 +37,16 @@ struct sym_priv {   */  struct events_stats {  	u64 total_period; +	u64 total_non_filtered_period;  	u64 total_lost; +	u64 total_invalid_chains;  	u32 nr_events[PERF_RECORD_HEADER_MAX]; +	u32 nr_non_filtered_samples; +	u32 nr_lost_warned;  	u32 nr_unknown_events; +	u32 nr_invalid_chains; +	u32 nr_unknown_id; +	u32 nr_unprocessable_samples;  };  enum hist_column { @@ -63,86 +56,292 @@ enum hist_column {  	HISTC_COMM,  	HISTC_PARENT,  	HISTC_CPU, +	HISTC_SRCLINE, +	HISTC_MISPREDICT, +	HISTC_IN_TX, +	HISTC_ABORT, +	HISTC_SYMBOL_FROM, +	HISTC_SYMBOL_TO, +	HISTC_DSO_FROM, +	HISTC_DSO_TO, +	HISTC_LOCAL_WEIGHT, +	HISTC_GLOBAL_WEIGHT, +	HISTC_MEM_DADDR_SYMBOL, +	HISTC_MEM_DADDR_DSO, +	HISTC_MEM_LOCKED, +	HISTC_MEM_TLB, +	HISTC_MEM_LVL, +	HISTC_MEM_SNOOP, +	HISTC_MEM_DCACHELINE, +	HISTC_TRANSACTION,  	HISTC_NR_COLS, /* Last entry */  }; +struct thread; +struct dso; +  struct hists { -	struct rb_node		rb_node; +	struct rb_root		entries_in_array[2]; +	struct rb_root		*entries_in;  	struct rb_root		entries; +	struct rb_root		entries_collapsed;  	u64			nr_entries; +	u64			nr_non_filtered_entries; +	const struct thread	*thread_filter; +	const struct dso	*dso_filter; +	const char		*uid_filter_str; +	const char		*symbol_filter_str; +	pthread_mutex_t		lock;  	struct events_stats	stats; -	u64			config;  	u64			event_stream; -	u32			type;  	u16			col_len[HISTC_NR_COLS];  }; -struct hist_entry *__hists__add_entry(struct hists *self, +struct hist_entry_iter; + +struct hist_iter_ops { +	int (*prepare_entry)(struct hist_entry_iter *, struct addr_location *); +	int (*add_single_entry)(struct hist_entry_iter *, struct addr_location *); +	int (*next_entry)(struct hist_entry_iter *, struct addr_location *); +	int (*add_next_entry)(struct hist_entry_iter *, struct addr_location *); +	int (*finish_entry)(struct hist_entry_iter *, struct addr_location *); +}; + +struct hist_entry_iter { +	int total; +	int curr; + +	bool hide_unresolved; + +	struct perf_evsel *evsel; +	struct perf_sample *sample; +	struct hist_entry *he; +	struct symbol *parent; +	void *priv; + +	const struct hist_iter_ops *ops; +	/* user-defined callback function (optional) */ +	int (*add_entry_cb)(struct hist_entry_iter *iter, +			    struct addr_location *al, bool single, void *arg); +}; + +extern const struct hist_iter_ops hist_iter_normal; +extern const struct hist_iter_ops hist_iter_branch; +extern const struct hist_iter_ops hist_iter_mem; +extern const struct hist_iter_ops hist_iter_cumulative; + +struct hist_entry *__hists__add_entry(struct hists *hists,  				      struct addr_location *al, -				      struct symbol *parent, u64 period); -extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); -extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); -int hist_entry__fprintf(struct hist_entry *self, struct hists *hists, -			struct hists *pair_hists, bool show_displacement, -			long displacement, FILE *fp, u64 total); -int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, -			 struct hists *hists, struct hists *pair_hists, -			 bool show_displacement, long displacement, -			 bool color, u64 total); +				      struct symbol *parent, +				      struct branch_info *bi, +				      struct mem_info *mi, u64 period, +				      u64 weight, u64 transaction, +				      bool sample_self); +int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, +			 struct perf_evsel *evsel, struct perf_sample *sample, +			 int max_stack_depth, void *arg); + +int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); +int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); +int hist_entry__transaction_len(void); +int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, +			      struct hists *hists);  void hist_entry__free(struct hist_entry *); -void hists__output_resort(struct hists *self); -void hists__collapse_resort(struct hists *self); +void hists__output_resort(struct hists *hists); +void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); + +void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); +void hists__output_recalc_col_len(struct hists *hists, int max_rows); + +u64 hists__total_period(struct hists *hists); +void hists__reset_stats(struct hists *hists); +void hists__inc_stats(struct hists *hists, struct hist_entry *h); +void hists__inc_nr_events(struct hists *hists, u32 type); +void hists__inc_nr_samples(struct hists *hists, bool filtered); +void events_stats__inc(struct events_stats *stats, u32 type); +size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); + +size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, +		      int max_cols, float min_pcnt, FILE *fp); + +void hists__filter_by_dso(struct hists *hists); +void hists__filter_by_thread(struct hists *hists); +void hists__filter_by_symbol(struct hists *hists); + +static inline bool hists__has_filter(struct hists *hists) +{ +	return hists->thread_filter || hists->dso_filter || +		hists->symbol_filter_str; +} + +u16 hists__col_len(struct hists *hists, enum hist_column col); +void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len); +bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len); +void hists__reset_col_len(struct hists *hists); +void hists__calc_col_len(struct hists *hists, struct hist_entry *he); + +void hists__match(struct hists *leader, struct hists *other); +int hists__link(struct hists *leader, struct hists *other); + +struct perf_hpp { +	char *buf; +	size_t size; +	const char *sep; +	void *ptr; +}; + +struct perf_hpp_fmt { +	int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, +		      struct perf_evsel *evsel); +	int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, +		     struct perf_evsel *evsel); +	int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, +		     struct hist_entry *he); +	int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, +		     struct hist_entry *he); +	int64_t (*cmp)(struct hist_entry *a, struct hist_entry *b); +	int64_t (*collapse)(struct hist_entry *a, struct hist_entry *b); +	int64_t (*sort)(struct hist_entry *a, struct hist_entry *b); + +	struct list_head list; +	struct list_head sort_list; +	bool elide; +}; + +extern struct list_head perf_hpp__list; +extern struct list_head perf_hpp__sort_list; + +#define perf_hpp__for_each_format(format) \ +	list_for_each_entry(format, &perf_hpp__list, list) + +#define perf_hpp__for_each_format_safe(format, tmp)	\ +	list_for_each_entry_safe(format, tmp, &perf_hpp__list, list) + +#define perf_hpp__for_each_sort_list(format) \ +	list_for_each_entry(format, &perf_hpp__sort_list, sort_list) + +#define perf_hpp__for_each_sort_list_safe(format, tmp)	\ +	list_for_each_entry_safe(format, tmp, &perf_hpp__sort_list, sort_list) + +extern struct perf_hpp_fmt perf_hpp__format[]; + +enum { +	/* Matches perf_hpp__format array. */ +	PERF_HPP__OVERHEAD, +	PERF_HPP__OVERHEAD_SYS, +	PERF_HPP__OVERHEAD_US, +	PERF_HPP__OVERHEAD_GUEST_SYS, +	PERF_HPP__OVERHEAD_GUEST_US, +	PERF_HPP__OVERHEAD_ACC, +	PERF_HPP__SAMPLES, +	PERF_HPP__PERIOD, -void hists__inc_nr_events(struct hists *self, u32 type); -size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); +	PERF_HPP__MAX_INDEX +}; + +void perf_hpp__init(void); +void perf_hpp__column_register(struct perf_hpp_fmt *format); +void perf_hpp__column_unregister(struct perf_hpp_fmt *format); +void perf_hpp__column_enable(unsigned col); +void perf_hpp__column_disable(unsigned col); +void perf_hpp__cancel_cumulate(void); + +void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); +void perf_hpp__setup_output_field(void); +void perf_hpp__reset_output_field(void); +void perf_hpp__append_sort_keys(void); + +bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); +bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); -size_t hists__fprintf(struct hists *self, struct hists *pair, -		      bool show_displacement, FILE *fp); +static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format) +{ +	return format->elide; +} -int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip); -int hist_entry__annotate(struct hist_entry *self, struct list_head *head, -			 size_t privsize); +void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); -void hists__filter_by_dso(struct hists *self, const struct dso *dso); -void hists__filter_by_thread(struct hists *self, const struct thread *thread); +typedef u64 (*hpp_field_fn)(struct hist_entry *he); +typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); +typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); -u16 hists__col_len(struct hists *self, enum hist_column col); -void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); -bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); +int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, +	       hpp_field_fn get_field, const char *fmt, +	       hpp_snprint_fn print_fn, bool fmt_percent); +int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, +		   hpp_field_fn get_field, const char *fmt, +		   hpp_snprint_fn print_fn, bool fmt_percent); -#ifdef NO_NEWT_SUPPORT -static inline int hists__browse(struct hists *self __used, -				const char *helpline __used, -				const char *ev_name __used) +static inline void advance_hpp(struct perf_hpp *hpp, int inc)  { -	return 0; +	hpp->buf  += inc; +	hpp->size -= inc;  } -static inline int hists__tui_browse_tree(struct rb_root *self __used, -					 const char *help __used) +static inline size_t perf_hpp__use_color(void) +{ +	return !symbol_conf.field_sep; +} + +static inline size_t perf_hpp__color_overhead(void) +{ +	return perf_hpp__use_color() ? +	       (COLOR_MAXLEN + sizeof(PERF_COLOR_RESET)) * PERF_HPP__MAX_INDEX +	       : 0; +} + +struct perf_evlist; + +struct hist_browser_timer { +	void (*timer)(void *arg); +	void *arg; +	int refresh; +}; + +#ifdef HAVE_SLANG_SUPPORT +#include "../ui/keysyms.h" +int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, +			     struct hist_browser_timer *hbt); + +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, +				  struct hist_browser_timer *hbt, +				  float min_pcnt, +				  struct perf_session_env *env); +int script_browse(const char *script_opt); +#else +static inline +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, +				  const char *help __maybe_unused, +				  struct hist_browser_timer *hbt __maybe_unused, +				  float min_pcnt __maybe_unused, +				  struct perf_session_env *env __maybe_unused)  {  	return 0;  } -static inline int hist_entry__tui_annotate(struct hist_entry *self __used) +static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, +					   struct perf_evsel *evsel __maybe_unused, +					   struct hist_browser_timer *hbt __maybe_unused)  {  	return 0;  } -#define KEY_LEFT -1 -#define KEY_RIGHT -2 -#else -#include <newt.h> -int hists__browse(struct hists *self, const char *helpline, -		  const char *ev_name); -int hist_entry__tui_annotate(struct hist_entry *self); -#define KEY_LEFT NEWT_KEY_LEFT -#define KEY_RIGHT NEWT_KEY_RIGHT +static inline int script_browse(const char *script_opt __maybe_unused) +{ +	return 0; +} -int hists__tui_browse_tree(struct rb_root *self, const char *help); +#define K_LEFT  -1000 +#define K_RIGHT -2000 +#define K_SWITCH_INPUT_DATA -3000  #endif -unsigned int hists__sort_list_width(struct hists *self); +unsigned int hists__sort_list_width(struct hists *hists); + +struct option; +int parse_filter_percentage(const struct option *opt __maybe_unused, +			    const char *arg, int unset __maybe_unused); +int perf_hist_config(const char *var, const char *value);  #endif	/* __PERF_HIST_H */  | 
