[pypy-commit] jitviewer default: merge
fijal
noreply at buildbot.pypy.org
Tue Sep 24 10:00:36 CEST 2013
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r252:15e03325a227
Date: 2013-09-24 10:00 +0200
http://bitbucket.org/pypy/jitviewer/changeset/15e03325a227/
Log: merge
diff --git a/README b/README
--- a/README
+++ b/README
@@ -23,10 +23,6 @@
source code is (roughly) the same version as the binary pypy that produced
the log file.
-Finally, run it:
+For usage information, invoke jitviewer.py with --help.
- jitviewer.py log.pypylog
-
-where log.pypylog is a logfile generated by
-PYPYLOG=jit-log-opt,jit-backend:log.pypylog pypy <args>.
-An example log file comes with a checkout.
+An example log file is shipped with the jitviewer source code.
diff --git a/_jitviewer/app.py b/_jitviewer/app.py
--- a/_jitviewer/app.py
+++ b/_jitviewer/app.py
@@ -1,29 +1,32 @@
#!/usr/bin/env pypy
-""" A web-based browser of your log files. Run by
+from misc import failout
- jitviewer.py <path to your log file> [port] [--qt]
+DESCR = """Jit Viewer: A web-based browser for PyPy log files"""
-By default the script will run a web server, point your browser to
-http://localhost:5000
+EPILOG = """
+Typical usage with no existing log file:
-If you pass --qt, this script will also start a lightweight PyQT/QWebKit based
-browser pointing at the jitviewer. This assumes that CPython is installed in
-/usr/bin/python, and that PyQT with WebKit support is installed.
+ jitviewer.py --collect <your script> <arg1> ... <argn>
-Demo logfile available in this directory as 'log'.
+Typical usage with existing log file:
-To produce the logfile for your program, run:
+ jitviewer.py --log <path to your log file>
- PYPYLOG=jit-log-opt,jit-backend:mylogfile.pypylog pypy myapp.py
+where you collected a logfile by setting PYPYLOG, e.g.:
+
+ PYPYLOG=jit-log-opt,jit-backend:<path to your log file> pypy arg1 ... argn
+
+When using an existing logfile, the source code of the logged script must be
+in the same location as the logfile.
+
+Once invoked, jitviewer will run a web server. By default the the server
+listens on http://localhost:5000
+
"""
import sys
import os.path
-
-try:
- import _jitviewer
-except ImportError:
- sys.path.insert(0, os.path.abspath(os.path.join(__file__, '..', '..')))
+import argparse
try:
import pypy
@@ -33,12 +36,12 @@
try:
import pypy
except ImportError:
- raise ImportError('Could not import pypy module, make sure to '
+ failout('Could not import pypy module, make sure to '
'add the pypy module to PYTHONPATH')
import jinja2
if jinja2.__version__ < '2.6':
- raise ImportError("Required jinja version is 2.6 (the git tip), older versions might segfault PyPy")
+ failout("Required jinja version is 2.6 (the git tip), older versions might segfault PyPy")
import flask
import inspect
@@ -199,26 +202,58 @@
orig___init__(self2, *args, **kwds)
BaseServer.__init__ = __init__
+def collect_log(args):
+ """ Collect a log file using pypy """
+ import tempfile, subprocess
+
+ print("Collecting log with: %s" % ' '.join(args))
+
+ # create a temp file, possibly racey, but very unlikey
+ (fd, path) = tempfile.mkstemp(prefix="jitviewer-")
+ os.close(fd) # just the filename we want
+
+ # possibly make this configurable if someone asks...
+ os.environ["PYPYLOG"] = "jit-log-opt,jit-backend:%s" % (path, )
+ print("Collecting log in '%s'..." % path)
+ p = subprocess.Popen([sys.executable] + args, env=os.environ).communicate()
+
+ # We don't check the return status. The user may want to see traces
+ # for a failing program!
+ return os.path.abspath(path)
+
def main(argv, run_app=True):
- if not '__pypy__' in sys.builtin_module_names:
- print "Please run it using pypy-c"
- sys.exit(1)
- #
- server_mode = True
- if '--qt' in argv:
- server_mode = False
- argv.remove('--qt')
- #
- if len(argv) != 2 and len(argv) != 3:
- print __doc__
- sys.exit(1)
- filename = argv[1]
- extra_path = os.path.dirname(filename)
- if len(argv) != 3:
- port = 5000
+ parser = argparse.ArgumentParser(
+ description = DESCR,
+ epilog = EPILOG,
+ formatter_class=argparse.RawDescriptionHelpFormatter
+ )
+
+ parser.add_argument("-l", "--log", help="specify existing logfile")
+ parser.add_argument("-c", "--collect", nargs=argparse.REMAINDER, help="collect logfile now", metavar="ARG")
+ parser.add_argument("-p", "--port", help="select HTTP port", type=int)
+ parser.add_argument("-q", "--qt", action="store_true", help="use embedded QT browser")
+
+ args = parser.parse_args()
+
+ if args.port is None:
+ args.port = 5000
+
+ if args.collect is not None:
+ if len(args.collect) < 1:
+ failout("please correctly specify invokation to collect log")
+ filename = collect_log(args.collect)
+ extra_path = os.path.dirname(args.collect[0]) # add dirname of script to extra_path
+ elif args.log is not None:
+ filename = args.log
+ # preserving behaviour before argparse
+ # XXX not robust as it could be. Assumes the logfile is in the same
+ # dir as the source code, may not be the case.
+ extra_path = os.path.dirname(filename)
else:
- port = int(argv[2])
+ failout("please specify either --log or --collect")
+
storage = LoopStorage(extra_path)
+
log, loops = import_log(filename, ParserWithHtmlRepr)
parse_log_counts(extract_category(log, 'jit-backend-count'), loops)
storage.loops = [loop for loop in loops
@@ -231,12 +266,12 @@
app.route('/loop')(server.loop)
if run_app:
def run():
- app.run(use_reloader=bool(os.environ.get('JITVIEWER_USE_RELOADER', True)), host='0.0.0.0', port=port)
+ app.run(use_reloader=bool(os.environ.get('JITVIEWER_USE_RELOADER', False)), host='0.0.0.0', port=args.port)
- if server_mode:
+ if not args.qt:
run()
else:
- url = "http://localhost:%d/" % port
+ url = "http://localhost:%d/" % args.port
run_server_and_browser(app, run, url, filename)
else:
return app
diff --git a/_jitviewer/misc.py b/_jitviewer/misc.py
new file mode 100644
--- /dev/null
+++ b/_jitviewer/misc.py
@@ -0,0 +1,5 @@
+import sys
+
+def failout(msg, exit_status = 1):
+ print("error: %s" % (msg, ))
+ sys.exit(exit_status)
diff --git a/_jitviewer/static/style.css b/_jitviewer/static/style.css
--- a/_jitviewer/static/style.css
+++ b/_jitviewer/static/style.css
@@ -232,17 +232,16 @@
font-weight: bold;
}
+.menu {
+ background: #cccccc;
+ text-color: red;
+}
+
+h1 {
+ padding: 10px 10px 10px 10px;
+ background: #ffcc66;
+ font-size: 25px;
+}
+
/* End of Formatting
-----------------------------------------*/
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/_jitviewer/templates/index.html b/_jitviewer/templates/index.html
--- a/_jitviewer/templates/index.html
+++ b/_jitviewer/templates/index.html
@@ -19,15 +19,18 @@
</head>
<body>
<header>
- <span>Menu</span><br/>
+ <div class="menu">Menu</div>
<a id="asmtoggler" href="#">Show assembler [a]</a><br>
<a id="bytecodepos_toggler" href="#">Show bytecode position [b]</a>
<div id="callstack">
</div>
</header>
+ <h1>JIT Viewer</h1>
+ <!--
<div id="title">
<span id="title-text">JIT viewer</span>
</div>
+ -->
<div id="filter">
Filter [/]: <input id="inp-bar" type="text" size="80"></input>
<div>
diff --git a/bin/jitviewer.py b/bin/jitviewer.py
--- a/bin/jitviewer.py
+++ b/bin/jitviewer.py
@@ -1,4 +1,15 @@
#!/usr/bin/env pypy
import sys
+import os.path
+
+script_path = os.path.abspath(__file__)
+pythonpath = os.path.dirname(os.path.dirname(script_path))
+sys.path.append(pythonpath)
+
+# Check we are running with PyPy first.
+if not '__pypy__' in sys.builtin_module_names:
+ from _jitviewer.misc import failout
+ failout("jitviewer must be run with PyPy")
+
from _jitviewer.app import main
main(sys.argv)
More information about the pypy-commit
mailing list