diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-12-17 14:54:28 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-12-18 12:18:19 +0000 |
commit | adfdca4df18f4b9d261dd865243accc868eeacc7 (patch) | |
tree | 6822b56353b8daf4cbdd8dbe4746f88751d384c5 | |
parent | 3187647d892fb5cf50158b0ceacfd9b759f695cb (diff) | |
download | poky-adfdca4df18f4b9d261dd865243accc868eeacc7.tar.gz |
buildstats: Improve to add getrusage data and corrected IO stats
Add IO stats and getrusage() data to the task statistics. We
also drop the CPU percentage calculation since its pretty arbitrary
and not very accurate/useful.
In particular we can now see the user and sys times as well as the
wall clock times.
(From OE-Core rev: b849130f71d3ba32a6fa94c291ca6ce7c7c3b3d1)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/classes/buildstats.bbclass | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/meta/classes/buildstats.bbclass b/meta/classes/buildstats.bbclass index 71469e401d..daf0b86b06 100644 --- a/meta/classes/buildstats.bbclass +++ b/meta/classes/buildstats.bbclass | |||
@@ -9,41 +9,53 @@ BUILDSTATS_BASE = "${TMPDIR}/buildstats/" | |||
9 | # | 9 | # |
10 | ################################################################################ | 10 | ################################################################################ |
11 | 11 | ||
12 | def get_process_cputime(pid): | 12 | def get_buildprocess_cputime(pid): |
13 | with open("/proc/%d/stat" % pid, "r") as f: | 13 | with open("/proc/%d/stat" % pid, "r") as f: |
14 | fields = f.readline().rstrip().split() | 14 | fields = f.readline().rstrip().split() |
15 | # 13: utime, 14: stime, 15: cutime, 16: cstime | 15 | # 13: utime, 14: stime, 15: cutime, 16: cstime |
16 | return sum(int(field) for field in fields[13:16]) | 16 | return sum(int(field) for field in fields[13:16]) |
17 | 17 | ||
18 | def get_process_cputime(pid): | ||
19 | import resource | ||
20 | with open("/proc/%d/stat" % pid, "r") as f: | ||
21 | fields = f.readline().rstrip().split() | ||
22 | stats = { | ||
23 | 'utime' : fields[13], | ||
24 | 'stime' : fields[14], | ||
25 | 'cutime' : fields[15], | ||
26 | 'cstime' : fields[16], | ||
27 | } | ||
28 | iostats = {} | ||
29 | with open("/proc/%d/io" % pid, "r") as f: | ||
30 | while True: | ||
31 | i = f.readline().strip() | ||
32 | if not i: | ||
33 | break | ||
34 | i = i.split(": ") | ||
35 | iostats[i[0]] = i[1] | ||
36 | resources = resource.getrusage(resource.RUSAGE_SELF) | ||
37 | childres = resource.getrusage(resource.RUSAGE_CHILDREN) | ||
38 | return stats, iostats, resources, childres | ||
39 | |||
18 | def get_cputime(): | 40 | def get_cputime(): |
19 | with open("/proc/stat", "r") as f: | 41 | with open("/proc/stat", "r") as f: |
20 | fields = f.readline().rstrip().split()[1:] | 42 | fields = f.readline().rstrip().split()[1:] |
21 | return sum(int(field) for field in fields) | 43 | return sum(int(field) for field in fields) |
22 | 44 | ||
23 | def set_timedata(var, d, server_time): | 45 | def set_timedata(var, d, server_time): |
24 | cputime = get_cputime() | 46 | d.setVar(var, server_time) |
25 | proctime = get_process_cputime(os.getpid()) | ||
26 | d.setVar(var, (server_time, cputime, proctime)) | ||
27 | 47 | ||
28 | def get_timedata(var, d, end_time): | 48 | def get_timedata(var, d, end_time): |
29 | timedata = d.getVar(var, False) | 49 | oldtime = d.getVar(var, False) |
30 | if timedata is None: | 50 | if oldtime is None: |
31 | return | 51 | return |
32 | oldtime, oldcpu, oldproc = timedata | 52 | return end_time - oldtime |
33 | procdiff = get_process_cputime(os.getpid()) - oldproc | ||
34 | cpudiff = get_cputime() - oldcpu | ||
35 | timediff = end_time - oldtime | ||
36 | if cpudiff > 0: | ||
37 | cpuperc = float(procdiff) * 100 / cpudiff | ||
38 | else: | ||
39 | cpuperc = None | ||
40 | return timediff, cpuperc | ||
41 | 53 | ||
42 | def set_buildtimedata(var, d): | 54 | def set_buildtimedata(var, d): |
43 | import time | 55 | import time |
44 | time = time.time() | 56 | time = time.time() |
45 | cputime = get_cputime() | 57 | cputime = get_cputime() |
46 | proctime = get_process_cputime(os.getpid()) | 58 | proctime = get_buildprocess_cputime(os.getpid()) |
47 | d.setVar(var, (time, cputime, proctime)) | 59 | d.setVar(var, (time, cputime, proctime)) |
48 | 60 | ||
49 | def get_buildtimedata(var, d): | 61 | def get_buildtimedata(var, d): |
@@ -52,7 +64,7 @@ def get_buildtimedata(var, d): | |||
52 | if timedata is None: | 64 | if timedata is None: |
53 | return | 65 | return |
54 | oldtime, oldcpu, oldproc = timedata | 66 | oldtime, oldcpu, oldproc = timedata |
55 | procdiff = get_process_cputime(os.getpid()) - oldproc | 67 | procdiff = get_buildprocess_cputime(os.getpid()) - oldproc |
56 | cpudiff = get_cputime() - oldcpu | 68 | cpudiff = get_cputime() - oldcpu |
57 | end_time = time.time() | 69 | end_time = time.time() |
58 | timediff = end_time - oldtime | 70 | timediff = end_time - oldtime |
@@ -66,13 +78,23 @@ def write_task_data(status, logfile, e, d): | |||
66 | bn = d.getVar('BUILDNAME', True) | 78 | bn = d.getVar('BUILDNAME', True) |
67 | bsdir = os.path.join(d.getVar('BUILDSTATS_BASE', True), bn) | 79 | bsdir = os.path.join(d.getVar('BUILDSTATS_BASE', True), bn) |
68 | with open(os.path.join(logfile), "a") as f: | 80 | with open(os.path.join(logfile), "a") as f: |
69 | timedata = get_timedata("__timedata_task", d, e.time) | 81 | elapsedtime = get_timedata("__timedata_task", d, e.time) |
70 | if timedata: | 82 | if elapsedtime: |
71 | elapsedtime, cpu = timedata | ||
72 | f.write(d.expand("${PF}: %s: Elapsed time: %0.2f seconds \n" % | 83 | f.write(d.expand("${PF}: %s: Elapsed time: %0.2f seconds \n" % |
73 | (e.task, elapsedtime))) | 84 | (e.task, elapsedtime))) |
85 | cpu, iostats, resources, childres = get_process_cputime(os.getpid()) | ||
74 | if cpu: | 86 | if cpu: |
75 | f.write("CPU usage: %0.1f%% \n" % cpu) | 87 | f.write("utime: %s\n" % cpu['utime']) |
88 | f.write("stime: %s\n" % cpu['stime']) | ||
89 | f.write("cutime: %s\n" % cpu['cutime']) | ||
90 | f.write("cstime: %s\n" % cpu['cstime']) | ||
91 | for i in iostats: | ||
92 | f.write("IO %s: %s\n" % (i, iostats[i])) | ||
93 | rusages = ["ru_utime", "ru_stime", "ru_maxrss", "ru_minflt", "ru_majflt", "ru_inblock", "ru_oublock", "ru_nvcsw", "ru_nivcsw"] | ||
94 | for i in rusages: | ||
95 | f.write("rusage %s: %s\n" % (i, getattr(resources, i))) | ||
96 | for i in rusages: | ||
97 | f.write("Child rusage %s: %s\n" % (i, getattr(childres, i))) | ||
76 | if status is "passed": | 98 | if status is "passed": |
77 | f.write("Status: PASSED \n") | 99 | f.write("Status: PASSED \n") |
78 | else: | 100 | else: |