mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
c61e52ee70
The sample events recorded by perf record are not time ordered because we have one buffer per cpu for each event (even demultiplexed per task/per cpu for task bound events). But when we read trace events we want them to be ordered by time because many state machines are involved. There are currently two ways perf tools deal with that: - use -M to multiplex every buffers (perf sched, perf kmem) But this creates a lot of contention in SMP machines on record time. - use a post-processing time reordering (perf timechart, perf lock) The reordering used by timechart is simple but doesn't scale well with huge flow of events, in terms of performance and memory use (unusable with perf lock for example). Perf lock has its own samples reordering that flushes its memory use in a regular basis and that uses a sorting based on the previous event queued (a new event to be queued is close to the previous one most of the time). This patch proposes to export perf lock's samples reordering facility to the session layer that reads the events. So if a tool wants to get ordered sample events, it needs to set its struct perf_event_ops::ordered_samples to true and that's it. This prepares tracing based perf tools to get rid of the need to use buffers multiplexing (-M) or to implement their own reordering. Also lower the flush period to 2 as it's sufficient already. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> Cc: Ingo Molnar <mingo@elte.hu> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Tom Zanussi <tzanussi@gmail.com>
106 lines
2.6 KiB
C
106 lines
2.6 KiB
C
#ifndef __PERF_SESSION_H
|
|
#define __PERF_SESSION_H
|
|
|
|
#include "event.h"
|
|
#include "header.h"
|
|
#include "symbol.h"
|
|
#include "thread.h"
|
|
#include <linux/rbtree.h>
|
|
#include "../../../include/linux/perf_event.h"
|
|
|
|
struct sample_queue;
|
|
struct ip_callchain;
|
|
struct thread;
|
|
|
|
struct ordered_samples {
|
|
u64 last_flush;
|
|
u64 flush_limit;
|
|
struct list_head samples_head;
|
|
struct sample_queue *last_inserted;
|
|
};
|
|
|
|
struct perf_session {
|
|
struct perf_header header;
|
|
unsigned long size;
|
|
unsigned long mmap_window;
|
|
struct rb_root threads;
|
|
struct thread *last_match;
|
|
struct rb_root kerninfo_root;
|
|
struct events_stats events_stats;
|
|
struct rb_root stats_by_id;
|
|
unsigned long event_total[PERF_RECORD_MAX];
|
|
unsigned long unknown_events;
|
|
struct rb_root hists;
|
|
u64 sample_type;
|
|
int fd;
|
|
bool fd_pipe;
|
|
int cwdlen;
|
|
char *cwd;
|
|
struct ordered_samples ordered_samples;
|
|
char filename[0];
|
|
};
|
|
|
|
typedef int (*event_op)(event_t *self, struct perf_session *session);
|
|
|
|
struct perf_event_ops {
|
|
event_op sample,
|
|
mmap,
|
|
comm,
|
|
fork,
|
|
exit,
|
|
lost,
|
|
read,
|
|
throttle,
|
|
unthrottle,
|
|
attr,
|
|
event_type,
|
|
tracing_data,
|
|
build_id;
|
|
bool ordered_samples;
|
|
};
|
|
|
|
struct perf_session *perf_session__new(const char *filename, int mode, bool force);
|
|
void perf_session__delete(struct perf_session *self);
|
|
|
|
void perf_event_header__bswap(struct perf_event_header *self);
|
|
|
|
int __perf_session__process_events(struct perf_session *self,
|
|
u64 data_offset, u64 data_size, u64 size,
|
|
struct perf_event_ops *ops);
|
|
int perf_session__process_events(struct perf_session *self,
|
|
struct perf_event_ops *event_ops);
|
|
|
|
struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
|
|
struct thread *thread,
|
|
struct ip_callchain *chain,
|
|
struct symbol **parent);
|
|
|
|
bool perf_session__has_traces(struct perf_session *self, const char *msg);
|
|
|
|
int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
|
|
const char *symbol_name,
|
|
u64 addr);
|
|
|
|
void mem_bswap_64(void *src, int byte_size);
|
|
|
|
int perf_session__create_kernel_maps(struct perf_session *self);
|
|
|
|
int do_read(int fd, void *buf, size_t size);
|
|
void perf_session__update_sample_type(struct perf_session *self);
|
|
|
|
#ifdef NO_NEWT_SUPPORT
|
|
static inline int perf_session__browse_hists(struct rb_root *hists __used,
|
|
u64 nr_hists __used,
|
|
u64 session_total __used,
|
|
const char *helpline __used,
|
|
const char *input_name __used)
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
|
|
u64 session_total, const char *helpline,
|
|
const char *input_name);
|
|
#endif
|
|
#endif /* __PERF_SESSION_H */
|