forked from cfengine/cfengine-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprofile.py
More file actions
112 lines (82 loc) · 3.01 KB
/
profile.py
File metadata and controls
112 lines (82 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import os
from collections import defaultdict
def format_elapsed_time(elapsed_ns):
elapsed_ms = float(elapsed_ns) / 1e6
if elapsed_ms < 1000:
return "%.2f ms" % elapsed_ms
elif elapsed_ms < 60000:
elapsed_s = elapsed_ms / 1000.0
return "%.2fs" % elapsed_s
else:
elapsed_s = elapsed_ms / 1000.0
minutes = int(elapsed_s // 60)
seconds = int(elapsed_s % 60)
return "%dm%ds" % (minutes, seconds)
def format_label(component, event_type, ns, name):
if component == "function":
return "%s %s" % (component, name)
elif event_type == "methods":
return "bundle invocation"
elif component == "promise":
return "%s %s" % (component, event_type)
return "%s %s %s:%s" % (component, event_type, ns, name)
def format_columns(events, top):
labels = []
for event in events[:top]:
label = format_label(
event["component"], event["type"], event["namespace"], event["name"]
)
location = "%s:%s" % (event["source"], event["offset"]["line"])
time = format_elapsed_time(event["elapsed"])
labels.append((label, location, time))
return labels
def get_max_column_lengths(lines, indent=4):
max_type, max_location, max_time = 0, 0, 0
for label, location, time_ms in lines:
max_type = max(max_type, len(label))
max_location = max(max_location, len(location))
max_time = max(max_time, len(time_ms))
return max_type + indent, max_location + indent, max_time + indent
def profile_cfengine(events, args):
filter = defaultdict(list)
if args.bundles:
filter["component"].append("bundle")
filter["type"].append("methods")
if args.promises:
filter["type"] += list(
set(
event["type"]
for event in events
if event["component"] == "promise" and event["type"] != "methods"
)
)
if args.functions:
filter["component"].append("function")
# filter events
if filter is not None:
events = [
event
for field in filter.keys()
for event in events
if event[field] in filter[field]
]
# sort events
events = sorted(events, key=lambda x: x["elapsed"], reverse=True)
lines = format_columns(events, args.top)
line_format = "%-{}s %-{}s %{}s".format(*get_max_column_lengths(lines))
# print top k filtered events
print(line_format % ("Type", "Location", "Time"))
for label, location, time_ms in lines:
print(line_format % (label, location, time_ms))
def generate_callstack(data, stack_path):
with open(stack_path, "w") as f:
for event in data:
f.write("%s %d\n" % (event["callstack"], event["elapsed"]))
print(
"Successfully generated callstack at '{}'".format(os.path.abspath(stack_path))
)
print(
"Run './flamgraph {} > flamegraph.svg' to generate the flamegraph".format(
stack_path
)
)