-
Notifications
You must be signed in to change notification settings - Fork 4
/
perfd.py
executable file
·97 lines (85 loc) · 3.63 KB
/
perfd.py
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
#!/usr/bin/python3
import os
import tempfile
import subprocess
import re
import db
temp_perf_file = tempfile.NamedTemporaryFile(delete=False, dir='.')
# temp_perf_file.name
os.system("perf record -e cycles:u -j any,u -a -o " +
temp_perf_file.name + " -- sleep 10")
batcmd = "perf script -F ip,dso -f -i " + temp_perf_file.name
result = subprocess.check_output(batcmd, shell=True, text=True)
lines = result.splitlines()
samples_per_obj_file = dict()
for line in lines:
cols = line.split()
name_parens = cols[1]
name = name_parens[1:-1]
if name in samples_per_obj_file:
samples_per_obj_file[name] += 1
else:
samples_per_obj_file[name] = 1
database = db.Database()
database.table = 'database'
for name in samples_per_obj_file:
database.write(
perf_name=temp_perf_file.name,
name_obj_file=name,
amount_of_samples=samples_per_obj_file[name])
database.commit()
def prepare_fdata(objfile):
fdata_files = []
records = database.read(name_obj_file = objfile) # find some sampels in the db, which have the same name_obj_file
for record in records:
fdata_file = tempfile.mktemp()
perf_name = record[0]
os.system(f"perf2bolt {objfile} -p {perf_name} -o {fdata_file}") # for every single perf files use perf2bolt
fdata_files.append(fdata_file) # add the fdata files in the list
merge_fdata = tempfile.mktemp()
os.system(f"merge-fdata {' '.join(fdata_files)} > {merge_fdata}") # merge all fdata files that i got
for fdata_file in fdata_files:
os.remove(fdata_file) # delete the mid-term fdata files and save only a last one
return merge_fdata
a = []
b = dict()
def invoke_bolt(objfile, fdata_file):
outfile = tempfile.mktemp() #create a new name for an optimized file
os.system(f"llvm-bolt {objfile} -data={fdata_file} -o {outfile} -dyno-stats") #trigger BOLT
return outfile #return an optimized file
records = database.read() #the information's from db.py
for _, name_obj_file, number_of_samples in records: #looking for obj_files which are larger or equal 100 samples
if name_obj_file in b: #count samples in an every perf_file
b[name_obj_file] += number_of_samples
else:
b[name_obj_file] = number_of_samples
for name_obj_file in b:
if b[name_obj_file] >= 100: #find obj_files which are more or equel 100 samples
if name_obj_file.split('.')[-1] != 'map' and name_obj_file[0] == "/": #skipping lines on certain conditions
a.append(name_obj_file) # add it to the list
new_list = sorted(a, key=lambda name: b[name], reverse=True) #sort object files by the numbers of samples in decreasing order
M = 1
for objfile in new_list[:M]: #for every new objfile
fdata_file = prepare_fdata(objfile) #prepare a profile
outfile = invoke_bolt(objfile, fdata_file) #trigger BOLT
os.remove(fdata_file)
print(outfile)
def get_hook(objfile):
hook = open('test_hook.txt', 'r') #create a file, there are two patterns
lines = hook.readlines() #read line by line
for line in lines:
cols = line.split() #split each line on 2 parts
pattern = cols[0]
script = cols[1]
result = re.match(pattern, objfile)
if result:
return script #if a script is found
return None #if a script isn't found
def test_hook(objfile, outfile):
hookname = get_hook(objfile) #call get_hook
if hookname == None: #if a script isn't found
return False
exit_code = os.system(f"{hookname} {objfile} {outfile}")
if exit_code == 0:
return True #if the check was succesed
return False #if the check wasn't succesed or found