import subprocess
import sys
import resource
from optparse import OptionParser
import time
import re
import tempfile
import os
from xml.dom import minidom
DATA_LIMIT = None
CPU_LIMIT = None
def run_sim(args):
argv = ['python', 'flowmon-bench.py'] + args
results_fname = tempfile.mktemp(prefix='results', suffix='.xml')
argv.append("--Results=%s" % results_fname)
print >> sys.stderr, "popen ", repr(argv)
start_time = time.time()
def preexec_fn(*dummy_args):
resource.setrlimit(resource.RLIMIT_DATA, (DATA_LIMIT, -1))
resource.setrlimit(resource.RLIMIT_AS, (DATA_LIMIT, -1))
resource.setrlimit(resource.RLIMIT_CPU, (CPU_LIMIT, -1))
proc = subprocess.Popen(argv, preexec_fn=preexec_fn)
max_mem = 0
while 1:
if proc.poll() is not None:
break
time.sleep(1.0)
mem = int(open("/proc/%i/statm" % proc.pid, "rt").read().split()[0])*4
if mem > max_mem:
max_mem = mem
retval = proc.wait()
end_time = time.time()
if retval:
raise RuntimeError("Simulation exited with code %i.\t" % (retval,))
if os.path.exists(results_fname):
results = minidom.parse(results_fname)
os.unlink(results_fname)
else:
results = None
return max_mem, (end_time - start_time), results
def main():
parser = OptionParser()
parser.add_option("-j", None, dest="concurrency", default="2",
help="Number of tasks to run in parallel")
parser.add_option("-c", "--cpu-limit", dest="cpu_limit", default="5",
help="CPU limit, in hours")
parser.add_option("-m", "--memory-limit", dest="mem_limit", default="detect",
help="Memory limit, total, in GigaBytes. "
"Actual per-process memory limit will be this value divided"
" by the concurrency level setting.")
parser.add_option("-s", "--stop-time", dest="stop_time", default="300",
help="Simulation stop time (s)")
(options, args) = parser.parse_args()
global CPU_LIMIT, DATA_LIMIT
CPU_LIMIT = long(float(options.cpu_limit)*60*60)
if options.mem_limit == 'detect':
for line in file("/proc/meminfo"):
m = re.match("MemTotal:\s+(\d+) kB", line)
if m:
DATA_LIMIT = 1024*long(m.group(1))
print >> sys.stderr, "Detected DATA_LIMIT = ", DATA_LIMIT, "(%s GiB)" % (DATA_LIMIT/1024.0/1024.0/1024.0)
break
else:
print >> sys.stderr, "Could not detect DATA_LIMIT => fallback to 512 MB."
DATA_LIMIT = long(float(0.5)*1024*1024*1024)
else:
DATA_LIMIT = long(float(options.mem_limit)*1024*1024*1024)
DATA_LIMIT /= int(int(options.concurrency)*1.25)
print >> sys.stderr, "Per-process data limit: %.3f GiB (%r)" % (DATA_LIMIT/1024.0/1024.0/1024.0, DATA_LIMIT)
newdoc = minidom.getDOMImplementation().createDocument(None, "flowmon-bench-results", None)
results_root_el = newdoc.documentElement
for num_nodes_side in range(2,11):
for run_number in range(10):
for enable_monitor in [False, True]:
args = ["--NumNodesSide=%i" % num_nodes_side,
"--RunNumber=%i" % run_number,
"--EnableMonitor=%i" % enable_monitor,
"--StopTime=%s" % options.stop_time,
]
max_mem, duration, results = run_sim(args)
simulation_el = results_root_el.appendChild(newdoc.createElement('simulation'))
simulation_el.setAttribute("num-nodes-side", str(num_nodes_side))
simulation_el.setAttribute("run-number", str(run_number))
simulation_el.setAttribute("enable-monitor", str(enable_monitor))
simulation_el.setAttribute("max-memory", str(max_mem))
simulation_el.setAttribute("cpu-time", str(duration))
if enable_monitor:
simulation_el.appendChild(results.documentElement.cloneNode(True))
out = open("results.xml", "wt")
newdoc.writexml(out, addindent=' ', newl='\n', encoding='utf-8')
out.close()
if __name__ == '__main__':
main()