Merge "Allow to setup timeout instead of waiting for OOM."
diff --git a/tools/historic_memory_usage.py b/tools/historic_memory_usage.py
index f23faaa..376426f 100755
--- a/tools/historic_memory_usage.py
+++ b/tools/historic_memory_usage.py
@@ -38,6 +38,10 @@
result.add_option('--output',
default='build',
help='Directory where to output results')
+ result.add_option('--timeout',
+ type=int,
+ default=0,
+ help='Set timeout instead of waiting for OOM.')
return result.parse_args(argv)
@@ -122,7 +126,10 @@
def run_on_app(options, commit):
app = options.app
compiler = options.compiler
- cmd = ['tools/run_on_app.py', '--app', app, '--compiler', compiler,
+ cmd = ['tools/run_on_app.py',
+ '--app', app,
+ '--compiler', compiler,
+ '--timeout', str(options.timeout),
'--no-build', '--find-min-xmx']
stdout = subprocess.check_output(cmd)
output_path = options.output or 'build'
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index 41d4578..b404dd3 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -27,6 +27,9 @@
# We use this magic exit code to signal that the program OOM'ed
OOM_EXIT_CODE = 42
+# According to Popen.returncode doc:
+# A negative value -N indicates that the child was terminated by signal N.
+TIMEOUT_KILL_CODE = -9
def ParseOptions(argv):
result = optparse.OptionParser()
@@ -58,6 +61,10 @@
help='Find the minimum amount of memory we can run in',
default=False,
action='store_true')
+ result.add_option('--timeout',
+ type=int,
+ default=0,
+ help='Set timeout instead of waiting for OOM.')
result.add_option('--golem',
help='Running on golem, do not build or download',
default=False,
@@ -178,7 +185,7 @@
assert len(args) == 0
# If we can run in 128 MB then we are good (which we can for small examples
# or D8 on medium sized examples)
- not_working = 128
+ not_working = 128 if options.compiler == 'd8' else 1024
working = 1024 * 8
exit_code = 0
while working - not_working > 32:
@@ -191,11 +198,15 @@
exit_code = run_with_options(options, [], extra_args)
t1 = time.time()
print('Running took: %s ms' % (1000.0 * (t1 - t0)))
- if exit_code != 0 and exit_code != OOM_EXIT_CODE:
- print('Non OOM error executing, exiting')
- return 2
+ if exit_code != 0:
+ if exit_code not in [OOM_EXIT_CODE, TIMEOUT_KILL_CODE]:
+ print('Non OOM/Timeout error executing, exiting')
+ return 2
if exit_code == 0:
working = next_candidate
+ elif exit_code == TIMEOUT_KILL_CODE:
+ print('Timeout. Continue to the next candidate.')
+ not_working = next_candidate
else:
assert exit_code == OOM_EXIT_CODE
not_working = next_candidate
@@ -356,7 +367,9 @@
debug=not options.no_debug,
profile=options.profile,
track_memory_file=options.track_memory_to_file,
- extra_args=extra_args, stderr=stderr)
+ extra_args=extra_args,
+ stderr=stderr,
+ timeout=options.timeout)
if exit_code != 0:
with open(stderr_path) as stderr:
stderr_text = stderr.read()
diff --git a/tools/toolhelper.py b/tools/toolhelper.py
index d7cf222..9371fb9 100644
--- a/tools/toolhelper.py
+++ b/tools/toolhelper.py
@@ -6,11 +6,12 @@
import gradle
import os
import subprocess
+from threading import Timer
import utils
def run(tool, args, build=None, debug=True,
profile=False, track_memory_file=None, extra_args=None,
- stderr=None, stdout=None, return_stdout=False):
+ stderr=None, stdout=None, return_stdout=False, timeout=0):
if build is None:
build, args = extract_build_from_args(args)
if build:
@@ -36,9 +37,20 @@
cmd.extend(["--lib", lib])
cmd.extend(args)
utils.PrintCmd(cmd)
- if return_stdout:
- return subprocess.check_output(cmd)
- return subprocess.call(cmd, stdout=stdout, stderr=stderr)
+ if timeout > 0:
+ kill = lambda process: process.kill()
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ timer = Timer(timeout, kill, [proc])
+ try:
+ timer.start()
+ stdout, stderr = proc.communicate()
+ finally:
+ timer.cancel()
+ return stdout if return_stdout else proc.returncode
+ else:
+ if return_stdout:
+ return subprocess.check_output(cmd)
+ return subprocess.call(cmd, stdout=stdout, stderr=stderr)
def run_in_tests(tool, args, build=None, debug=True, extra_args=None):
if build is None: