2009-12-15 01:09:31 +03:00
/*
* builtin - diff . c
*
* Builtin diff command : Analyze two perf . data input files , look up and read
* DSOs and symbol information , sort them and produce a diff .
*/
# include "builtin.h"
# include "util/debug.h"
# include "util/event.h"
# include "util/hist.h"
# include "util/session.h"
# include "util/sort.h"
# include "util/symbol.h"
# include "util/util.h"
# include <stdlib.h>
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
static char const * input_old = " perf.data.old " ,
* input_new = " perf.data " ;
2009-12-16 19:09:53 +03:00
static char diff__default_sort_order [ ] = " dso,symbol " ;
2010-04-13 12:37:33 +04:00
static bool force ;
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
static bool show_displacement ;
2009-12-15 01:09:31 +03:00
static int perf_session__add_hist_entry ( struct perf_session * self ,
struct addr_location * al , u64 count )
{
bool hit ;
2010-03-05 18:51:06 +03:00
struct hist_entry * he = __perf_session__add_hist_entry ( & self - > hists ,
al , NULL ,
2009-12-15 01:09:31 +03:00
count , & hit ) ;
if ( he = = NULL )
return - ENOMEM ;
if ( hit )
he - > count + = count ;
return 0 ;
}
static int diff__process_sample_event ( event_t * event , struct perf_session * session )
{
struct addr_location al ;
struct sample_data data = { . period = 1 , } ;
2010-01-14 17:23:09 +03:00
dump_printf ( " (IP, %d): %d: %#Lx \n " , event - > header . misc ,
event - > ip . pid , event - > ip . ip ) ;
2009-12-15 01:09:31 +03:00
if ( event__preprocess_sample ( event , session , & al , NULL ) < 0 ) {
pr_warning ( " problem processing %d event, skipping it. \n " ,
event - > header . type ) ;
return - 1 ;
}
2009-12-29 03:48:35 +03:00
if ( al . filtered | | al . sym = = NULL )
2009-12-16 01:04:41 +03:00
return 0 ;
2009-12-15 01:09:31 +03:00
event__parse_sample ( event , session - > sample_type , & data ) ;
2009-12-29 03:48:35 +03:00
if ( perf_session__add_hist_entry ( session , & al , data . period ) ) {
2009-12-15 01:09:31 +03:00
pr_warning ( " problem incrementing symbol count, skipping event \n " ) ;
return - 1 ;
}
session - > events_stats . total + = data . period ;
return 0 ;
}
static struct perf_event_ops event_ops = {
2009-12-28 02:37:05 +03:00
. sample = diff__process_sample_event ,
. mmap = event__process_mmap ,
. comm = event__process_comm ,
. exit = event__process_task ,
. fork = event__process_task ,
. lost = event__process_lost ,
2009-12-15 01:09:31 +03:00
} ;
static void perf_session__insert_hist_entry_by_name ( struct rb_root * root ,
struct hist_entry * he )
{
struct rb_node * * p = & root - > rb_node ;
struct rb_node * parent = NULL ;
struct hist_entry * iter ;
while ( * p ! = NULL ) {
parent = * p ;
iter = rb_entry ( parent , struct hist_entry , rb_node ) ;
2009-12-29 03:48:36 +03:00
if ( hist_entry__cmp ( he , iter ) < 0 )
2009-12-15 01:09:31 +03:00
p = & ( * p ) - > rb_left ;
2009-12-29 03:48:36 +03:00
else
2009-12-15 01:09:31 +03:00
p = & ( * p ) - > rb_right ;
}
rb_link_node ( & he - > rb_node , parent , p ) ;
rb_insert_color ( & he - > rb_node , root ) ;
}
2009-12-29 03:48:36 +03:00
static void perf_session__resort_hist_entries ( struct perf_session * self )
2009-12-15 01:09:31 +03:00
{
unsigned long position = 1 ;
struct rb_root tmp = RB_ROOT ;
struct rb_node * next = rb_first ( & self - > hists ) ;
while ( next ! = NULL ) {
struct hist_entry * n = rb_entry ( next , struct hist_entry , rb_node ) ;
next = rb_next ( & n - > rb_node ) ;
rb_erase ( & n - > rb_node , & self - > hists ) ;
n - > position = position + + ;
perf_session__insert_hist_entry_by_name ( & tmp , n ) ;
}
self - > hists = tmp ;
}
2009-12-29 03:48:36 +03:00
static void perf_session__set_hist_entries_positions ( struct perf_session * self )
{
2010-03-05 18:51:08 +03:00
perf_session__output_resort ( & self - > hists , self - > events_stats . total ) ;
2009-12-29 03:48:36 +03:00
perf_session__resort_hist_entries ( self ) ;
}
2009-12-15 01:09:31 +03:00
static struct hist_entry *
2009-12-29 03:48:36 +03:00
perf_session__find_hist_entry ( struct perf_session * self ,
struct hist_entry * he )
2009-12-15 01:09:31 +03:00
{
struct rb_node * n = self - > hists . rb_node ;
while ( n ) {
struct hist_entry * iter = rb_entry ( n , struct hist_entry , rb_node ) ;
2009-12-29 03:48:36 +03:00
int64_t cmp = hist_entry__cmp ( he , iter ) ;
2009-12-15 01:09:31 +03:00
2009-12-29 03:48:36 +03:00
if ( cmp < 0 )
2009-12-15 01:09:31 +03:00
n = n - > rb_left ;
2009-12-29 03:48:36 +03:00
else if ( cmp > 0 )
2009-12-15 01:09:31 +03:00
n = n - > rb_right ;
2009-12-29 03:48:36 +03:00
else
return iter ;
2009-12-15 01:09:31 +03:00
}
return NULL ;
}
static void perf_session__match_hists ( struct perf_session * old_session ,
struct perf_session * new_session )
{
struct rb_node * nd ;
for ( nd = rb_first ( & new_session - > hists ) ; nd ; nd = rb_next ( nd ) ) {
struct hist_entry * pos = rb_entry ( nd , struct hist_entry , rb_node ) ;
2009-12-29 03:48:36 +03:00
pos - > pair = perf_session__find_hist_entry ( old_session , pos ) ;
2009-12-15 01:09:31 +03:00
}
}
static int __cmd_diff ( void )
{
int ret , i ;
struct perf_session * session [ 2 ] ;
2009-12-16 01:04:39 +03:00
session [ 0 ] = perf_session__new ( input_old , O_RDONLY , force ) ;
session [ 1 ] = perf_session__new ( input_new , O_RDONLY , force ) ;
2009-12-15 01:09:31 +03:00
if ( session [ 0 ] = = NULL | | session [ 1 ] = = NULL )
return - ENOMEM ;
for ( i = 0 ; i < 2 ; + + i ) {
ret = perf_session__process_events ( session [ i ] , & event_ops ) ;
if ( ret )
goto out_delete ;
}
2010-03-05 18:51:08 +03:00
perf_session__output_resort ( & session [ 1 ] - > hists ,
session [ 1 ] - > events_stats . total ) ;
2009-12-29 03:48:36 +03:00
if ( show_displacement )
perf_session__set_hist_entries_positions ( session [ 0 ] ) ;
2009-12-15 01:09:31 +03:00
perf_session__match_hists ( session [ 0 ] , session [ 1 ] ) ;
2010-03-05 18:51:08 +03:00
perf_session__fprintf_hists ( & session [ 1 ] - > hists , session [ 0 ] ,
show_displacement , stdout ,
session [ 1 ] - > events_stats . total ) ;
2009-12-15 01:09:31 +03:00
out_delete :
for ( i = 0 ; i < 2 ; + + i )
perf_session__delete ( session [ i ] ) ;
return ret ;
}
2009-12-18 21:35:58 +03:00
static const char * const diff_usage [ ] = {
2009-12-15 01:09:31 +03:00
" perf diff [<options>] [old_file] [new_file] " ,
2009-12-18 21:35:58 +03:00
NULL ,
2009-12-15 01:09:31 +03:00
} ;
static const struct option options [ ] = {
2010-04-13 12:37:33 +04:00
OPT_INCR ( ' v ' , " verbose " , & verbose ,
2009-12-15 01:09:31 +03:00
" be more verbose (show symbol address, etc) " ) ,
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
OPT_BOOLEAN ( ' m ' , " displacement " , & show_displacement ,
" Show position displacement relative to baseline " ) ,
2009-12-15 01:09:31 +03:00
OPT_BOOLEAN ( ' D ' , " dump-raw-trace " , & dump_trace ,
" dump raw trace in ASCII " ) ,
OPT_BOOLEAN ( ' f ' , " force " , & force , " don't complain, do it " ) ,
OPT_BOOLEAN ( ' m ' , " modules " , & symbol_conf . use_modules ,
" load module symbols - WARNING: use only with -k and LIVE kernel " ) ,
2009-12-28 02:37:04 +03:00
OPT_BOOLEAN ( ' P ' , " full-paths " , & symbol_conf . full_paths ,
2009-12-15 01:09:31 +03:00
" Don't shorten the pathnames taking into account the cwd " ) ,
2009-12-16 01:04:41 +03:00
OPT_STRING ( ' d ' , " dsos " , & symbol_conf . dso_list_str , " dso[,dso...] " ,
" only consider symbols in these dsos " ) ,
OPT_STRING ( ' C ' , " comms " , & symbol_conf . comm_list_str , " comm[,comm...] " ,
" only consider symbols in these comms " ) ,
OPT_STRING ( ' S ' , " symbols " , & symbol_conf . sym_list_str , " symbol[,symbol...] " ,
" only consider these symbols " ) ,
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
OPT_STRING ( ' s ' , " sort " , & sort_order , " key[,key2...] " ,
" sort by key(s): pid, comm, dso, symbol, parent " ) ,
OPT_STRING ( ' t ' , " field-separator " , & symbol_conf . field_sep , " separator " ,
" separator for columns, no spaces will be added between "
" columns '.' is reserved. " ) ,
2009-12-15 01:09:31 +03:00
OPT_END ( )
} ;
int cmd_diff ( int argc , const char * * argv , const char * prefix __used )
{
2009-12-16 19:09:53 +03:00
sort_order = diff__default_sort_order ;
2009-12-15 01:09:31 +03:00
argc = parse_options ( argc , argv , options , diff_usage , 0 ) ;
if ( argc ) {
if ( argc > 2 )
usage_with_options ( diff_usage , options ) ;
if ( argc = = 2 ) {
input_old = argv [ 0 ] ;
input_new = argv [ 1 ] ;
} else
input_new = argv [ 0 ] ;
}
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
symbol_conf . exclude_other = false ;
2009-12-16 01:04:40 +03:00
if ( symbol__init ( ) < 0 )
return - 1 ;
setup_sorting ( diff_usage , options ) ;
2009-12-15 01:09:31 +03:00
setup_pager ( ) ;
perf diff: Use perf_session__fprintf_hists just like 'perf record'
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:
$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
9.02% +1.00% find libc-2.10.1.so [.] _IO_vfprintf_internal
2.91% -1.00% find [kernel] [k] __kmalloc
2.85% -1.00% find [kernel] [k] ext4_htree_store_dirent
1.99% -1.00% find [kernel] [k] _atomic_dec_and_lock
2.44% find [kernel] [k] half_md4_transform
$
So if you want to zoom into libc:
$ perf diff --dsos libc-2.10.1.so | head -8
37.34% find [.] _IO_vfprintf_internal
10.34% find [.] __GI_memmove
8.25% +2.00% find [.] _int_malloc
5.07% -1.00% find [.] __GI_mempcpy
7.62% +2.00% find [.] _int_free
$
And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:
$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% [.] __GI_mempcpy
7.62% +2.00% [.] _int_free
$
The displacement column now is off by default, to use it:
perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34% [.] _IO_vfprintf_internal
10.34% [.] __GI_memmove
8.25% +2.00% [.] _int_malloc
5.07% -1.00% +2 [.] __GI_mempcpy
7.62% +2.00% -1 [.] _int_free
$
Using -t/--field-separator can be used for scripting:
$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%, +2,[.] __GI_mempcpy
7.62,+2.00%, -1,[.] _int_free
6.99,+1.00%, -1,[.] _IO_new_file_xsputn
1.89,-2.00%, +4,[.] __readdir64
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260978567-550-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-16 18:49:27 +03:00
sort_entry__setup_elide ( & sort_dso , symbol_conf . dso_list , " dso " , NULL ) ;
sort_entry__setup_elide ( & sort_comm , symbol_conf . comm_list , " comm " , NULL ) ;
sort_entry__setup_elide ( & sort_sym , symbol_conf . sym_list , " symbol " , NULL ) ;
2009-12-15 01:09:31 +03:00
return __cmd_diff ( ) ;
}