[Checkins] SVN: z3ext.profiler/ initial import
Nikolay Kim
fafhrd at datacom.kz
Fri Mar 28 06:37:09 EDT 2008
Log message for revision 84988:
initial import
Changed:
A z3ext.profiler/
A z3ext.profiler/branches/
A z3ext.profiler/tags/
A z3ext.profiler/trunk/
A z3ext.profiler/trunk/CHANGES.txt
A z3ext.profiler/trunk/LICENSE.txt
A z3ext.profiler/trunk/setup.py
A z3ext.profiler/trunk/src/
A z3ext.profiler/trunk/src/z3ext/
A z3ext.profiler/trunk/src/z3ext/__init__.py
A z3ext.profiler/trunk/src/z3ext/profiler/
A z3ext.profiler/trunk/src/z3ext/profiler/DMstats.py
A z3ext.profiler/trunk/src/z3ext/profiler/__init__.py
A z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml
A z3ext.profiler/trunk/src/z3ext/profiler/profiler.py
A z3ext.profiler/trunk/src/z3ext/profiler/view.pt
A z3ext.profiler/trunk/src/z3ext/profiler/view.py
-=-
Added: z3ext.profiler/trunk/CHANGES.txt
===================================================================
--- z3ext.profiler/trunk/CHANGES.txt (rev 0)
+++ z3ext.profiler/trunk/CHANGES.txt 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,16 @@
+=======
+CHANGES
+=======
+
+1.1.0 (2008-03-28)
+------------------
+
+- python2.5 support
+
+- code moved to svn.zope.org
+
+
+1.0.0 (2008-02-04)
+------------------
+
+- Initial release.
Added: z3ext.profiler/trunk/LICENSE.txt
===================================================================
--- z3ext.profiler/trunk/LICENSE.txt (rev 0)
+++ z3ext.profiler/trunk/LICENSE.txt 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+ accompanying copyright notice, this list of conditions,
+ and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+ copyright notice, this list of conditions, and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+ endorse or promote products derived from this software
+ without prior written permission from the copyright
+ holders.
+
+4. The right to distribute this software or to use it for
+ any purpose does not give you the right to use
+ Servicemarks (sm) or Trademarks (tm) of the copyright
+ holders. Use of them is covered by separate agreement
+ with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+ files to carry prominent notices stating that you changed
+ the files and the date of any change.
+
+Disclaimer
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+ AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
Added: z3ext.profiler/trunk/setup.py
===================================================================
--- z3ext.profiler/trunk/setup.py (rev 0)
+++ z3ext.profiler/trunk/setup.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Setup for z3ext.profiler package
+
+$Id$
+"""
+import sys, os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version='1.1.0'
+
+
+setup(name = 'z3ext.profiler',
+ version = version,
+ author = 'Nikolay Kim',
+ author_email = 'fafhrd91 at gmail.com',
+ description = "Simple profiler for zope3.",
+ long_description = (read('CHANGES.txt')),
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Framework :: Zope3'],
+ url='http://z3ext.net/',
+ license='ZPL 2.1',
+ packages=find_packages('src'),
+ package_dir = {'':'src'},
+ namespace_packages=['z3ext'],
+ install_requires = ['setuptools',
+ 'zope.interface',
+ 'zope.component',
+ 'zope.app.wsgi',
+ 'zope.app.folder',
+ 'zope.app.publisher',
+ ],
+ include_package_data = True,
+ zip_safe = False
+ )
Property changes on: z3ext.profiler/trunk/setup.py
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id
Added: z3ext.profiler/trunk/src/z3ext/__init__.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/__init__.py (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/__init__.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,6 @@
+# namespace package boilerplate
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError, e:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
Property changes on: z3ext.profiler/trunk/src/z3ext/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3ext.profiler/trunk/src/z3ext/profiler/DMstats.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/DMstats.py (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/DMstats.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,91 @@
+# Copyright (C) 2006 by Dr. Dieter Maurer, Eichendorffstr. 23, D-66386 St. Ingbert, Germany
+# see "LICENSE.txt" for details
+# $Id$
+''''Stats' enhancements.
+
+The module defines 'Stats' which inherits from Pythons 'Stats'
+and enhances it by methods 'showCallees(funRe)', 'showCallers(funRe)'
+and 'showStats(funRe)' which extracts information for functions
+matched by the regular expression *funRe*.
+This can make profile analysis significantly easier.
+'''
+
+from pstats import Stats as pStats
+from sys import stdout
+from re import compile
+from StringIO import StringIO
+
+
+class Stats(pStats):
+
+ def setOutputFile(self, file):
+ self._out = file
+
+ def showCallees(self, *amount):
+ msg, fs = self._selectFunctions(amount)
+ self._print(msg)
+ for f in fs: self._showCallees(f); self._print('\n')
+
+ def showStats(self, *amount):
+ msg, fs = self._selectFunctions(amount)
+ self._print(msg)
+ for f in fs: self._showStats(f)
+
+ def showCallers(self, *amount):
+ msg, fs = self._selectFunctions(amount)
+ self._print(msg)
+ for f in fs: self._showCallers(f); self._print('\n')
+
+ def _selectFunctions(self, amount):
+ if self.fcn_list:
+ l = self.fcn_list
+ msg = " Ordered by: " + self.sort_type + '\n'
+ else:
+ l = self.stats.keys()
+ msg = " Unordered\n"
+ for sel in amount:
+ l, msg = self.eval_print_amount(sel, l, msg)
+ return msg, l
+
+ def _showCallees(self, f):
+ self._showStats(f)
+ self.calc_callees()
+ callees = self.all_callees.get(f)
+ if not callees: return
+ stats = self.stats; format = self._formatFunction
+ for (cf, calls) in callees.iteritems():
+ scf = stats[cf]
+ try:
+ self._print('\t%4dc\t(of %4dc in %8.3fs)\t%s\n'
+ % (calls, scf[1], scf[3], format(cf), ))
+ except:
+ self._print('\t%4dc\t(of %4dc in %8.3fs)\t%s\n'
+ % (calls[0], scf[1], scf[3], format(cf), ))
+
+ def _showCallers(self, f):
+ self._showStats(f)
+ stats = self.stats; format = self._formatFunction
+ mstat = stats[f]
+ for (cf, calls) in mstat[4].iteritems():
+ scf = stats[cf]
+ try:
+ self._print('\t%4dc\t(from %4dc in %8.3fs)\t%s\n'
+ % (calls, scf[1], scf[3], format(cf), )
+ )
+ except:
+ self._print('\t%4dc\t(from %4dc in %8.3fs)\t%s\n'
+ % (calls[0], scf[1], scf[3], format(cf), )
+ )
+
+ def _formatFunction(self, ft):
+ return '%s:%s(%s)' % ft
+
+ def _showStats(self, ft):
+ s = self.stats[ft]
+ self._print('%4dc - %8.3fs %8.3fs/c - %8.3fs %8.3fs/c - %s\n' % (
+ s[1], s[2], s[2]/s[1], s[3], s[3]/s[1], self._formatFunction(ft),
+ )
+ )
+
+ def _print(self, txt):
+ self._out.write(txt)
Property changes on: z3ext.profiler/trunk/src/z3ext/profiler/DMstats.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3ext.profiler/trunk/src/z3ext/profiler/__init__.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/__init__.py (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/__init__.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.
Property changes on: z3ext.profiler/trunk/src/z3ext/profiler/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/configure.zcml 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,14 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <browser:page
+ name="z3ext.profiler"
+ for="zope.app.folder.interfaces.IRootFolder"
+ template="view.pt"
+ class=".view.Profiler"
+ title="Profiler"
+ menu="zmi_actions"
+ permission="zope.ManageServices" />
+
+</configure>
Added: z3ext.profiler/trunk/src/z3ext/profiler/profiler.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/profiler.py (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/profiler.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,81 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+import time
+import cProfile
+from threading import RLock
+
+from zope.app.wsgi import WSGIPublisherApplication
+
+from DMstats import Stats
+
+_lock = RLock()
+_calls = 1
+_stats = {}
+
+
+def monkey_call(self, environ, start_response):
+ if (environ.get('HTTP_REFERER', '').endswith('z3ext.profiler') or
+ environ.get('REQUEST_URI', '').endswith('z3ext.profiler')):
+ return orig_call(self, environ, start_response)
+
+ prof = cProfile.Profile(time.time)
+ response = prof.runcall(orig_call, self, environ, start_response)
+
+ lock= _lock
+
+ lock.acquire()
+ try:
+ global _stats
+
+ uri = environ.get('REQUEST_URI', '')
+
+ if _stats.has_key(uri):
+ _stats[uri][0].add(prof)
+ _stats[uri][2] = _stats[uri][2] + 1
+ else:
+ _stats[uri] = ([Stats(prof), environ, 1])
+ finally:
+ global _calls
+ if _calls > 0:
+ _calls = _calls - 1
+
+ if _calls <= 0:
+ WSGIPublisherApplication.__call__ = orig_call
+
+ lock.release()
+
+ return response
+
+
+orig_call = WSGIPublisherApplication.__call__
+
+
+def getStats():
+ return _stats
+
+
+def installProfiler(calls):
+ global _calls, _stats
+
+ _calls = calls
+ _stats = {}
+
+ WSGIPublisherApplication.__call__ = monkey_call
+
+def uninstallProfiler(calls):
+ WSGIPublisherApplication.__call__ = orig_call
Property changes on: z3ext.profiler/trunk/src/z3ext/profiler/profiler.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3ext.profiler/trunk/src/z3ext/profiler/view.pt
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/view.pt (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/view.pt 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,104 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ metal:use-macro="context/@@standard_macros/view">
+
+ <body>
+ <metal:block fill-slot="body"
+ tal:define="stats view/listStats">
+ <h1>z3ext Profiler</h1>
+
+ <form method="post" action="z3ext.profiler">
+ <div>
+ Enable profiler
+ <div>
+ <input type="text" size="2" name="calls:int"
+ tal:attributes="value request/calls|string:2" />
+ <input type="submit" name="profile.install" value="Enable" />
+ <input type="submit" name="profile.reload" value="Reload" />
+ </div>
+ </div>
+ </form>
+
+ <br /><br />
+ <hr />
+
+ <div tal:condition="stats">
+ <form method="post" action="z3ext.profiler">
+ <table>
+ <tr>
+ <td>Select request:</td>
+ <td><select name="stats" tal:define="default request/stats|nothing">
+ <option tal:repeat="stat stats"
+ tal:attributes="value stat/uri;
+ selected python:stat['uri'] == default"
+ tal:content="string:${stat/uri} (${stat/calls} calls)"></option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>Number of records:</td>
+ <td><input type="text" name="limit:int"
+ tal:attributes="value request/limit|string:500" />
+ </td>
+ </tr>
+ <tr>
+ <td>Mode:</td>
+ <td>
+ <select name="mode"
+ tal:define="default request/mode|string:stats">
+ <option tal:repeat="item python:('stats', 'callees', 'callers')"
+ tal:content="item"
+ tal:attributes="value item; selected python:item == default">
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>Sort on:</td>
+ <td><select name="sorton"
+ tal:define="default request/sorton|string:time">
+ <option tal:repeat="item python:(
+ ('time', 'internal time'),
+ ('cumulative', 'cumulative time'),
+ ('calls', 'call count'),
+ ('pcalls', 'primitive call count'),
+ ('name', 'function name'),
+ ('file', 'file name'),
+ ('module', 'module name'),
+ ('line', 'line number'),
+ ('nfl', 'name/file/line'),
+ ('stdname', 'standard name'))"
+ tal:attributes="value python:item[0];
+ selected python:item[0] == default"
+ tal:content="python:item[1]"></option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>Stdname regexp:</td>
+ <td><input name="stdnameRe"
+ tal:attributes="value request/stdnameRe|nothing"></td>
+ </tr>
+ <tr>
+ <td>Strip dirs:</td>
+ <td><input type="checkbox" name="stripdirs:bool"
+ tal:attributes="checked request/stripdirs|nothing" />
+ </td>
+ </tr>
+ </table>
+
+ <br />
+ <input type="submit" name="view_stats" value="Update" />
+ </form>
+
+ <br />
+ <br />
+ <pre tal:content="view/viewStats"></pre>
+ </div>
+ <div tal:condition="not:stats">
+ There are no any statistics.
+ </div>
+
+ </metal:block>
+ </body>
+</html>
Added: z3ext.profiler/trunk/src/z3ext/profiler/view.py
===================================================================
--- z3ext.profiler/trunk/src/z3ext/profiler/view.py (rev 0)
+++ z3ext.profiler/trunk/src/z3ext/profiler/view.py 2008-03-28 10:37:09 UTC (rev 84988)
@@ -0,0 +1,84 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+import sys
+from cStringIO import StringIO
+from profiler import getStats, installProfiler, uninstallProfiler
+
+
+class Profiler(object):
+
+ def listStats(self):
+ stats = []
+ for uri, info in getStats().items():
+ stats.append({'uri': uri, 'calls': info[2]})
+
+ return stats
+
+ def viewStats(self):
+ stats = getStats()
+ request = self.request
+
+ if not stats:
+ return ''
+
+ uri = request.get('stats', None)
+
+ info = stats.get(uri)
+ if not info:
+ info = stats.items()[0][1]
+
+ stats = info[0]
+
+ output = StringIO()
+
+ stripdirs = request.get('stripdirs', False)
+ if stripdirs:
+ stats.strip_dirs()
+
+ sorton = request.get('sorton', 'time')
+ stats.sort_stats(sorton)
+
+ mode = request.get('mode', 'stats')
+ stdnameRe = request.get('stdnameRe', '')
+ limit = int(request.get('limit', 500))
+
+ if stdnameRe:
+ stats.setOutputFile(output)
+ getattr(stats, 'show%s' % mode.capitalize())(str(stdnameRe), limit)
+ res = output.getvalue()
+ if not res:
+ res = 'No matching functions'
+ return res
+ else:
+ stats.stream = output
+
+ try:
+ getattr(stats, 'print_%s'%mode)(limit)
+ finally:
+ pass
+
+ return output.getvalue()
+
+ def __call__(self):
+ request = self.request
+
+ if 'profile.install' in request:
+ calls = int(request.get('calls', 2))
+ installProfiler(calls)
+
+ return self.index()
Property changes on: z3ext.profiler/trunk/src/z3ext/profiler/view.py
___________________________________________________________________
Name: svn:keywords
+ Id
More information about the Checkins
mailing list