[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