9
from optparse import OptionParser
10
from signal import SIGKILL
14
DEFAULT_PROCESSES = 100
19
#process memory usage function
20
def mem_usage(process, samples=1):
23
for n in xrange(1, samples + 1):
24
pid = commands.getoutput("pidof %s" % process)
25
output = commands.getoutput("pmap -d %s" % pid)
27
raise Exception, "%s process not found" % process
29
# mapped: 0K writeable/private: 0K shared: 0K
30
lastline = output.splitlines()[-1]
31
values = lastline.split()
32
# use the mapped memory counter, remove trailing K.
33
usage = int(values[1][:-1])
39
return usage_sum / samples
41
def get_gem_objects():
42
dri = commands.getoutput("xdriinfo")
43
if not dri.startswith('Screen'):
44
print >> sys.stderr, "xdriinfo fail : %s" % (dri)
46
screen = dri.split()[1][:-1]
47
path = os.path.join("/sys/kernel/debug/dri/", screen, "i915_gem_objects")
49
# 2432 objects, 173256704 bytes
51
file = open(path, 'r');
53
print >> sys.stderr, "File %s doesn't exist" % (path)
55
objects_label, bytes_label = file.readline().split(", ")
56
objects, label = objects_label.split(" ")
59
#compare pre-test and post-test video card mem values function
60
#there is a 10% margin
61
def compare_mem_results(orig, new, margin=0.1):
62
return new < (orig + (orig * margin)) and new > (orig - (orig * margin))
64
def compare_gem_results(orig, new, margin=0.1):
65
return new < (orig * ( 1 + margin )) and new > ( orig * ( 1 - margin ))
67
def start_processes(name, number=1):
69
for n in xrange(number):
70
pid = subprocess.Popen(name).pid
75
def stop_processes(pids, signal=SIGKILL):
81
usage = "Usage: %prog [OPTIONS] PROGRAM"
82
parser = OptionParser(usage=usage)
83
parser.add_option("-m", "--margin",
84
default=DEFAULT_MARGIN,
86
help="Margin of error for memory usage (default %default)")
87
parser.add_option("-p", "--processes",
88
default=DEFAULT_PROCESSES,
90
help="Number of processes to start and stop (default %default)")
91
parser.add_option("--samples",
92
default=DEFAULT_SAMPLES,
94
help="Number of samples to get the memory usage (default %default)")
95
parser.add_option("--sleep",
96
default=DEFAULT_SLEEP,
98
help="Seconds to sleep between starting and stopping processes (default %default)")
99
(options, args) = parser.parse_args(args)
103
parser.error("Must specify a program to start")
105
parser.error("Must only specify a single program to start")
107
#Check current video card driver memory usage
108
begin_mem_usage = mem_usage("X", options.samples)
110
#Check current GEM object usage
111
begin_gem_obj = get_gem_objects()
113
#Open windows and let the system come upto speed
114
pids = start_processes(args[0], options.processes)
115
time.sleep(options.sleep)
119
time.sleep(options.sleep)
121
#Check video card driver's memory usage again to see if it returned to
122
#value found previously (give system time to normalize)
123
end_mem_usage = mem_usage("X", options.samples)
125
#Check GEM object usage again, for state after running processes
126
end_gem_obj = get_gem_objects()
128
#compare new memory value to old memory value
129
if not compare_mem_results(begin_mem_usage, end_mem_usage, options.margin):
130
return "Xorg memory leak detected, before %d and after %d" \
131
% (begin_mem_usage, end_mem_usage)
132
if not compare_gem_results(begin_gem_obj, end_gem_obj, options.margin):
133
return "DRI GEM objects leak detected, before %d and after %d" \
134
% (begin_gem_obj, end_gem_obj)
138
if __name__ == "__main__":
139
sys.exit(main(sys.argv[1:]))