summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2017-05-01 14:32:33 -0700
committerGitHub <noreply@github.com>2017-05-01 14:32:33 -0700
commit094d47bff15b67d6e04b9fedf0637f3a2767cf1a (patch)
tree4422c134cf293a307bd61594b3d5679240ae2778 /bin
parentc86b53a73fca0a7d14b5a44c69034bbdd619025e (diff)
downloadspack-094d47bff15b67d6e04b9fedf0637f3a2767cf1a.tar.gz
spack-094d47bff15b67d6e04b9fedf0637f3a2767cf1a.tar.bz2
spack-094d47bff15b67d6e04b9fedf0637f3a2767cf1a.tar.xz
spack-094d47bff15b67d6e04b9fedf0637f3a2767cf1a.zip
Allow user to specify profile sort column on the command line. (#4056)
- Add -P <STAT> argument so that caller can specify a sort column for cProfile. Can specify multiple columns with commas. e.g.: spack -P cumtime,module - Add --lines option to Spack spec to control number of profile lines displayed - Sort by time by default (because it works in all Python versions) - Show sort column options in command help. - Do a short profile run in the unit tests.
Diffstat (limited to 'bin')
-rwxr-xr-xbin/spack45
1 files changed, 42 insertions, 3 deletions
diff --git a/bin/spack b/bin/spack
index c737a0f178..922e6a6be4 100755
--- a/bin/spack
+++ b/bin/spack
@@ -93,6 +93,12 @@ from llnl.util.tty.color import *
import spack
from spack.error import SpackError
import argparse
+import pstats
+
+# Get the allowed names of statistics for cProfile, and make a list of
+# groups of 7 names to wrap them nicely.
+stat_names = pstats.Stats.sort_arg_dict_default
+stat_lines = list(zip(*(iter(stat_names),)*7))
# Command parsing
parser = argparse.ArgumentParser(
@@ -120,10 +126,15 @@ parser.add_argument('-m', '--mock', action='store_true',
help="use mock packages instead of real ones")
parser.add_argument('-p', '--profile', action='store_true',
help="profile execution using cProfile")
+parser.add_argument('-P', '--sorted-profile', default=None, metavar="STAT",
+ help="profile and sort by one or more of:\n[%s]" %
+ ',\n '.join([', '.join(line) for line in stat_lines]))
+parser.add_argument('--lines', default=20, action='store',
+ help="lines of profile output: default 20; 'all' for all")
parser.add_argument('-v', '--verbose', action='store_true',
help="print additional output during builds")
parser.add_argument('-s', '--stacktrace', action='store_true',
- help="add stacktrace information to all printed statements")
+ help="add stacktrace info to all printed statements")
parser.add_argument('-V', '--version', action='version',
version="%s" % spack.spack_version)
@@ -206,9 +217,37 @@ def main(args):
# actually parse the args.
args, unknown = parser.parse_known_args()
- if args.profile:
+ if args.profile or args.sorted_profile:
import cProfile
- cProfile.runctx('_main(args, unknown)', globals(), locals())
+
+ try:
+ nlines = int(args.lines)
+ except ValueError:
+ if args.lines != 'all':
+ tty.die('Invalid number for --lines: %s' % args.lines)
+ nlines = -1
+
+ # allow comma-separated list of fields
+ sortby = ['time']
+ if args.sorted_profile:
+ sortby = args.sorted_profile.split(',')
+ for stat in sortby:
+ if stat not in stat_names:
+ tty.die("Invalid sort field: %s" % stat)
+
+ try:
+ # make a profiler and run the code.
+ pr = cProfile.Profile()
+ pr.enable()
+ _main(args, unknown)
+ finally:
+ pr.disable()
+
+ # print out profile stats.
+ stats = pstats.Stats(pr)
+ stats.sort_stats(*sortby)
+ stats.print_stats(nlines)
+
elif args.pdb:
import pdb
pdb.runctx('_main(args, unknown)', globals(), locals())