Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Linux-御风守护者
linux
提交
975fc2d5
L
linux
项目概览
Linux-御风守护者
/
linux
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
975fc2d5
编写于
5月 12, 2010
作者:
I
Ingo Molnar
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'perf' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6
into perf/core
上级
8e6d5573
ef7b93a1
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
688 addition
and
355 deletion
+688
-355
tools/perf/Makefile
tools/perf/Makefile
+10
-2
tools/perf/builtin-annotate.c
tools/perf/builtin-annotate.c
+2
-196
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+19
-5
tools/perf/util/hist.c
tools/perf/util/hist.c
+243
-0
tools/perf/util/hist.h
tools/perf/util/hist.h
+44
-0
tools/perf/util/newt.c
tools/perf/util/newt.c
+370
-131
tools/perf/util/session.h
tools/perf/util/session.h
+0
-15
tools/perf/util/sort.h
tools/perf/util/sort.h
+0
-6
未找到文件。
tools/perf/Makefile
浏览文件 @
975fc2d5
...
...
@@ -506,8 +506,8 @@ PERFLIBS = $(LIB_FILE)
-include
config.mak
ifndef
NO_DWARF
ifneq
($(shell sh -c "(echo '\
#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
msg
:=
$(
warning
No libdw.h found or old libdw.h found
, disables dwarf support. Please
install
elfutils-devel/libdw-dev
)
;
ifneq
($(shell sh -c "(echo '\
#include <dwarf.h>'; echo '\#include <libdw.h>'; echo '
\#include <version.h>'; echo '\#ifndef _ELFUTILS_PREREQ'; echo '\#error'; echo '\#endif'; echo '
int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
msg
:=
$(
warning
No libdw.h found or old libdw.h found
or elfutils is older than 0.138, disables dwarf support. Please
install
new
elfutils-devel/libdw-dev
)
;
NO_DWARF
:=
1
endif
# Dwarf support
endif
# NO_DWARF
...
...
@@ -560,6 +560,8 @@ ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtIni
msg
:=
$(
warning
newt not found, disables TUI support. Please
install
newt-devel or libnewt-dev
)
;
BASIC_CFLAGS
+=
-DNO_NEWT_SUPPORT
else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
BASIC_CFLAGS
+=
-I
/usr/include/slang
EXTLIBS
+=
-lnewt
LIB_OBJS
+=
$(OUTPUT)
util/newt.o
endif
...
...
@@ -592,6 +594,9 @@ endif
ifdef
NO_DEMANGLE
BASIC_CFLAGS
+=
-DNO_DEMANGLE
else
ifdef
HAVE_CPLUS_DEMANGLE
EXTLIBS
+=
-liberty
BASIC_CFLAGS
+=
-DHAVE_CPLUS_DEMANGLE
else
has_bfd
:=
$(
shell
sh
-c
"(echo '
\#
include <bfd.h>'; echo 'int main(void
)
{ bfd_demangle(0, 0, 0
)
; return 0;
}
'
)
|
$(CC)
-x c -
$(ALL_CFLAGS)
-o
$(BITBUCKET)
$(ALL_LDFLAGS)
$(EXTLIBS)
-lbfd "
$(QUIET_STDERR)
" && echo y"
)
...
...
@@ -945,6 +950,9 @@ $(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
$(OUTPUT)util/config.o
:
util/config.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DETC_PERFCONFIG
=
'"
$(ETC_PERFCONFIG_SQ)
"'
$<
$(OUTPUT)util/newt.o
:
util/newt.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DENABLE_SLFUTURE_CONST
$<
$(OUTPUT)util/rbtree.o
:
../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC)
-o
$@
-c
$(ALL_CFLAGS)
-DETC_PERFCONFIG
=
'"
$(ETC_PERFCONFIG_SQ)
"'
$<
...
...
tools/perf/builtin-annotate.c
浏览文件 @
975fc2d5
...
...
@@ -34,68 +34,8 @@ static bool full_paths;
static
bool
print_line
;
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
;
};
static
const
char
*
sym_hist_filter
;
static
int
sym__alloc_hist
(
struct
symbol
*
self
)
{
struct
sym_priv
*
priv
=
symbol__priv
(
self
);
const
int
size
=
(
sizeof
(
*
priv
->
hist
)
+
(
self
->
end
-
self
->
start
)
*
sizeof
(
u64
));
priv
->
hist
=
zalloc
(
size
);
return
priv
->
hist
==
NULL
?
-
1
:
0
;
}
/*
* collect histogram counts
*/
static
int
annotate__hist_hit
(
struct
hist_entry
*
he
,
u64
ip
)
{
unsigned
int
sym_size
,
offset
;
struct
symbol
*
sym
=
he
->
ms
.
sym
;
struct
sym_priv
*
priv
;
struct
sym_hist
*
h
;
if
(
!
sym
||
!
he
->
ms
.
map
)
return
0
;
priv
=
symbol__priv
(
sym
);
if
(
priv
->
hist
==
NULL
&&
sym__alloc_hist
(
sym
)
<
0
)
return
-
ENOMEM
;
sym_size
=
sym
->
end
-
sym
->
start
;
offset
=
ip
-
sym
->
start
;
pr_debug3
(
"%s: ip=%#Lx
\n
"
,
__func__
,
he
->
ms
.
map
->
unmap_ip
(
he
->
ms
.
map
,
ip
));
if
(
offset
>=
sym_size
)
return
0
;
h
=
priv
->
hist
;
h
->
sum
++
;
h
->
ip
[
offset
]
++
;
pr_debug3
(
"%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
he
->
ms
.
sym
->
start
,
he
->
ms
.
sym
->
name
,
ip
,
ip
-
he
->
ms
.
sym
->
start
,
h
->
ip
[
offset
]);
return
0
;
}
static
int
hists__add_entry
(
struct
hists
*
self
,
struct
addr_location
*
al
)
{
struct
hist_entry
*
he
;
...
...
@@ -115,7 +55,7 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
if
(
he
==
NULL
)
return
-
ENOMEM
;
return
annotate__hist_hit
(
he
,
al
->
addr
);
return
hist_entry__inc_addr_samples
(
he
,
al
->
addr
);
}
static
int
process_sample_event
(
event_t
*
event
,
struct
perf_session
*
session
)
...
...
@@ -140,101 +80,6 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return
0
;
}
struct
objdump_line
{
struct
list_head
node
;
s64
offset
;
char
*
line
;
};
static
struct
objdump_line
*
objdump_line__new
(
s64
offset
,
char
*
line
)
{
struct
objdump_line
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
self
!=
NULL
)
{
self
->
offset
=
offset
;
self
->
line
=
line
;
}
return
self
;
}
static
void
objdump_line__free
(
struct
objdump_line
*
self
)
{
free
(
self
->
line
);
free
(
self
);
}
static
void
objdump__add_line
(
struct
list_head
*
head
,
struct
objdump_line
*
line
)
{
list_add_tail
(
&
line
->
node
,
head
);
}
static
struct
objdump_line
*
objdump__get_next_ip_line
(
struct
list_head
*
head
,
struct
objdump_line
*
pos
)
{
list_for_each_entry_continue
(
pos
,
head
,
node
)
if
(
pos
->
offset
>=
0
)
return
pos
;
return
NULL
;
}
static
int
parse_line
(
FILE
*
file
,
struct
hist_entry
*
he
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
he
->
ms
.
sym
;
struct
objdump_line
*
objdump_line
;
char
*
line
=
NULL
,
*
tmp
,
*
tmp2
;
size_t
line_len
;
s64
line_ip
,
offset
=
-
1
;
char
*
c
;
if
(
getline
(
&
line
,
&
line_len
,
file
)
<
0
)
return
-
1
;
if
(
!
line
)
return
-
1
;
c
=
strchr
(
line
,
'\n'
);
if
(
c
)
*
c
=
0
;
line_ip
=
-
1
;
/*
* Strip leading spaces:
*/
tmp
=
line
;
while
(
*
tmp
)
{
if
(
*
tmp
!=
' '
)
break
;
tmp
++
;
}
if
(
*
tmp
)
{
/*
* Parse hexa addresses followed by ':'
*/
line_ip
=
strtoull
(
tmp
,
&
tmp2
,
16
);
if
(
*
tmp2
!=
':'
)
line_ip
=
-
1
;
}
if
(
line_ip
!=
-
1
)
{
u64
start
=
map__rip_2objdump
(
he
->
ms
.
map
,
sym
->
start
);
offset
=
line_ip
-
start
;
}
objdump_line
=
objdump_line__new
(
offset
,
line
);
if
(
objdump_line
==
NULL
)
{
free
(
line
);
return
-
1
;
}
objdump__add_line
(
head
,
objdump_line
);
return
0
;
}
static
int
objdump_line__print
(
struct
objdump_line
*
self
,
struct
list_head
*
head
,
struct
hist_entry
*
he
,
u64
len
)
...
...
@@ -439,28 +284,12 @@ static void annotate_sym(struct hist_entry *he)
struct
symbol
*
sym
=
he
->
ms
.
sym
;
const
char
*
filename
=
dso
->
long_name
,
*
d_filename
;
u64
len
;
char
command
[
PATH_MAX
*
2
];
FILE
*
file
;
LIST_HEAD
(
head
);
struct
objdump_line
*
pos
,
*
n
;
if
(
!
filename
)
if
(
hist_entry__annotate
(
he
,
&
head
)
<
0
)
return
;
if
(
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
if
(
dso
->
annotate_warned
)
return
;
dso
->
annotate_warned
=
1
;
pr_err
(
"Can't annotate %s: No vmlinux file was found in the "
"path:
\n
"
,
sym
->
name
);
vmlinux_path__fprintf
(
stderr
);
return
;
}
pr_debug
(
"%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx
\n
"
,
__func__
,
filename
,
sym
->
name
,
map
->
unmap_ip
(
map
,
sym
->
start
),
map
->
unmap_ip
(
map
,
sym
->
end
));
if
(
full_paths
)
d_filename
=
filename
;
else
...
...
@@ -477,29 +306,6 @@ static void annotate_sym(struct hist_entry *he)
printf
(
" Percent | Source code & Disassembly of %s
\n
"
,
d_filename
);
printf
(
"------------------------------------------------
\n
"
);
if
(
verbose
>=
2
)
printf
(
"annotating [%p] %30s : [%p] %30s
\n
"
,
dso
,
dso
->
long_name
,
sym
,
sym
->
name
);
sprintf
(
command
,
"objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s"
,
map__rip_2objdump
(
map
,
sym
->
start
),
map__rip_2objdump
(
map
,
sym
->
end
),
filename
,
filename
);
if
(
verbose
>=
3
)
printf
(
"doing: %s
\n
"
,
command
);
file
=
popen
(
command
,
"r"
);
if
(
!
file
)
return
;
while
(
!
feof
(
file
))
{
if
(
parse_line
(
file
,
he
,
&
head
)
<
0
)
break
;
}
pclose
(
file
);
if
(
verbose
)
hist_entry__print_hits
(
he
);
...
...
tools/perf/builtin-report.c
浏览文件 @
975fc2d5
...
...
@@ -106,8 +106,18 @@ static int perf_session__add_hist_entry(struct perf_session *self,
if
(
he
==
NULL
)
goto
out_free_syms
;
err
=
0
;
if
(
symbol_conf
.
use_callchain
)
if
(
symbol_conf
.
use_callchain
)
{
err
=
append_chain
(
he
->
callchain
,
data
->
callchain
,
syms
);
if
(
err
)
goto
out_free_syms
;
}
/*
* Only in the newt browser we are doing integrated annotation,
* so we don't allocated the extra space needed because the stdio
* code will not use it.
*/
if
(
use_browser
)
err
=
hist_entry__inc_addr_samples
(
he
,
al
->
addr
);
out_free_syms:
free
(
syms
);
return
err
;
...
...
@@ -301,10 +311,7 @@ static int __cmd_report(void)
hists__collapse_resort
(
hists
);
hists__output_resort
(
hists
);
if
(
use_browser
)
perf_session__browse_hists
(
&
hists
->
entries
,
hists
->
nr_entries
,
hists
->
stats
.
total
,
help
,
input_name
);
hists__browse
(
hists
,
help
,
input_name
);
else
{
if
(
rb_first
(
&
session
->
hists
.
entries
)
==
rb_last
(
&
session
->
hists
.
entries
))
...
...
@@ -461,6 +468,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if
(
strcmp
(
input_name
,
"-"
)
!=
0
)
setup_browser
();
/*
* Only in the newt browser we are doing integrated annotation,
* so don't allocate extra space that won't be used in the stdio
* implementation.
*/
if
(
use_browser
)
symbol_conf
.
priv_size
=
sizeof
(
struct
sym_priv
);
if
(
symbol__init
()
<
0
)
return
-
1
;
...
...
tools/perf/util/hist.c
浏览文件 @
975fc2d5
...
...
@@ -784,3 +784,246 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
return
ret
;
}
enum
hist_filter
{
HIST_FILTER__DSO
,
HIST_FILTER__THREAD
,
};
void
hists__filter_by_dso
(
struct
hists
*
self
,
const
struct
dso
*
dso
)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
symbol_conf
.
exclude_other
&&
!
h
->
parent
)
continue
;
if
(
dso
!=
NULL
&&
(
h
->
ms
.
map
==
NULL
||
h
->
ms
.
map
->
dso
!=
dso
))
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__DSO
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__DSO
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
}
}
}
void
hists__filter_by_thread
(
struct
hists
*
self
,
const
struct
thread
*
thread
)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
thread
!=
NULL
&&
h
->
thread
!=
thread
)
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__THREAD
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__THREAD
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
}
}
}
static
int
symbol__alloc_hist
(
struct
symbol
*
self
)
{
struct
sym_priv
*
priv
=
symbol__priv
(
self
);
const
int
size
=
(
sizeof
(
*
priv
->
hist
)
+
(
self
->
end
-
self
->
start
)
*
sizeof
(
u64
));
priv
->
hist
=
zalloc
(
size
);
return
priv
->
hist
==
NULL
?
-
1
:
0
;
}
int
hist_entry__inc_addr_samples
(
struct
hist_entry
*
self
,
u64
ip
)
{
unsigned
int
sym_size
,
offset
;
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
sym_priv
*
priv
;
struct
sym_hist
*
h
;
if
(
!
sym
||
!
self
->
ms
.
map
)
return
0
;
priv
=
symbol__priv
(
sym
);
if
(
priv
->
hist
==
NULL
&&
symbol__alloc_hist
(
sym
)
<
0
)
return
-
ENOMEM
;
sym_size
=
sym
->
end
-
sym
->
start
;
offset
=
ip
-
sym
->
start
;
pr_debug3
(
"%s: ip=%#Lx
\n
"
,
__func__
,
self
->
ms
.
map
->
unmap_ip
(
self
->
ms
.
map
,
ip
));
if
(
offset
>=
sym_size
)
return
0
;
h
=
priv
->
hist
;
h
->
sum
++
;
h
->
ip
[
offset
]
++
;
pr_debug3
(
"%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
self
->
ms
.
sym
->
start
,
self
->
ms
.
sym
->
name
,
ip
,
ip
-
self
->
ms
.
sym
->
start
,
h
->
ip
[
offset
]);
return
0
;
}
static
struct
objdump_line
*
objdump_line__new
(
s64
offset
,
char
*
line
)
{
struct
objdump_line
*
self
=
malloc
(
sizeof
(
*
self
));
if
(
self
!=
NULL
)
{
self
->
offset
=
offset
;
self
->
line
=
line
;
}
return
self
;
}
void
objdump_line__free
(
struct
objdump_line
*
self
)
{
free
(
self
->
line
);
free
(
self
);
}
static
void
objdump__add_line
(
struct
list_head
*
head
,
struct
objdump_line
*
line
)
{
list_add_tail
(
&
line
->
node
,
head
);
}
struct
objdump_line
*
objdump__get_next_ip_line
(
struct
list_head
*
head
,
struct
objdump_line
*
pos
)
{
list_for_each_entry_continue
(
pos
,
head
,
node
)
if
(
pos
->
offset
>=
0
)
return
pos
;
return
NULL
;
}
static
int
hist_entry__parse_objdump_line
(
struct
hist_entry
*
self
,
FILE
*
file
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
objdump_line
*
objdump_line
;
char
*
line
=
NULL
,
*
tmp
,
*
tmp2
,
*
c
;
size_t
line_len
;
s64
line_ip
,
offset
=
-
1
;
if
(
getline
(
&
line
,
&
line_len
,
file
)
<
0
)
return
-
1
;
if
(
!
line
)
return
-
1
;
while
(
line_len
!=
0
&&
isspace
(
line
[
line_len
-
1
]))
line
[
--
line_len
]
=
'\0'
;
c
=
strchr
(
line
,
'\n'
);
if
(
c
)
*
c
=
0
;
line_ip
=
-
1
;
/*
* Strip leading spaces:
*/
tmp
=
line
;
while
(
*
tmp
)
{
if
(
*
tmp
!=
' '
)
break
;
tmp
++
;
}
if
(
*
tmp
)
{
/*
* Parse hexa addresses followed by ':'
*/
line_ip
=
strtoull
(
tmp
,
&
tmp2
,
16
);
if
(
*
tmp2
!=
':'
)
line_ip
=
-
1
;
}
if
(
line_ip
!=
-
1
)
{
u64
start
=
map__rip_2objdump
(
self
->
ms
.
map
,
sym
->
start
);
offset
=
line_ip
-
start
;
}
objdump_line
=
objdump_line__new
(
offset
,
line
);
if
(
objdump_line
==
NULL
)
{
free
(
line
);
return
-
1
;
}
objdump__add_line
(
head
,
objdump_line
);
return
0
;
}
int
hist_entry__annotate
(
struct
hist_entry
*
self
,
struct
list_head
*
head
)
{
struct
symbol
*
sym
=
self
->
ms
.
sym
;
struct
map
*
map
=
self
->
ms
.
map
;
struct
dso
*
dso
=
map
->
dso
;
const
char
*
filename
=
dso
->
long_name
;
char
command
[
PATH_MAX
*
2
];
FILE
*
file
;
u64
len
;
if
(
!
filename
)
return
-
1
;
if
(
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
if
(
dso
->
annotate_warned
)
return
0
;
dso
->
annotate_warned
=
1
;
pr_err
(
"Can't annotate %s: No vmlinux file was found in the "
"path:
\n
"
,
sym
->
name
);
vmlinux_path__fprintf
(
stderr
);
return
-
1
;
}
pr_debug
(
"%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx
\n
"
,
__func__
,
filename
,
sym
->
name
,
map
->
unmap_ip
(
map
,
sym
->
start
),
map
->
unmap_ip
(
map
,
sym
->
end
));
len
=
sym
->
end
-
sym
->
start
;
pr_debug
(
"annotating [%p] %30s : [%p] %30s
\n
"
,
dso
,
dso
->
long_name
,
sym
,
sym
->
name
);
snprintf
(
command
,
sizeof
(
command
),
"objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s|expand"
,
map__rip_2objdump
(
map
,
sym
->
start
),
map__rip_2objdump
(
map
,
sym
->
end
),
filename
,
filename
);
pr_debug
(
"Executing: %s
\n
"
,
command
);
file
=
popen
(
command
,
"r"
);
if
(
!
file
)
return
-
1
;
while
(
!
feof
(
file
))
if
(
hist_entry__parse_objdump_line
(
self
,
file
,
head
)
<
0
)
break
;
pclose
(
file
);
return
0
;
}
tools/perf/util/hist.h
浏览文件 @
975fc2d5
...
...
@@ -11,6 +11,32 @@ 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
;
};
struct
events_stats
{
u64
total
;
u64
lost
;
...
...
@@ -44,4 +70,22 @@ void hists__output_resort(struct hists *self);
void
hists__collapse_resort
(
struct
hists
*
self
);
size_t
hists__fprintf
(
struct
hists
*
self
,
struct
hists
*
pair
,
bool
show_displacement
,
FILE
*
fp
);
int
hist_entry__inc_addr_samples
(
struct
hist_entry
*
self
,
u64
ip
);
int
hist_entry__annotate
(
struct
hist_entry
*
self
,
struct
list_head
*
head
);
void
hists__filter_by_dso
(
struct
hists
*
self
,
const
struct
dso
*
dso
);
void
hists__filter_by_thread
(
struct
hists
*
self
,
const
struct
thread
*
thread
);
#ifdef NO_NEWT_SUPPORT
static
inline
int
hists__browse
(
struct
hists
self
__used
,
const
char
*
helpline
__used
,
const
char
*
input_name
__used
)
{
return
0
;
}
#else
int
hists__browse
(
struct
hists
*
self
,
const
char
*
helpline
,
const
char
*
input_name
);
#endif
#endif
/* __PERF_HIST_H */
tools/perf/util/newt.c
浏览文件 @
975fc2d5
...
...
@@ -2,6 +2,7 @@
#include <stdio.h>
#undef _GNU_SOURCE
#include <slang.h>
#include <stdlib.h>
#include <newt.h>
#include <sys/ttydefaults.h>
...
...
@@ -57,6 +58,43 @@ void ui_progress__delete(struct ui_progress *self)
free
(
self
);
}
static
void
ui_helpline__pop
(
void
)
{
newtPopHelpLine
();
}
static
void
ui_helpline__push
(
const
char
*
msg
)
{
newtPushHelpLine
(
msg
);
}
static
void
ui_helpline__vpush
(
const
char
*
fmt
,
va_list
ap
)
{
char
*
s
;
if
(
vasprintf
(
&
s
,
fmt
,
ap
)
<
0
)
vfprintf
(
stderr
,
fmt
,
ap
);
else
{
ui_helpline__push
(
s
);
free
(
s
);
}
}
static
void
ui_helpline__fpush
(
const
char
*
fmt
,
...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
ui_helpline__vpush
(
fmt
,
ap
);
va_end
(
ap
);
}
static
void
ui_helpline__puts
(
const
char
*
msg
)
{
ui_helpline__pop
();
ui_helpline__push
(
msg
);
}
static
char
browser__last_msg
[
1024
];
int
browser__show_help
(
const
char
*
format
,
va_list
ap
)
...
...
@@ -69,8 +107,7 @@ int browser__show_help(const char *format, va_list ap)
backlog
+=
ret
;
if
(
browser__last_msg
[
backlog
-
1
]
==
'\n'
)
{
newtPopHelpLine
();
newtPushHelpLine
(
browser__last_msg
);
ui_helpline__puts
(
browser__last_msg
);
newtRefresh
();
backlog
=
0
;
}
...
...
@@ -135,6 +172,254 @@ static bool dialog_yesno(const char *msg)
return
newtWinChoice
(
NULL
,
yes
,
no
,
(
char
*
)
msg
)
==
1
;
}
#define HE_COLORSET_TOP 50
#define HE_COLORSET_MEDIUM 51
#define HE_COLORSET_NORMAL 52
#define HE_COLORSET_SELECTED 53
#define HE_COLORSET_CODE 54
static
int
ui_browser__percent_color
(
double
percent
,
bool
current
)
{
if
(
current
)
return
HE_COLORSET_SELECTED
;
if
(
percent
>=
MIN_RED
)
return
HE_COLORSET_TOP
;
if
(
percent
>=
MIN_GREEN
)
return
HE_COLORSET_MEDIUM
;
return
HE_COLORSET_NORMAL
;
}
struct
ui_browser
{
newtComponent
form
,
sb
;
u64
index
,
first_visible_entry_idx
;
void
*
first_visible_entry
,
*
entries
;
u16
top
,
left
,
width
,
height
;
void
*
priv
;
u32
nr_entries
;
};
static
void
ui_browser__refresh_dimensions
(
struct
ui_browser
*
self
)
{
int
cols
,
rows
;
newtGetScreenSize
(
&
cols
,
&
rows
);
if
(
self
->
width
>
cols
-
4
)
self
->
width
=
cols
-
4
;
self
->
height
=
rows
-
5
;
if
(
self
->
height
>
self
->
nr_entries
)
self
->
height
=
self
->
nr_entries
;
self
->
top
=
(
rows
-
self
->
height
)
/
2
;
self
->
left
=
(
cols
-
self
->
width
)
/
2
;
}
static
void
ui_browser__reset_index
(
struct
ui_browser
*
self
)
{
self
->
index
=
self
->
first_visible_entry_idx
=
0
;
self
->
first_visible_entry
=
NULL
;
}
static
int
objdump_line__show
(
struct
objdump_line
*
self
,
struct
list_head
*
head
,
int
width
,
struct
hist_entry
*
he
,
int
len
,
bool
current_entry
)
{
if
(
self
->
offset
!=
-
1
)
{
struct
symbol
*
sym
=
he
->
ms
.
sym
;
unsigned
int
hits
=
0
;
double
percent
=
0
.
0
;
int
color
;
struct
sym_priv
*
priv
=
symbol__priv
(
sym
);
struct
sym_ext
*
sym_ext
=
priv
->
ext
;
struct
sym_hist
*
h
=
priv
->
hist
;
s64
offset
=
self
->
offset
;
struct
objdump_line
*
next
=
objdump__get_next_ip_line
(
head
,
self
);
while
(
offset
<
(
s64
)
len
&&
(
next
==
NULL
||
offset
<
next
->
offset
))
{
if
(
sym_ext
)
{
percent
+=
sym_ext
[
offset
].
percent
;
}
else
hits
+=
h
->
ip
[
offset
];
++
offset
;
}
if
(
sym_ext
==
NULL
&&
h
->
sum
)
percent
=
100
.
0
*
hits
/
h
->
sum
;
color
=
ui_browser__percent_color
(
percent
,
current_entry
);
SLsmg_set_color
(
color
);
SLsmg_printf
(
" %7.2f "
,
percent
);
if
(
!
current_entry
)
SLsmg_set_color
(
HE_COLORSET_CODE
);
}
else
{
int
color
=
ui_browser__percent_color
(
0
,
current_entry
);
SLsmg_set_color
(
color
);
SLsmg_write_nstring
(
" "
,
9
);
}
SLsmg_write_char
(
':'
);
SLsmg_write_nstring
(
" "
,
8
);
if
(
!*
self
->
line
)
SLsmg_write_nstring
(
" "
,
width
-
18
);
else
SLsmg_write_nstring
(
self
->
line
,
width
-
18
);
return
0
;
}
static
int
ui_browser__refresh_entries
(
struct
ui_browser
*
self
)
{
struct
objdump_line
*
pos
;
struct
list_head
*
head
=
self
->
entries
;
struct
hist_entry
*
he
=
self
->
priv
;
int
row
=
0
;
int
len
=
he
->
ms
.
sym
->
end
-
he
->
ms
.
sym
->
start
;
if
(
self
->
first_visible_entry
==
NULL
||
self
->
first_visible_entry
==
self
->
entries
)
self
->
first_visible_entry
=
head
->
next
;
pos
=
list_entry
(
self
->
first_visible_entry
,
struct
objdump_line
,
node
);
list_for_each_entry_from
(
pos
,
head
,
node
)
{
bool
current_entry
=
(
self
->
first_visible_entry_idx
+
row
)
==
self
->
index
;
SLsmg_gotorc
(
self
->
top
+
row
,
self
->
left
);
objdump_line__show
(
pos
,
head
,
self
->
width
,
he
,
len
,
current_entry
);
if
(
++
row
==
self
->
height
)
break
;
}
SLsmg_set_color
(
HE_COLORSET_NORMAL
);
SLsmg_fill_region
(
self
->
top
+
row
,
self
->
left
,
self
->
height
-
row
,
self
->
width
,
' '
);
return
0
;
}
static
int
ui_browser__run
(
struct
ui_browser
*
self
,
const
char
*
title
,
struct
newtExitStruct
*
es
)
{
if
(
self
->
form
)
{
newtFormDestroy
(
self
->
form
);
newtPopWindow
();
}
ui_browser__refresh_dimensions
(
self
);
newtCenteredWindow
(
self
->
width
+
2
,
self
->
height
,
title
);
self
->
form
=
newt_form__new
();
if
(
self
->
form
==
NULL
)
return
-
1
;
self
->
sb
=
newtVerticalScrollbar
(
self
->
width
+
1
,
0
,
self
->
height
,
HE_COLORSET_NORMAL
,
HE_COLORSET_SELECTED
);
if
(
self
->
sb
==
NULL
)
return
-
1
;
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_UP
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_DOWN
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_PGUP
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_PGDN
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_HOME
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_END
);
if
(
ui_browser__refresh_entries
(
self
)
<
0
)
return
-
1
;
newtFormAddComponent
(
self
->
form
,
self
->
sb
);
while
(
1
)
{
unsigned
int
offset
;
newtFormRun
(
self
->
form
,
es
);
if
(
es
->
reason
!=
NEWT_EXIT_HOTKEY
)
break
;
switch
(
es
->
u
.
key
)
{
case
NEWT_KEY_DOWN
:
if
(
self
->
index
==
self
->
nr_entries
-
1
)
break
;
++
self
->
index
;
if
(
self
->
index
==
self
->
first_visible_entry_idx
+
self
->
height
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
++
self
->
first_visible_entry_idx
;
self
->
first_visible_entry
=
pos
->
next
;
}
break
;
case
NEWT_KEY_UP
:
if
(
self
->
index
==
0
)
break
;
--
self
->
index
;
if
(
self
->
index
<
self
->
first_visible_entry_idx
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
--
self
->
first_visible_entry_idx
;
self
->
first_visible_entry
=
pos
->
prev
;
}
break
;
case
NEWT_KEY_PGDN
:
if
(
self
->
first_visible_entry_idx
+
self
->
height
>
self
->
nr_entries
-
1
)
break
;
offset
=
self
->
height
;
if
(
self
->
index
+
offset
>
self
->
nr_entries
-
1
)
offset
=
self
->
nr_entries
-
1
-
self
->
index
;
self
->
index
+=
offset
;
self
->
first_visible_entry_idx
+=
offset
;
while
(
offset
--
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
next
;
}
break
;
case
NEWT_KEY_PGUP
:
if
(
self
->
first_visible_entry_idx
==
0
)
break
;
if
(
self
->
first_visible_entry_idx
<
self
->
height
)
offset
=
self
->
first_visible_entry_idx
;
else
offset
=
self
->
height
;
self
->
index
-=
offset
;
self
->
first_visible_entry_idx
-=
offset
;
while
(
offset
--
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
prev
;
}
break
;
case
NEWT_KEY_HOME
:
ui_browser__reset_index
(
self
);
break
;
case
NEWT_KEY_END
:
{
struct
list_head
*
head
=
self
->
entries
;
offset
=
self
->
height
-
1
;
if
(
offset
>
self
->
nr_entries
)
offset
=
self
->
nr_entries
;
self
->
index
=
self
->
first_visible_entry_idx
=
self
->
nr_entries
-
1
-
offset
;
self
->
first_visible_entry
=
head
->
prev
;
while
(
offset
--
!=
0
)
{
struct
list_head
*
pos
=
self
->
first_visible_entry
;
self
->
first_visible_entry
=
pos
->
prev
;
}
}
break
;
case
NEWT_KEY_ESCAPE
:
case
CTRL
(
'c'
):
case
'Q'
:
case
'q'
:
return
0
;
default:
continue
;
}
if
(
ui_browser__refresh_entries
(
self
)
<
0
)
return
-
1
;
}
return
0
;
}
/*
* When debugging newt problems it was useful to be able to "unroll"
* the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate
...
...
@@ -317,62 +602,40 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
return
ret
;
}
static
void
map_symbol__annotate_browser
(
const
struct
map_symbol
*
self
,
const
char
*
input_name
)
static
void
hist_entry__annotate_browser
(
struct
hist_entry
*
self
)
{
FILE
*
fp
;
int
cols
,
rows
;
newtComponent
form
,
tree
;
struct
ui_browser
browser
;
struct
newtExitStruct
es
;
char
*
str
;
size_t
line_len
,
max_line_len
=
0
;
size_t
max_usable_width
;
char
*
line
=
NULL
;
struct
objdump_line
*
pos
,
*
n
;
LIST_HEAD
(
head
);
if
(
self
->
sym
==
NULL
)
if
(
self
->
ms
.
sym
==
NULL
)
return
;
if
(
asprintf
(
&
str
,
"perf annotate -i
\"
%s
\"
-d
\"
%s
\"
%s 2>&1 | expand"
,
input_name
,
self
->
map
->
dso
->
name
,
self
->
sym
->
name
)
<
0
)
if
(
hist_entry__annotate
(
self
,
&
head
)
<
0
)
return
;
fp
=
popen
(
str
,
"r"
);
if
(
fp
==
NULL
)
goto
out_free_str
;
newtPushHelpLine
(
"Press ESC to exit"
);
newtGetScreenSize
(
&
cols
,
&
rows
);
tree
=
newtListbox
(
0
,
0
,
rows
-
5
,
NEWT_FLAG_SCROLL
);
while
(
!
feof
(
fp
))
{
if
(
getline
(
&
line
,
&
line_len
,
fp
)
<
0
||
!
line_len
)
break
;
while
(
line_len
!=
0
&&
isspace
(
line
[
line_len
-
1
]))
line
[
--
line_len
]
=
'\0'
;
ui_helpline__push
(
"Press ESC to exit"
);
if
(
line_len
>
max_line_len
)
max_line_len
=
line_len
;
newtListboxAppendEntry
(
tree
,
line
,
NULL
);
memset
(
&
browser
,
0
,
sizeof
(
browser
));
browser
.
entries
=
&
head
;
browser
.
priv
=
self
;
list_for_each_entry
(
pos
,
&
head
,
node
)
{
size_t
line_len
=
strlen
(
pos
->
line
);
if
(
browser
.
width
<
line_len
)
browser
.
width
=
line_len
;
++
browser
.
nr_entries
;
}
fclose
(
fp
);
free
(
line
);
max_usable_width
=
cols
-
22
;
if
(
max_line_len
>
max_usable_width
)
max_line_len
=
max_usable_width
;
newtListboxSetWidth
(
tree
,
max_line_len
);
newtCenteredWindow
(
max_line_len
+
2
,
rows
-
5
,
self
->
sym
->
name
);
form
=
newt_form__new
();
newtFormAddComponent
(
form
,
tree
);
newtFormRun
(
form
,
&
es
);
newtFormDestroy
(
form
);
browser
.
width
+=
18
;
/* Percentage */
ui_browser__run
(
&
browser
,
self
->
ms
.
sym
->
name
,
&
es
);
newtFormDestroy
(
browser
.
form
);
newtPopWindow
();
newtPopHelpLine
();
out_free_str:
free
(
str
);
list_for_each_entry_safe
(
pos
,
n
,
&
head
,
node
)
{
list_del
(
&
pos
->
node
);
objdump_line__free
(
pos
);
}
ui_helpline__pop
();
}
static
const
void
*
newt__symbol_tree_get_current
(
newtComponent
self
)
...
...
@@ -410,8 +673,8 @@ static void hist_browser__delete(struct hist_browser *self)
free
(
self
);
}
static
int
hist_browser__populate
(
struct
hist_browser
*
self
,
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
title
)
static
int
hist_browser__populate
(
struct
hist_browser
*
self
,
struct
hists
*
hists
,
const
char
*
title
)
{
int
max_len
=
0
,
idx
,
cols
,
rows
;
struct
ui_progress
*
progress
;
...
...
@@ -426,7 +689,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
}
snprintf
(
str
,
sizeof
(
str
),
"Samples: %Ld "
,
session_
total
);
hists
->
stats
.
total
);
newtDrawRootText
(
0
,
0
,
str
);
newtGetScreenSize
(
NULL
,
&
rows
);
...
...
@@ -442,24 +705,25 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
newtComponentAddCallback
(
self
->
tree
,
hist_browser__selection
,
&
self
->
selection
);
progress
=
ui_progress__new
(
"Adding entries to the browser..."
,
nr_hists
);
progress
=
ui_progress__new
(
"Adding entries to the browser..."
,
hists
->
nr_entries
);
if
(
progress
==
NULL
)
return
-
1
;
idx
=
0
;
for
(
nd
=
rb_first
(
hist
s
);
nd
;
nd
=
rb_next
(
nd
))
{
for
(
nd
=
rb_first
(
&
hists
->
entrie
s
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
int
len
;
if
(
h
->
filtered
)
continue
;
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
session_
total
);
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
hists
->
stats
.
total
);
if
(
len
>
max_len
)
max_len
=
len
;
if
(
symbol_conf
.
use_callchain
)
hist_entry__append_callchain_browser
(
h
,
self
->
tree
,
session_
total
,
idx
++
);
hists
->
stats
.
total
,
idx
++
);
++
curr_hist
;
if
(
curr_hist
%
5
)
ui_progress__update
(
progress
,
curr_hist
);
...
...
@@ -490,58 +754,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
return
0
;
}
enum
hist_filter
{
HIST_FILTER__DSO
,
HIST_FILTER__THREAD
,
};
static
u64
hists__filter_by_dso
(
struct
rb_root
*
hists
,
const
struct
dso
*
dso
,
u64
*
session_total
)
{
struct
rb_node
*
nd
;
u64
nr_hists
=
0
;
*
session_total
=
0
;
for
(
nd
=
rb_first
(
hists
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
dso
!=
NULL
&&
(
h
->
ms
.
map
==
NULL
||
h
->
ms
.
map
->
dso
!=
dso
))
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__DSO
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__DSO
);
++
nr_hists
;
*
session_total
+=
h
->
count
;
}
return
nr_hists
;
}
static
u64
hists__filter_by_thread
(
struct
rb_root
*
hists
,
const
struct
thread
*
thread
,
u64
*
session_total
)
{
struct
rb_node
*
nd
;
u64
nr_hists
=
0
;
*
session_total
=
0
;
for
(
nd
=
rb_first
(
hists
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
hist_entry
*
h
=
rb_entry
(
nd
,
struct
hist_entry
,
rb_node
);
if
(
thread
!=
NULL
&&
h
->
thread
!=
thread
)
{
h
->
filtered
|=
(
1
<<
HIST_FILTER__THREAD
);
continue
;
}
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__THREAD
);
++
nr_hists
;
*
session_total
+=
h
->
count
;
}
return
nr_hists
;
}
static
struct
thread
*
hist_browser__selected_thread
(
struct
hist_browser
*
self
)
static
struct
hist_entry
*
hist_browser__selected_entry
(
struct
hist_browser
*
self
)
{
int
*
indexes
;
...
...
@@ -557,7 +770,13 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
}
return
NULL
;
out:
return
*
(
struct
thread
**
)(
self
->
selection
+
1
);
return
container_of
(
self
->
selection
,
struct
hist_entry
,
ms
);
}
static
struct
thread
*
hist_browser__selected_thread
(
struct
hist_browser
*
self
)
{
struct
hist_entry
*
he
=
hist_browser__selected_entry
(
self
);
return
he
?
he
->
thread
:
NULL
;
}
static
int
hist_browser__title
(
char
*
bf
,
size_t
size
,
const
char
*
input_name
,
...
...
@@ -577,9 +796,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
return
printed
?:
snprintf
(
bf
,
size
,
"Report: %s"
,
input_name
);
}
int
perf_session__browse_hists
(
struct
rb_root
*
hists
,
u64
nr_hists
,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
)
int
hists__browse
(
struct
hists
*
self
,
const
char
*
helpline
,
const
char
*
input_name
)
{
struct
hist_browser
*
browser
=
hist_browser__new
();
const
struct
thread
*
thread_filter
=
NULL
;
...
...
@@ -591,11 +808,11 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
if
(
browser
==
NULL
)
return
-
1
;
newtPushHelpLine
(
helpline
);
ui_helpline__push
(
helpline
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
while
(
1
)
{
...
...
@@ -653,46 +870,48 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
continue
;
do_annotate:
if
(
choice
==
annotate
)
{
struct
hist_entry
*
he
;
if
(
browser
->
selection
->
map
->
dso
->
origin
==
DSO__ORIG_KERNEL
)
{
newtPopHelpLine
();
newtPushHelpLine
(
"No vmlinux file found, can't "
ui_helpline__puts
(
"No vmlinux file found, can't "
"annotate with just a "
"kallsyms file"
);
continue
;
}
map_symbol__annotate_browser
(
browser
->
selection
,
input_name
);
he
=
hist_browser__selected_entry
(
browser
);
if
(
he
==
NULL
)
continue
;
hist_entry__annotate_browser
(
he
);
}
else
if
(
choice
==
zoom_dso
)
{
if
(
dso_filter
)
{
newtPopHelpLine
();
ui_helpline__pop
();
dso_filter
=
NULL
;
}
else
{
snprintf
(
msg
,
sizeof
(
msg
),
"To zoom out press -> +
\"
Zoom out of %s DSO
\"
"
,
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s DSO
\"
"
,
dso
->
kernel
?
"the Kernel"
:
dso
->
short_name
);
newtPushHelpLine
(
msg
);
dso_filter
=
dso
;
}
nr_hists
=
hists__filter_by_dso
(
hists
,
dso_filter
,
&
session_total
);
hists__filter_by_dso
(
self
,
dso_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
}
else
if
(
choice
==
zoom_thread
)
{
if
(
thread_filter
)
{
newtPopHelpLine
();
ui_helpline__pop
();
thread_filter
=
NULL
;
}
else
{
snprintf
(
msg
,
sizeof
(
msg
),
"To zoom out press -> +
\"
Zoom out of %s(%d) thread
\"
"
,
(
thread
->
comm_set
?
thread
->
comm
:
""
),
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s(%d) thread
\"
"
,
thread
->
comm_set
?
thread
->
comm
:
""
,
thread
->
pid
);
newtPushHelpLine
(
msg
);
thread_filter
=
thread
;
}
nr_hists
=
hists__filter_by_thread
(
hists
,
thread_filter
,
&
session_total
);
hists__filter_by_thread
(
self
,
thread_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
hists
,
nr_hists
,
session_total
,
msg
)
<
0
)
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
}
}
...
...
@@ -702,15 +921,35 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
return
err
;
}
static
struct
newtPercentTreeColors
{
const
char
*
topColorFg
,
*
topColorBg
;
const
char
*
mediumColorFg
,
*
mediumColorBg
;
const
char
*
normalColorFg
,
*
normalColorBg
;
const
char
*
selColorFg
,
*
selColorBg
;
const
char
*
codeColorFg
,
*
codeColorBg
;
}
defaultPercentTreeColors
=
{
"red"
,
"lightgray"
,
"green"
,
"lightgray"
,
"black"
,
"lightgray"
,
"lightgray"
,
"magenta"
,
"blue"
,
"lightgray"
,
};
void
setup_browser
(
void
)
{
struct
newtPercentTreeColors
*
c
=
&
defaultPercentTreeColors
;
if
(
!
isatty
(
1
))
return
;
use_browser
=
true
;
newtInit
();
newtCls
();
newtPushHelpLine
(
" "
);
ui_helpline__puts
(
" "
);
SLtt_set_color
(
HE_COLORSET_TOP
,
NULL
,
c
->
topColorFg
,
c
->
topColorBg
);
SLtt_set_color
(
HE_COLORSET_MEDIUM
,
NULL
,
c
->
mediumColorFg
,
c
->
mediumColorBg
);
SLtt_set_color
(
HE_COLORSET_NORMAL
,
NULL
,
c
->
normalColorFg
,
c
->
normalColorBg
);
SLtt_set_color
(
HE_COLORSET_SELECTED
,
NULL
,
c
->
selColorFg
,
c
->
selColorBg
);
SLtt_set_color
(
HE_COLORSET_CODE
,
NULL
,
c
->
codeColorFg
,
c
->
codeColorBg
);
}
void
exit_browser
(
bool
wait_for_ok
)
...
...
tools/perf/util/session.h
浏览文件 @
975fc2d5
...
...
@@ -102,21 +102,6 @@ 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
static
inline
struct
machine
*
perf_session__find_host_machine
(
struct
perf_session
*
self
)
{
...
...
tools/perf/util/sort.h
浏览文件 @
975fc2d5
...
...
@@ -48,12 +48,6 @@ struct hist_entry {
u64
count_us
;
u64
count_guest_sys
;
u64
count_guest_us
;
/*
* XXX WARNING!
* thread _has_ to come after ms, see
* hist_browser__selected_thread in util/newt.c
*/
struct
map_symbol
ms
;
struct
thread
*
thread
;
u64
ip
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录