[Zope-CVS] SVN: profilestats/trunk/src/profilestats/ initial version

Jim Fulton jim at zope.com
Mon Jan 9 19:19:50 EST 2006


Log message for revision 41244:
  initial version

Changed:
  A   profilestats/trunk/src/profilestats/
  A   profilestats/trunk/src/profilestats/SETUP.cfg
  A   profilestats/trunk/src/profilestats/__init__.py
  A   profilestats/trunk/src/profilestats/browser.py
  A   profilestats/trunk/src/profilestats/configure.zcml
  A   profilestats/trunk/src/profilestats/detail.pt
  A   profilestats/trunk/src/profilestats/profilestats-configure.zcml
  A   profilestats/trunk/src/profilestats/stats.py
  A   profilestats/trunk/src/profilestats/table.pt
  A   profilestats/trunk/src/profilestats/tree.pt

-=-
Added: profilestats/trunk/src/profilestats/SETUP.cfg
===================================================================
--- profilestats/trunk/src/profilestats/SETUP.cfg	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/SETUP.cfg	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,5 @@
+# Tell zpkg how to install the ZCML slugs.
+
+<data-files zopeskel/etc/package-includes>
+  profilestats-*.zcml
+</data-files>


Property changes on: profilestats/trunk/src/profilestats/SETUP.cfg
___________________________________________________________________
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/__init__.py
===================================================================
--- profilestats/trunk/src/profilestats/__init__.py	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/__init__.py	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1 @@
+#


Property changes on: profilestats/trunk/src/profilestats/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/browser.py
===================================================================
--- profilestats/trunk/src/profilestats/browser.py	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/browser.py	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,223 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Stats views
+
+$Id$
+"""
+import marshal, urllib, cgi
+
+from zope.app.pagetemplate import ViewPageTemplateFile
+import zope.app.form.browser
+from zope.formlib import form
+from zope import schema, interface
+
+import profilestats.stats
+
+
+class Add(form.AddForm):
+
+    form_fields = (
+        form.Field(
+            schema.Bytes(__name__='file',
+                         title=u"profile stats file"),
+            custom_widget = zope.app.form.browser.FileWidget,
+            ),
+        )
+
+    def create(self, data):
+        return profilestats.stats.Stats(marshal.loads(data['file']))
+        
+        
+class StatsView:
+
+    detail_template = ViewPageTemplateFile('detail.pt')
+    table_template = ViewPageTemplateFile('table.pt')
+    tree_template = ViewPageTemplateFile('tree.pt')
+
+    def __init__(self, stats, request):
+        self.context = stats
+        self.stats = stats.stats
+        self.request = request
+
+    def tree(self):
+        """Show profile results as a tree
+        """
+
+        class Tree(dict):
+
+            def __init__(self, name='', time=0.0):
+                self.name = name
+                self.time = time
+
+        tree = Tree()
+        for ((filename, lineno, func),
+             (direct_calls, calls, time, cummulative, callers)
+             ) in self.stats.iteritems():
+            if not calls:
+                continue
+            
+            t = tree
+            t.time += time
+            for n in filename.split('/'):
+                tn = t.get(n)
+                if tn is None:
+                    tn = t[n] = Tree(n)
+                t = tn
+                t.time += time
+
+            name = func
+            if lineno:
+                name = "(%s) %s" % (lineno, name)
+
+            url = 'detail.html?filename=%s&lineno=%s&func=%s' % (
+                urllib.quote(filename, ""), lineno, urllib.quote(func))
+
+            name = '<a href="%s">%s</a>' % (url, name)
+
+            t[name] = Tree(name, time)
+
+
+        def simplify_tree(tree):
+            while len(tree) == 1:
+                k = tree.keys()[0]
+                v = tree.pop(k)
+                tree.name += '/' + k
+                tree.update(v)
+
+            for t in tree.itervalues():
+                simplify_tree(t)
+
+        simplify_tree(tree)
+            
+        def showtree(tree, write, style=''):
+            items = sorted(tree.iteritems())
+            if items and style:
+                write('<a onclick="toggle_visibility(this);">+</a>')
+            write('%s <span class="time">%s</span>' % (tree.name, tree.time))
+            if items:
+                write("<div>")
+                for name, subtree in items:
+                    if subtree.time == 0.0:
+                        continue
+                    write("<div %s>" % style)
+                    showtree(subtree, write,
+                             'style="display:none;padding-left:2em"')
+                    write("</div>")
+                write("</div>")
+
+        results = []
+        showtree(tree, results.append)
+                
+        return self.tree_template(tree="\n".join(results))
+
+        
+    def _table_data(self):
+        table = []
+        total = 0
+        for ((filename, lineno, func),
+             (direct_calls, calls, time, cummulative, callers)
+             ) in self.stats.iteritems():
+
+            if calls < 1:
+                continue
+
+            table.append(dict(
+                calls=scalls(calls, direct_calls),
+                time=time,
+                timeper=time*1e6/calls,
+                cummulative=cummulative,
+                cummulativeper=cummulative*1e6/direct_calls,
+                link=link(filename, lineno, func),
+                ))
+            total += time
+
+        return table, total
+
+    def byTime(self):
+        data, total = self._table_data()
+        return self.table_template(
+            sortby="time",
+            total=total,
+            data=sorted(data, key=lambda row: -row['time']),
+            )
+
+    def byCumulative(self):
+        data, total = self._table_data()
+        return self.table_template(
+            sortby="cummulative",
+            total=total,
+            data=sorted(data, key=lambda row: -row['cummulative']),
+            )
+
+    def detail_data(self, filename, lineno, func):
+        stats = self.stats
+        key = (filename, int(lineno), func)
+        direct_calls, calls, time, cummulative, callers = stats[key]
+
+        callees = []
+        for (callee, callee_data) in stats.iteritems():
+            called = callee_data[-1].get(key)
+            if called is not None:
+                callees.append((callee, called))
+
+        return dict(
+            filename=filename,
+            lineno=lineno,
+            func=func,
+            scalls=scalls(calls, direct_calls),
+            time=time,
+            timeper=time*1e6/calls,
+            cummulative=cummulative,
+            cummulativeper=cummulative*1e6/direct_calls,
+            callers=[
+                (link(*caller), n,
+                 time*n/calls,
+                 (caller != key) and (cummulative*n/direct_calls) or 0,
+                 )
+                for (caller, n) in sorted(callers.iteritems())
+                ],
+            callees=[
+                (link(*callee), n,
+                 n*time_per(stats, callee),
+                 (callee != key) and (n*cummulative_per(stats, callee)) or 0,
+                 )
+                for (callee, n) in sorted(callees)
+                ],
+            )
+
+    def detail(self, filename, lineno, func):
+        return self.detail_template(**self.detail_data(filename, lineno, func))
+
+def time_per(stats, key):
+    direct_calls, calls, time, cummulative, callers = stats[key]
+    return time/calls
+
+def cummulative_per(stats, key):
+    direct_calls, calls, time, cummulative, callers = stats[key]
+    return time/direct_calls
+
+def link(filename, lineno, func):
+    url = 'detail.html?filename=%s&lineno=%s&func=%s' % (
+        urllib.quote(filename, ""), lineno, urllib.quote(func))
+    return '<a href="%s">%s(%s) %s</a>' % (
+        url,
+        cgi.escape(filename),
+        lineno,
+        cgi.escape(func),
+        )
+
+def scalls(calls, direct_calls):
+    if calls == direct_calls:
+        return str(calls)
+    return "%s/%s" % (calls, direct_calls)


Property changes on: profilestats/trunk/src/profilestats/browser.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/configure.zcml
===================================================================
--- profilestats/trunk/src/profilestats/configure.zcml	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/configure.zcml	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,63 @@
+<configure 
+    xmlns='http://namespaces.zope.org/zope'
+    xmlns:browser='http://namespaces.zope.org/browser'
+    i18n_domain="profilestats"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    >
+
+<content class=".stats.Stats">
+   <implements 
+       interface="zope.app.annotation.IAttributeAnnotatable" />
+   <require permission="zope.View" attributes="stats" />
+</content>
+
+<browser:page
+    for="zope.app.container.interfaces.IAdding"
+    name="AddProfileStats.html"
+    class=".browser.Add"
+    permission="zope.ManageContent"
+    />
+
+<browser:addMenuItem
+    class=".stats.Stats"
+    title="Profiler Statistics"
+    permission="zope.ManageContent"
+    view="AddProfileStats.html"
+    />
+
+<browser:page
+    for=".stats.IStats"
+    name="index.html"
+    menu="zmi_views" title="By File"
+    class=".browser.StatsView"
+    attribute="tree"
+    permission="zope.ManageContent"
+    />
+
+<browser:page
+    for=".stats.IStats"
+    name="byTime.html"
+    menu="zmi_views" title="By Time"
+    class=".browser.StatsView"
+    attribute="byTime"
+    permission="zope.ManageContent"
+    />
+
+<browser:page
+    for=".stats.IStats"
+    name="byCumulative.html"
+    menu="zmi_views" title="By Cummulative Time"
+    class=".browser.StatsView"
+    attribute="byCumulative"
+    permission="zope.ManageContent"
+    />
+
+<browser:page
+    for=".stats.IStats"
+    name="detail.html"
+    class=".browser.StatsView"
+    attribute="detail"
+    permission="zope.ManageContent"
+    />
+
+</configure> 


Property changes on: profilestats/trunk/src/profilestats/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/detail.pt
===================================================================
--- profilestats/trunk/src/profilestats/detail.pt	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/detail.pt	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,55 @@
+<html metal:use-macro="context/@@standard_macros/view"
+      i18n:domain="buddydemo">
+<body>
+<div metal:fill-slot="body">
+  <h2>Details for 
+      <span tal:content="options/filename">src/foo.py</span>(<span 
+          tal:content="options/lineno" >10</span>) 
+      <span tal:content="options/func">foo</span>
+  </h2>
+
+  <table>
+    <tr><td>Calls:</td>
+        <td><span tal:content="options/scalls">100/10</span></td></tr>
+    <tr><td>Time:</td>
+        <td><span tal:content="options/time">1.2</span></td></tr>
+    <tr><td>Time per call &mu;s:</td>
+        <td><span tal:content="options/timeper">1200</span></td></tr>
+    <tr><td>Cummulative time:</td>
+        <td><span tal:content="options/cummulative">4.5</span></td></tr>
+    <tr><td>Cummulative time per call &mu;s:</td>
+        <td><span tal:content="options/cummulativeper">4500</span></td></tr>
+  </table>
+
+  <div tal:condition="options/callers">
+    <h3>Callers</h3>',
+    <table border=1>
+      <tr>
+      <th>function</th>
+      <th>calls</th>
+      <th>time credited to function</th>
+      <th>cummulative time credited to function</th>
+      </tr>
+      <tr tal:repeat="row options/callers">
+          <td tal:repeat="value row" tal:content="structure value" />
+      </tr>
+    </table>
+  </div>
+
+  <div tal:condition="options/callees">
+    <h3>Callees</h3>',
+    <table border=1>
+      <tr>
+      <th>function</th>
+      <th>calls</th>
+      <th>time credited to function</th>
+      <th>cummulative time credited to function</th>
+      </tr>
+      <tr tal:repeat="row options/callees">
+          <td tal:repeat="value row" tal:content="structure value" />
+      </tr>
+    </table>
+  </div>
+
+</div>
+</body></html>


Property changes on: profilestats/trunk/src/profilestats/detail.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/profilestats-configure.zcml
===================================================================
--- profilestats/trunk/src/profilestats/profilestats-configure.zcml	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/profilestats-configure.zcml	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1 @@
+<include package="profilestats" />


Property changes on: profilestats/trunk/src/profilestats/profilestats-configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/stats.py
===================================================================
--- profilestats/trunk/src/profilestats/stats.py	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/stats.py	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Profiler statistics.
+
+$Id$
+"""
+
+import marshal
+from persistent import Persistent
+from zope import interface
+
+class IStats(interface.Interface):
+    pass # XXX working around zcml/menu bug
+
+class Stats(Persistent):
+
+    interface.implements(IStats)
+
+    def __init__(self, stats):
+        self.stats = stats


Property changes on: profilestats/trunk/src/profilestats/stats.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/table.pt
===================================================================
--- profilestats/trunk/src/profilestats/table.pt	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/table.pt	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,30 @@
+<html metal:use-macro="context/@@standard_macros/view"
+      i18n:domain="buddydemo">
+<body>
+<div metal:fill-slot="body">
+  <h2>Profile results sorted by 
+      <span tal:content="options/sortby">time</span></h2>
+
+  <p>Total time: <span tal:content="options/total">100.2</span></p>
+
+  <table border=1>
+    <tr>
+      <th>calls</th>
+      <th>time</th>
+      <th>time per call &mu;s</th>
+      <th>cummulative time</th>
+      <th>cummulative time per call &mu;s</th>
+      <th>function</th>
+    </tr>
+    <tr tal:repeat="row options/data">
+      <td class="calls" tal:content="row/calls">100/10</td>
+      <td class="time" tal:content="row/time">1.3</td>
+      <td class="timeper" tal:content="row/timeper">1300</td>
+      <td class="cummulative" tal:content="row/cummulative">4.5</td>
+      <td class="cummunlativeper" tal:content="row/cummulativeper">4500</td>
+      <td class="link" tal:content="structure row/link">%s</td>
+    </tr>
+  </table>
+
+</div>
+</body></html>


Property changes on: profilestats/trunk/src/profilestats/table.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: profilestats/trunk/src/profilestats/tree.pt
===================================================================
--- profilestats/trunk/src/profilestats/tree.pt	2006-01-10 00:17:12 UTC (rev 41243)
+++ profilestats/trunk/src/profilestats/tree.pt	2006-01-10 00:19:49 UTC (rev 41244)
@@ -0,0 +1,41 @@
+<html metal:use-macro="context/@@standard_macros/view"
+      i18n:domain="buddydemo">
+<head>
+<div metal:fill-slot="headers">
+  <script type="text/javascript" language="JavaScript1.3">
+    function toggle_visibility(element) {
+        element.normalize();
+        var label = element.childNodes[0]
+        if (label.data == '+') {
+           label.data = '-';
+        } else {
+           label.data = '+';
+        }
+
+        var lower = element.nextSibling.nextSibling.nextSibling.nextSibling
+
+        // if this is a leaf node, there is nothing to do
+        if (lower == undefined) return;
+
+        lower = lower.childNodes;
+        for (var i=0; i < lower.length; i++) {
+          child = lower[i];
+          if (child.style != undefined) {
+            if (child.style.display == 'none') {
+                child.style.display = '';
+            } else {
+                child.style.display = 'none';
+            }
+          }
+        }
+      }
+  </script>
+</div>
+</head>
+<body>
+<div metal:fill-slot="body">
+  <h2>Profile results organized by file and function</h2>
+  Total time is 
+  <div tal:replace="structure options/tree" />
+</div>
+</body></html>


Property changes on: profilestats/trunk/src/profilestats/tree.pt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Zope-CVS mailing list