Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
7ebaa283
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
7ebaa283
编写于
5月 15, 2010
作者:
I
Ingo Molnar
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'perf' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6
into perf/core
上级
1ff3d7d7
3e1bbdc3
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
322 addition
and
130 deletion
+322
-130
tools/perf/Makefile
tools/perf/Makefile
+2
-0
tools/perf/builtin-annotate.c
tools/perf/builtin-annotate.c
+1
-1
tools/perf/builtin-diff.c
tools/perf/builtin-diff.c
+4
-4
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+31
-13
tools/perf/builtin-sched.c
tools/perf/builtin-sched.c
+6
-11
tools/perf/builtin-trace.c
tools/perf/builtin-trace.c
+1
-1
tools/perf/util/event.c
tools/perf/util/event.c
+18
-1
tools/perf/util/event.h
tools/perf/util/event.h
+2
-0
tools/perf/util/hist.c
tools/perf/util/hist.c
+74
-47
tools/perf/util/hist.h
tools/perf/util/hist.h
+21
-3
tools/perf/util/newt.c
tools/perf/util/newt.c
+38
-8
tools/perf/util/pstack.c
tools/perf/util/pstack.c
+75
-0
tools/perf/util/pstack.h
tools/perf/util/pstack.h
+12
-0
tools/perf/util/session.c
tools/perf/util/session.c
+2
-34
tools/perf/util/session.h
tools/perf/util/session.h
+6
-2
tools/perf/util/sort.h
tools/perf/util/sort.h
+6
-5
tools/perf/util/util.c
tools/perf/util/util.c
+22
-0
tools/perf/util/util.h
tools/perf/util/util.h
+1
-0
未找到文件。
tools/perf/Makefile
浏览文件 @
7ebaa283
...
...
@@ -416,6 +416,7 @@ LIB_H += util/thread.h
LIB_H
+=
util/trace-event.h
LIB_H
+=
util/probe-finder.h
LIB_H
+=
util/probe-event.h
LIB_H
+=
util/pstack.h
LIB_H
+=
util/cpumap.h
LIB_OBJS
+=
$(OUTPUT)
util/abspath.o
...
...
@@ -451,6 +452,7 @@ LIB_OBJS += $(OUTPUT)util/callchain.o
LIB_OBJS
+=
$(OUTPUT)
util/values.o
LIB_OBJS
+=
$(OUTPUT)
util/debug.o
LIB_OBJS
+=
$(OUTPUT)
util/map.o
LIB_OBJS
+=
$(OUTPUT)
util/pstack.o
LIB_OBJS
+=
$(OUTPUT)
util/session.o
LIB_OBJS
+=
$(OUTPUT)
util/thread.o
LIB_OBJS
+=
$(OUTPUT)
util/trace-event-parse.o
...
...
tools/perf/builtin-annotate.c
浏览文件 @
7ebaa283
...
...
@@ -365,7 +365,7 @@ static int __cmd_annotate(void)
goto
out_delete
;
if
(
dump_trace
)
{
event__print_totals
(
);
perf_session__fprintf_nr_events
(
session
,
stdout
);
goto
out_delete
;
}
...
...
tools/perf/builtin-diff.c
浏览文件 @
7ebaa283
...
...
@@ -23,9 +23,9 @@ static bool force;
static
bool
show_displacement
;
static
int
hists__add_entry
(
struct
hists
*
self
,
struct
addr_location
*
al
,
u64
count
)
struct
addr_location
*
al
,
u64
period
)
{
if
(
__hists__add_entry
(
self
,
al
,
NULL
,
count
)
!=
NULL
)
if
(
__hists__add_entry
(
self
,
al
,
NULL
,
period
)
!=
NULL
)
return
0
;
return
-
ENOMEM
;
}
...
...
@@ -50,11 +50,11 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
event__parse_sample
(
event
,
session
->
sample_type
,
&
data
);
if
(
hists__add_entry
(
&
session
->
hists
,
&
al
,
data
.
period
))
{
pr_warning
(
"problem incrementing symbol
count
, skipping event
\n
"
);
pr_warning
(
"problem incrementing symbol
period
, skipping event
\n
"
);
return
-
1
;
}
session
->
hists
.
stats
.
total
+=
data
.
period
;
session
->
hists
.
stats
.
total
_period
+=
data
.
period
;
return
0
;
}
...
...
tools/perf/builtin-report.c
浏览文件 @
7ebaa283
...
...
@@ -138,8 +138,14 @@ static int add_event_total(struct perf_session *session,
if
(
!
hists
)
return
-
ENOMEM
;
hists
->
stats
.
total
+=
data
->
period
;
session
->
hists
.
stats
.
total
+=
data
->
period
;
hists
->
stats
.
total_period
+=
data
->
period
;
/*
* FIXME: add_event_total should be moved from here to
* perf_session__process_event so that the proper hist is passed to
* the event_op methods.
*/
hists__inc_nr_events
(
hists
,
PERF_RECORD_SAMPLE
);
session
->
hists
.
stats
.
total_period
+=
data
->
period
;
return
0
;
}
...
...
@@ -182,14 +188,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return
0
;
if
(
perf_session__add_hist_entry
(
session
,
&
al
,
&
data
))
{
pr_debug
(
"problem incrementing symbol
count
, skipping event
\n
"
);
pr_debug
(
"problem incrementing symbol
period
, skipping event
\n
"
);
return
-
1
;
}
attr
=
perf_header__find_attr
(
data
.
id
,
&
session
->
header
);
if
(
add_event_total
(
session
,
&
data
,
attr
))
{
pr_debug
(
"problem adding event
count
\n
"
);
pr_debug
(
"problem adding event
period
\n
"
);
return
-
1
;
}
...
...
@@ -263,11 +269,25 @@ static struct perf_event_ops event_ops = {
extern
volatile
int
session_done
;
static
void
sig_handler
(
int
sig
__
attribute__
((
__unused__
))
)
static
void
sig_handler
(
int
sig
__
used
)
{
session_done
=
1
;
}
static
size_t
hists__fprintf_nr_sample_events
(
struct
hists
*
self
,
const
char
*
evname
,
FILE
*
fp
)
{
size_t
ret
;
char
unit
;
unsigned
long
nr_events
=
self
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
];
nr_events
=
convert_unit
(
nr_events
,
&
unit
);
ret
=
fprintf
(
fp
,
"# Events: %lu%c"
,
nr_events
,
unit
);
if
(
evname
!=
NULL
)
ret
+=
fprintf
(
fp
,
" %s"
,
evname
);
return
ret
+
fprintf
(
fp
,
"
\n
#
\n
"
);
}
static
int
__cmd_report
(
void
)
{
int
ret
=
-
EINVAL
;
...
...
@@ -293,7 +313,7 @@ static int __cmd_report(void)
goto
out_delete
;
if
(
dump_trace
)
{
event__print_totals
(
);
perf_session__fprintf_nr_events
(
session
,
stdout
);
goto
out_delete
;
}
...
...
@@ -313,14 +333,12 @@ static int __cmd_report(void)
if
(
use_browser
)
hists__browse
(
hists
,
help
,
input_name
);
else
{
if
(
rb_first
(
&
session
->
hists
.
entries
)
==
const
char
*
evname
=
NULL
;
if
(
rb_first
(
&
session
->
hists
.
entries
)
!=
rb_last
(
&
session
->
hists
.
entries
))
fprintf
(
stdout
,
"# Samples: %Ld
\n
#
\n
"
,
hists
->
stats
.
total
);
else
fprintf
(
stdout
,
"# Samples: %Ld %s
\n
#
\n
"
,
hists
->
stats
.
total
,
__event_name
(
hists
->
type
,
hists
->
config
));
evname
=
__event_name
(
hists
->
type
,
hists
->
config
);
hists__fprintf_nr_sample_events
(
hists
,
evname
,
stdout
);
hists__fprintf
(
hists
,
NULL
,
false
,
stdout
);
fprintf
(
stdout
,
"
\n\n
"
);
...
...
tools/perf/builtin-sched.c
浏览文件 @
7ebaa283
...
...
@@ -1641,19 +1641,10 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return
0
;
}
static
int
process_lost_event
(
event_t
*
event
__used
,
struct
perf_session
*
session
__used
)
{
nr_lost_chunks
++
;
nr_lost_events
+=
event
->
lost
.
lost
;
return
0
;
}
static
struct
perf_event_ops
event_ops
=
{
.
sample
=
process_sample_event
,
.
comm
=
event__process_comm
,
.
lost
=
process_lost_even
t
,
.
lost
=
event__process_los
t
,
.
ordered_samples
=
true
,
};
...
...
@@ -1664,8 +1655,12 @@ static int read_events(void)
if
(
session
==
NULL
)
return
-
ENOMEM
;
if
(
perf_session__has_traces
(
session
,
"record -R"
))
if
(
perf_session__has_traces
(
session
,
"record -R"
))
{
err
=
perf_session__process_events
(
session
,
&
event_ops
);
nr_events
=
session
->
hists
.
stats
.
nr_events
[
0
];
nr_lost_events
=
session
->
hists
.
stats
.
total_lost
;
nr_lost_chunks
=
session
->
hists
.
stats
.
nr_events
[
PERF_RECORD_LOST
];
}
perf_session__delete
(
session
);
return
err
;
...
...
tools/perf/builtin-trace.c
浏览文件 @
7ebaa283
...
...
@@ -109,7 +109,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
data
.
time
,
thread
->
comm
);
}
session
->
hists
.
stats
.
total
+=
data
.
period
;
session
->
hists
.
stats
.
total
_period
+=
data
.
period
;
return
0
;
}
...
...
tools/perf/util/event.c
浏览文件 @
7ebaa283
...
...
@@ -7,6 +7,23 @@
#include "strlist.h"
#include "thread.h"
const
char
*
event__name
[]
=
{
[
0
]
=
"TOTAL"
,
[
PERF_RECORD_MMAP
]
=
"MMAP"
,
[
PERF_RECORD_LOST
]
=
"LOST"
,
[
PERF_RECORD_COMM
]
=
"COMM"
,
[
PERF_RECORD_EXIT
]
=
"EXIT"
,
[
PERF_RECORD_THROTTLE
]
=
"THROTTLE"
,
[
PERF_RECORD_UNTHROTTLE
]
=
"UNTHROTTLE"
,
[
PERF_RECORD_FORK
]
=
"FORK"
,
[
PERF_RECORD_READ
]
=
"READ"
,
[
PERF_RECORD_SAMPLE
]
=
"SAMPLE"
,
[
PERF_RECORD_HEADER_ATTR
]
=
"ATTR"
,
[
PERF_RECORD_HEADER_EVENT_TYPE
]
=
"EVENT_TYPE"
,
[
PERF_RECORD_HEADER_TRACING_DATA
]
=
"TRACING_DATA"
,
[
PERF_RECORD_HEADER_BUILD_ID
]
=
"BUILD_ID"
,
};
static
pid_t
event__synthesize_comm
(
pid_t
pid
,
int
full
,
event__handler_t
process
,
struct
perf_session
*
session
)
...
...
@@ -368,7 +385,7 @@ int event__process_comm(event_t *self, struct perf_session *session)
int
event__process_lost
(
event_t
*
self
,
struct
perf_session
*
session
)
{
dump_printf
(
": id:%Ld: lost:%Ld
\n
"
,
self
->
lost
.
id
,
self
->
lost
.
lost
);
session
->
hists
.
stats
.
lost
+=
self
->
lost
.
lost
;
session
->
hists
.
stats
.
total_
lost
+=
self
->
lost
.
lost
;
return
0
;
}
...
...
tools/perf/util/event.h
浏览文件 @
7ebaa283
...
...
@@ -160,4 +160,6 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
struct
addr_location
*
al
,
symbol_filter_t
filter
);
int
event__parse_sample
(
event_t
*
event
,
u64
type
,
struct
sample_data
*
data
);
extern
const
char
*
event__name
[];
#endif
/* __PERF_RECORD_H */
tools/perf/util/hist.c
浏览文件 @
7ebaa283
...
...
@@ -9,21 +9,21 @@ struct callchain_param callchain_param = {
.
min_percent
=
0
.
5
};
static
void
hist_entry__add_cpumode_
count
(
struct
hist_entry
*
self
,
unsigned
int
cpumode
,
u64
count
)
static
void
hist_entry__add_cpumode_
period
(
struct
hist_entry
*
self
,
unsigned
int
cpumode
,
u64
period
)
{
switch
(
cpumode
)
{
case
PERF_RECORD_MISC_KERNEL
:
self
->
count_sys
+=
count
;
self
->
period_sys
+=
period
;
break
;
case
PERF_RECORD_MISC_USER
:
self
->
count_us
+=
count
;
self
->
period_us
+=
period
;
break
;
case
PERF_RECORD_MISC_GUEST_KERNEL
:
self
->
count_guest_sys
+=
count
;
self
->
period_guest_sys
+=
period
;
break
;
case
PERF_RECORD_MISC_GUEST_USER
:
self
->
count_guest_us
+=
count
;
self
->
period_guest_us
+=
period
;
break
;
default:
break
;
...
...
@@ -31,7 +31,7 @@ static void hist_entry__add_cpumode_count(struct hist_entry *self,
}
/*
* histogram, sorted on item, collects
count
s
* histogram, sorted on item, collects
period
s
*/
static
struct
hist_entry
*
hist_entry__new
(
struct
hist_entry
*
template
)
...
...
@@ -41,6 +41,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
if
(
self
!=
NULL
)
{
*
self
=
*
template
;
self
->
nr_events
=
1
;
if
(
symbol_conf
.
use_callchain
)
callchain_init
(
self
->
callchain
);
}
...
...
@@ -57,7 +58,7 @@ static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry)
struct
hist_entry
*
__hists__add_entry
(
struct
hists
*
self
,
struct
addr_location
*
al
,
struct
symbol
*
sym_parent
,
u64
count
)
struct
symbol
*
sym_parent
,
u64
period
)
{
struct
rb_node
**
p
=
&
self
->
entries
.
rb_node
;
struct
rb_node
*
parent
=
NULL
;
...
...
@@ -70,7 +71,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
},
.
ip
=
al
->
addr
,
.
level
=
al
->
level
,
.
count
=
count
,
.
period
=
period
,
.
parent
=
sym_parent
,
};
int
cmp
;
...
...
@@ -82,7 +83,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
cmp
=
hist_entry__cmp
(
&
entry
,
he
);
if
(
!
cmp
)
{
he
->
count
+=
count
;
he
->
period
+=
period
;
++
he
->
nr_events
;
goto
out
;
}
...
...
@@ -99,7 +101,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
rb_insert_color
(
&
he
->
rb_node
,
&
self
->
entries
);
hists__inc_nr_entries
(
self
,
he
);
out:
hist_entry__add_cpumode_
count
(
he
,
al
->
cpumode
,
count
);
hist_entry__add_cpumode_
period
(
he
,
al
->
cpumode
,
period
);
return
he
;
}
...
...
@@ -160,7 +162,7 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
cmp
=
hist_entry__collapse
(
iter
,
he
);
if
(
!
cmp
)
{
iter
->
count
+=
he
->
count
;
iter
->
period
+=
he
->
period
;
hist_entry__free
(
he
);
return
false
;
}
...
...
@@ -203,7 +205,7 @@ void hists__collapse_resort(struct hists *self)
}
/*
* reverse the map, sort on
count
.
* reverse the map, sort on
period
.
*/
static
void
__hists__insert_output_entry
(
struct
rb_root
*
entries
,
...
...
@@ -222,7 +224,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
parent
=
*
p
;
iter
=
rb_entry
(
parent
,
struct
hist_entry
,
rb_node
);
if
(
he
->
count
>
iter
->
count
)
if
(
he
->
period
>
iter
->
period
)
p
=
&
(
*
p
)
->
rb_left
;
else
p
=
&
(
*
p
)
->
rb_right
;
...
...
@@ -239,7 +241,7 @@ void hists__output_resort(struct hists *self)
struct
hist_entry
*
n
;
u64
min_callchain_hits
;
min_callchain_hits
=
self
->
stats
.
total
*
(
callchain_param
.
min_percent
/
100
);
min_callchain_hits
=
self
->
stats
.
total
_period
*
(
callchain_param
.
min_percent
/
100
);
tmp
=
RB_ROOT
;
next
=
rb_first
(
&
self
->
entries
);
...
...
@@ -288,7 +290,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
}
static
size_t
ipchain__fprintf_graph
(
FILE
*
fp
,
struct
callchain_list
*
chain
,
int
depth
,
int
depth_mask
,
int
count
,
int
depth
,
int
depth_mask
,
int
period
,
u64
total_samples
,
int
hits
,
int
left_margin
)
{
...
...
@@ -301,7 +303,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
ret
+=
fprintf
(
fp
,
"|"
);
else
ret
+=
fprintf
(
fp
,
" "
);
if
(
!
count
&&
i
==
depth
-
1
)
{
if
(
!
period
&&
i
==
depth
-
1
)
{
double
percent
;
percent
=
hits
*
100
.
0
/
total_samples
;
...
...
@@ -516,7 +518,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
long
displacement
,
bool
color
,
u64
session_total
)
{
struct
sort_entry
*
se
;
u64
count
,
total
,
count_sys
,
count_us
,
count_guest_sys
,
count
_guest_us
;
u64
period
,
total
,
period_sys
,
period_us
,
period_guest_sys
,
period
_guest_us
;
const
char
*
sep
=
symbol_conf
.
field_sep
;
int
ret
;
...
...
@@ -524,57 +526,57 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
return
0
;
if
(
pair_hists
)
{
count
=
self
->
pair
?
self
->
pair
->
count
:
0
;
total
=
pair_hists
->
stats
.
total
;
count_sys
=
self
->
pair
?
self
->
pair
->
count
_sys
:
0
;
count_us
=
self
->
pair
?
self
->
pair
->
count
_us
:
0
;
count_guest_sys
=
self
->
pair
?
self
->
pair
->
count
_guest_sys
:
0
;
count_guest_us
=
self
->
pair
?
self
->
pair
->
count
_guest_us
:
0
;
period
=
self
->
pair
?
self
->
pair
->
period
:
0
;
total
=
pair_hists
->
stats
.
total
_period
;
period_sys
=
self
->
pair
?
self
->
pair
->
period
_sys
:
0
;
period_us
=
self
->
pair
?
self
->
pair
->
period
_us
:
0
;
period_guest_sys
=
self
->
pair
?
self
->
pair
->
period
_guest_sys
:
0
;
period_guest_us
=
self
->
pair
?
self
->
pair
->
period
_guest_us
:
0
;
}
else
{
count
=
self
->
count
;
period
=
self
->
period
;
total
=
session_total
;
count_sys
=
self
->
count
_sys
;
count_us
=
self
->
count
_us
;
count_guest_sys
=
self
->
count
_guest_sys
;
count_guest_us
=
self
->
count
_guest_us
;
period_sys
=
self
->
period
_sys
;
period_us
=
self
->
period
_us
;
period_guest_sys
=
self
->
period
_guest_sys
;
period_guest_us
=
self
->
period
_guest_us
;
}
if
(
total
)
{
if
(
color
)
ret
=
percent_color_snprintf
(
s
,
size
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
*
100
.
0
)
/
total
);
(
period
*
100
.
0
)
/
total
);
else
ret
=
snprintf
(
s
,
size
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
*
100
.
0
)
/
total
);
(
period
*
100
.
0
)
/
total
);
if
(
symbol_conf
.
show_cpu_utilization
)
{
ret
+=
percent_color_snprintf
(
s
+
ret
,
size
-
ret
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
_sys
*
100
.
0
)
/
total
);
(
period
_sys
*
100
.
0
)
/
total
);
ret
+=
percent_color_snprintf
(
s
+
ret
,
size
-
ret
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
_us
*
100
.
0
)
/
total
);
(
period
_us
*
100
.
0
)
/
total
);
if
(
perf_guest
)
{
ret
+=
percent_color_snprintf
(
s
+
ret
,
size
-
ret
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
_guest_sys
*
100
.
0
)
/
(
period
_guest_sys
*
100
.
0
)
/
total
);
ret
+=
percent_color_snprintf
(
s
+
ret
,
size
-
ret
,
sep
?
"%.2f"
:
" %6.2f%%"
,
(
count
_guest_us
*
100
.
0
)
/
(
period
_guest_us
*
100
.
0
)
/
total
);
}
}
}
else
ret
=
snprintf
(
s
,
size
,
sep
?
"%lld"
:
"%12lld "
,
count
);
ret
=
snprintf
(
s
,
size
,
sep
?
"%lld"
:
"%12lld "
,
period
);
if
(
symbol_conf
.
show_nr_samples
)
{
if
(
sep
)
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%c%lld"
,
*
sep
,
count
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%c%lld"
,
*
sep
,
period
);
else
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%11lld"
,
count
);
ret
+=
snprintf
(
s
+
ret
,
size
-
ret
,
"%11lld"
,
period
);
}
if
(
pair_hists
)
{
...
...
@@ -582,9 +584,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
double
old_percent
=
0
,
new_percent
=
0
,
diff
;
if
(
total
>
0
)
old_percent
=
(
count
*
100
.
0
)
/
total
;
old_percent
=
(
period
*
100
.
0
)
/
total
;
if
(
session_total
>
0
)
new_percent
=
(
self
->
count
*
100
.
0
)
/
session_total
;
new_percent
=
(
self
->
period
*
100
.
0
)
/
session_total
;
diff
=
new_percent
-
old_percent
;
...
...
@@ -769,10 +771,10 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
++
position
;
}
ret
+=
hist_entry__fprintf
(
h
,
pair
,
show_displacement
,
displacement
,
fp
,
self
->
stats
.
total
);
displacement
,
fp
,
self
->
stats
.
total
_period
);
if
(
symbol_conf
.
use_callchain
)
ret
+=
hist_entry__fprintf_callchain
(
h
,
fp
,
self
->
stats
.
total
);
ret
+=
hist_entry__fprintf_callchain
(
h
,
fp
,
self
->
stats
.
total
_period
);
if
(
h
->
ms
.
map
==
NULL
&&
verbose
>
1
)
{
__map_groups__fprintf_maps
(
&
h
->
thread
->
mg
,
...
...
@@ -795,7 +797,8 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
nr_entries
=
self
->
stats
.
total_period
=
0
;
self
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
]
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
...
...
@@ -812,7 +815,8 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__DSO
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
self
->
stats
.
total_period
+=
h
->
period
;
self
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
]
+=
h
->
nr_events
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
...
...
@@ -824,7 +828,8 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
{
struct
rb_node
*
nd
;
self
->
nr_entries
=
self
->
stats
.
total
=
0
;
self
->
nr_entries
=
self
->
stats
.
total_period
=
0
;
self
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
]
=
0
;
self
->
max_sym_namelen
=
0
;
for
(
nd
=
rb_first
(
&
self
->
entries
);
nd
;
nd
=
rb_next
(
nd
))
{
...
...
@@ -837,7 +842,8 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
h
->
filtered
&=
~
(
1
<<
HIST_FILTER__THREAD
);
if
(
!
h
->
filtered
)
{
++
self
->
nr_entries
;
self
->
stats
.
total
+=
h
->
count
;
self
->
stats
.
total_period
+=
h
->
period
;
self
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
]
+=
h
->
nr_events
;
if
(
h
->
ms
.
sym
&&
self
->
max_sym_namelen
<
h
->
ms
.
sym
->
namelen
)
self
->
max_sym_namelen
=
h
->
ms
.
sym
->
namelen
;
...
...
@@ -881,7 +887,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
h
->
sum
++
;
h
->
ip
[
offset
]
++
;
pr_debug3
(
"%#Lx %s:
count
++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
self
->
ms
.
sym
->
start
,
pr_debug3
(
"%#Lx %s:
period
++ [ip: %#Lx, %#Lx] => %Ld
\n
"
,
self
->
ms
.
sym
->
start
,
self
->
ms
.
sym
->
name
,
ip
,
ip
-
self
->
ms
.
sym
->
start
,
h
->
ip
[
offset
]);
return
0
;
}
...
...
@@ -1028,3 +1034,24 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
pclose
(
file
);
return
0
;
}
void
hists__inc_nr_events
(
struct
hists
*
self
,
u32
type
)
{
++
self
->
stats
.
nr_events
[
0
];
++
self
->
stats
.
nr_events
[
type
];
}
size_t
hists__fprintf_nr_events
(
struct
hists
*
self
,
FILE
*
fp
)
{
int
i
;
size_t
ret
=
0
;
for
(
i
=
0
;
i
<
PERF_RECORD_HEADER_MAX
;
++
i
)
{
if
(
!
event__name
[
i
])
continue
;
ret
+=
fprintf
(
fp
,
"%10s events: %10d
\n
"
,
event__name
[
i
],
self
->
stats
.
nr_events
[
i
]);
}
return
ret
;
}
tools/perf/util/hist.h
浏览文件 @
7ebaa283
...
...
@@ -37,9 +37,23 @@ struct sym_priv {
struct
sym_ext
*
ext
;
};
/*
* The kernel collects the number of events it couldn't send in a stretch and
* when possible sends this number in a PERF_RECORD_LOST event. The number of
* such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
* total_lost tells exactly how many events the kernel in fact lost, i.e. it is
* the sum of all struct lost_event.lost fields reported.
*
* The total_period is needed because by default auto-freq is used, so
* multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
* the total number of low level events, it is necessary to to sum all struct
* sample_event.period and stash the result in total_period.
*/
struct
events_stats
{
u64
total
;
u64
lost
;
u64
total_period
;
u64
total_lost
;
u32
nr_events
[
PERF_RECORD_HEADER_MAX
];
u32
nr_unknown_events
;
};
struct
hists
{
...
...
@@ -55,7 +69,7 @@ struct hists {
struct
hist_entry
*
__hists__add_entry
(
struct
hists
*
self
,
struct
addr_location
*
al
,
struct
symbol
*
parent
,
u64
count
);
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
*
pair_hists
,
...
...
@@ -68,6 +82,10 @@ void hist_entry__free(struct hist_entry *);
void
hists__output_resort
(
struct
hists
*
self
);
void
hists__collapse_resort
(
struct
hists
*
self
);
void
hists__inc_nr_events
(
struct
hists
*
self
,
u32
type
);
size_t
hists__fprintf_nr_events
(
struct
hists
*
self
,
FILE
*
fp
);
size_t
hists__fprintf
(
struct
hists
*
self
,
struct
hists
*
pair
,
bool
show_displacement
,
FILE
*
fp
);
...
...
tools/perf/util/newt.c
浏览文件 @
7ebaa283
...
...
@@ -9,6 +9,7 @@
#include "cache.h"
#include "hist.h"
#include "pstack.h"
#include "session.h"
#include "sort.h"
#include "symbol.h"
...
...
@@ -680,16 +681,18 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
struct
ui_progress
*
progress
;
struct
rb_node
*
nd
;
u64
curr_hist
=
0
;
char
seq
[]
=
"."
;
char
seq
[]
=
"."
,
unit
;
char
str
[
256
];
unsigned
long
nr_events
=
hists
->
stats
.
nr_events
[
PERF_RECORD_SAMPLE
];
if
(
self
->
form
)
{
newtFormDestroy
(
self
->
form
);
newtPopWindow
();
}
snprintf
(
str
,
sizeof
(
str
),
"Samples: %Ld "
,
hists
->
stats
.
total
);
nr_events
=
convert_unit
(
nr_events
,
&
unit
);
snprintf
(
str
,
sizeof
(
str
),
"Events: %lu%c "
,
nr_events
,
unit
);
newtDrawRootText
(
0
,
0
,
str
);
newtGetScreenSize
(
NULL
,
&
rows
);
...
...
@@ -718,12 +721,12 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
if
(
h
->
filtered
)
continue
;
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
hists
->
stats
.
total
);
len
=
hist_entry__append_browser
(
h
,
self
->
tree
,
hists
->
stats
.
total
_period
);
if
(
len
>
max_len
)
max_len
=
len
;
if
(
symbol_conf
.
use_callchain
)
hist_entry__append_callchain_browser
(
h
,
self
->
tree
,
hists
->
stats
.
total
,
idx
++
);
hists
->
stats
.
total
_period
,
idx
++
);
++
curr_hist
;
if
(
curr_hist
%
5
)
ui_progress__update
(
progress
,
curr_hist
);
...
...
@@ -748,6 +751,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
newtFormAddHotKey
(
self
->
form
,
'A'
);
newtFormAddHotKey
(
self
->
form
,
'a'
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_RIGHT
);
newtFormAddHotKey
(
self
->
form
,
NEWT_KEY_LEFT
);
newtFormAddComponents
(
self
->
form
,
self
->
tree
,
NULL
);
self
->
selection
=
newt__symbol_tree_get_current
(
self
->
tree
);
...
...
@@ -799,6 +803,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
int
hists__browse
(
struct
hists
*
self
,
const
char
*
helpline
,
const
char
*
input_name
)
{
struct
hist_browser
*
browser
=
hist_browser__new
();
struct
pstack
*
fstack
=
pstack__new
(
2
);
const
struct
thread
*
thread_filter
=
NULL
;
const
struct
dso
*
dso_filter
=
NULL
;
struct
newtExitStruct
es
;
...
...
@@ -808,12 +813,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
if
(
browser
==
NULL
)
return
-
1
;
fstack
=
pstack__new
(
2
);
if
(
fstack
==
NULL
)
goto
out
;
ui_helpline__push
(
helpline
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
dso_filter
,
thread_filter
);
if
(
hist_browser__populate
(
browser
,
self
,
msg
)
<
0
)
goto
out
;
goto
out
_free_stack
;
while
(
1
)
{
const
struct
thread
*
thread
;
...
...
@@ -834,6 +843,19 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
else
continue
;
}
if
(
es
.
u
.
key
==
NEWT_KEY_LEFT
)
{
const
void
*
top
;
if
(
pstack__empty
(
fstack
))
continue
;
top
=
pstack__pop
(
fstack
);
if
(
top
==
&
dso_filter
)
goto
zoom_out_dso
;
if
(
top
==
&
thread_filter
)
goto
zoom_out_thread
;
continue
;
}
}
if
(
browser
->
selection
->
sym
!=
NULL
&&
...
...
@@ -886,12 +908,15 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
hist_entry__annotate_browser
(
he
);
}
else
if
(
choice
==
zoom_dso
)
{
if
(
dso_filter
)
{
pstack__remove
(
fstack
,
&
dso_filter
);
zoom_out_dso:
ui_helpline__pop
();
dso_filter
=
NULL
;
}
else
{
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s DSO
\"
"
,
ui_helpline__fpush
(
"To zoom out press
<- or
-> +
\"
Zoom out of %s DSO
\"
"
,
dso
->
kernel
?
"the Kernel"
:
dso
->
short_name
);
dso_filter
=
dso
;
pstack__push
(
fstack
,
&
dso_filter
);
}
hists__filter_by_dso
(
self
,
dso_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
...
...
@@ -900,13 +925,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
goto
out
;
}
else
if
(
choice
==
zoom_thread
)
{
if
(
thread_filter
)
{
pstack__remove
(
fstack
,
&
thread_filter
);
zoom_out_thread:
ui_helpline__pop
();
thread_filter
=
NULL
;
}
else
{
ui_helpline__fpush
(
"To zoom out press -> +
\"
Zoom out of %s(%d) thread
\"
"
,
ui_helpline__fpush
(
"To zoom out press
<- or
-> +
\"
Zoom out of %s(%d) thread
\"
"
,
thread
->
comm_set
?
thread
->
comm
:
""
,
thread
->
pid
);
thread_filter
=
thread
;
pstack__push
(
fstack
,
&
thread_filter
);
}
hists__filter_by_thread
(
self
,
thread_filter
);
hist_browser__title
(
msg
,
sizeof
(
msg
),
input_name
,
...
...
@@ -916,6 +944,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
}
}
err
=
0
;
out_free_stack:
pstack__delete
(
fstack
);
out:
hist_browser__delete
(
browser
);
return
err
;
...
...
tools/perf/util/pstack.c
0 → 100644
浏览文件 @
7ebaa283
/*
* Simple pointer stack
*
* (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
*/
#include "util.h"
#include "pstack.h"
#include <linux/kernel.h>
#include <stdlib.h>
struct
pstack
{
unsigned
short
top
;
unsigned
short
max_nr_entries
;
void
*
entries
[
0
];
};
struct
pstack
*
pstack__new
(
unsigned
short
max_nr_entries
)
{
struct
pstack
*
self
=
zalloc
((
sizeof
(
*
self
)
+
max_nr_entries
*
sizeof
(
void
*
)));
if
(
self
!=
NULL
)
self
->
max_nr_entries
=
max_nr_entries
;
return
self
;
}
void
pstack__delete
(
struct
pstack
*
self
)
{
free
(
self
);
}
bool
pstack__empty
(
const
struct
pstack
*
self
)
{
return
self
->
top
==
0
;
}
void
pstack__remove
(
struct
pstack
*
self
,
void
*
key
)
{
unsigned
short
i
=
self
->
top
,
last_index
=
self
->
top
-
1
;
while
(
i
--
!=
0
)
{
if
(
self
->
entries
[
i
]
==
key
)
{
if
(
i
<
last_index
)
memmove
(
self
->
entries
+
i
,
self
->
entries
+
i
+
1
,
(
last_index
-
i
)
*
sizeof
(
void
*
));
--
self
->
top
;
return
;
}
}
pr_err
(
"%s: %p not on the pstack!
\n
"
,
__func__
,
key
);
}
void
pstack__push
(
struct
pstack
*
self
,
void
*
key
)
{
if
(
self
->
top
==
self
->
max_nr_entries
)
{
pr_err
(
"%s: top=%d, overflow!
\n
"
,
__func__
,
self
->
top
);
return
;
}
self
->
entries
[
self
->
top
++
]
=
key
;
}
void
*
pstack__pop
(
struct
pstack
*
self
)
{
void
*
ret
;
if
(
self
->
top
==
0
)
{
pr_err
(
"%s: underflow!
\n
"
,
__func__
);
return
NULL
;
}
ret
=
self
->
entries
[
--
self
->
top
];
self
->
entries
[
self
->
top
]
=
NULL
;
return
ret
;
}
tools/perf/util/pstack.h
0 → 100644
浏览文件 @
7ebaa283
#ifndef _PERF_PSTACK_
#define _PERF_PSTACK_
struct
pstack
;
struct
pstack
*
pstack__new
(
unsigned
short
max_nr_entries
);
void
pstack__delete
(
struct
pstack
*
self
);
bool
pstack__empty
(
const
struct
pstack
*
self
);
void
pstack__remove
(
struct
pstack
*
self
,
void
*
key
);
void
pstack__push
(
struct
pstack
*
self
,
void
*
key
);
void
*
pstack__pop
(
struct
pstack
*
self
);
#endif
/* _PERF_PSTACK_ */
tools/perf/util/session.c
浏览文件 @
7ebaa283
...
...
@@ -94,7 +94,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
self
->
mmap_window
=
32
;
self
->
cwd
=
NULL
;
self
->
cwdlen
=
0
;
self
->
unknown_events
=
0
;
self
->
machines
=
RB_ROOT
;
self
->
repipe
=
repipe
;
INIT_LIST_HEAD
(
&
self
->
ordered_samples
.
samples_head
);
...
...
@@ -241,36 +240,6 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
}
}
static
const
char
*
event__name
[]
=
{
[
0
]
=
"TOTAL"
,
[
PERF_RECORD_MMAP
]
=
"MMAP"
,
[
PERF_RECORD_LOST
]
=
"LOST"
,
[
PERF_RECORD_COMM
]
=
"COMM"
,
[
PERF_RECORD_EXIT
]
=
"EXIT"
,
[
PERF_RECORD_THROTTLE
]
=
"THROTTLE"
,
[
PERF_RECORD_UNTHROTTLE
]
=
"UNTHROTTLE"
,
[
PERF_RECORD_FORK
]
=
"FORK"
,
[
PERF_RECORD_READ
]
=
"READ"
,
[
PERF_RECORD_SAMPLE
]
=
"SAMPLE"
,
[
PERF_RECORD_HEADER_ATTR
]
=
"ATTR"
,
[
PERF_RECORD_HEADER_EVENT_TYPE
]
=
"EVENT_TYPE"
,
[
PERF_RECORD_HEADER_TRACING_DATA
]
=
"TRACING_DATA"
,
[
PERF_RECORD_HEADER_BUILD_ID
]
=
"BUILD_ID"
,
};
unsigned
long
event__total
[
PERF_RECORD_HEADER_MAX
];
void
event__print_totals
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
PERF_RECORD_HEADER_MAX
;
++
i
)
{
if
(
!
event__name
[
i
])
continue
;
pr_info
(
"%10s events: %10ld
\n
"
,
event__name
[
i
],
event__total
[
i
]);
}
}
void
mem_bswap_64
(
void
*
src
,
int
byte_size
)
{
u64
*
m
=
src
;
...
...
@@ -580,8 +549,7 @@ static int perf_session__process_event(struct perf_session *self,
dump_printf
(
"%#Lx [%#x]: PERF_RECORD_%s"
,
offset
+
head
,
event
->
header
.
size
,
event__name
[
event
->
header
.
type
]);
++
event__total
[
0
];
++
event__total
[
event
->
header
.
type
];
hists__inc_nr_events
(
&
self
->
hists
,
event
->
header
.
type
);
}
if
(
self
->
header
.
needs_swap
&&
event__swap_ops
[
event
->
header
.
type
])
...
...
@@ -619,7 +587,7 @@ static int perf_session__process_event(struct perf_session *self,
case
PERF_RECORD_FINISHED_ROUND
:
return
ops
->
finished_round
(
event
,
self
,
ops
);
default:
self
->
unknown_events
++
;
++
self
->
hists
.
stats
.
nr_unknown_events
;
return
-
1
;
}
}
...
...
tools/perf/util/session.h
浏览文件 @
7ebaa283
...
...
@@ -30,8 +30,6 @@ struct perf_session {
struct
machine
host_machine
;
struct
rb_root
machines
;
struct
rb_root
hists_tree
;
unsigned
long
event_total
[
PERF_RECORD_MAX
];
unsigned
long
unknown_events
;
/*
* FIXME: should point to the first entry in hists_tree and
* be a hists instance. Right now its only 'report'
...
...
@@ -140,4 +138,10 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
{
return
machines__fprintf_dsos_buildid
(
&
self
->
machines
,
fp
,
with_hits
);
}
static
inline
size_t
perf_session__fprintf_nr_events
(
struct
perf_session
*
self
,
FILE
*
fp
)
{
return
hists__fprintf_nr_events
(
&
self
->
hists
,
fp
);
}
#endif
/* __PERF_SESSION_H */
tools/perf/util/sort.h
浏览文件 @
7ebaa283
...
...
@@ -43,14 +43,15 @@ extern enum sort_type sort__first_dimension;
struct
hist_entry
{
struct
rb_node
rb_node
;
u64
count
;
u64
count
_sys
;
u64
count
_us
;
u64
count
_guest_sys
;
u64
count
_guest_us
;
u64
period
;
u64
period
_sys
;
u64
period
_us
;
u64
period
_guest_sys
;
u64
period
_guest_us
;
struct
map_symbol
ms
;
struct
thread
*
thread
;
u64
ip
;
u32
nr_events
;
char
level
;
u8
filtered
;
struct
symbol
*
parent
;
...
...
tools/perf/util/util.c
浏览文件 @
7ebaa283
...
...
@@ -92,3 +92,25 @@ int copyfile(const char *from, const char *to)
out:
return
err
;
}
unsigned
long
convert_unit
(
unsigned
long
value
,
char
*
unit
)
{
*
unit
=
' '
;
if
(
value
>
1000
)
{
value
/=
1000
;
*
unit
=
'K'
;
}
if
(
value
>
1000
)
{
value
/=
1000
;
*
unit
=
'M'
;
}
if
(
value
>
1000
)
{
value
/=
1000
;
*
unit
=
'G'
;
}
return
value
;
}
tools/perf/util/util.h
浏览文件 @
7ebaa283
...
...
@@ -423,6 +423,7 @@ char **argv_split(const char *str, int *argcp);
void
argv_free
(
char
**
argv
);
bool
strglobmatch
(
const
char
*
str
,
const
char
*
pat
);
bool
strlazymatch
(
const
char
*
str
,
const
char
*
pat
);
unsigned
long
convert_unit
(
unsigned
long
value
,
char
*
unit
);
#define _STR(x) #x
#define STR(x) _STR(x)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录