[hg] galaxy 1576: Add a memdump page to the admin controller, ma...

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[hg] galaxy 1576: Add a memdump page to the admin controller, ma...

Nate Coraor (nate@bx.psu.edu)
details:   http://www.bx.psu.edu/hg/galaxy/rev/8eec48aaca6e
changeset: 1576:8eec48aaca6e
user:      Nate Coraor <[hidden email]>
date:      Mon Oct 27 17:03:50 2008 -0400
description:
Add a memdump page to the admin controller, makes heapy output slightly
browsable and provides an entry point to heapy (via editing the
template) while the server is running.

4 file(s) affected in this change:

lib/galaxy/app.py
lib/galaxy/util/memdump.py
lib/galaxy/web/controllers/admin.py
templates/admin/memdump.mako

diffs (174 lines):

diff -r 415cc6dc8e35 -r 8eec48aaca6e lib/galaxy/app.py
--- a/lib/galaxy/app.py Mon Oct 27 16:03:43 2008 -0400
+++ b/lib/galaxy/app.py Mon Oct 27 17:03:50 2008 -0400
@@ -35,6 +35,7 @@
         self.job_queue = jobs.JobQueue( self, job_dispatcher )
         self.job_stop_queue = jobs.JobStopQueue( self, job_dispatcher )
         self.heartbeat = None
+        self.memdump = None
         # Start the heartbeat process if configured and available
         if self.config.use_heartbeat:
             from galaxy.util import heartbeat
diff -r 415cc6dc8e35 -r 8eec48aaca6e lib/galaxy/util/memdump.py
--- a/lib/galaxy/util/memdump.py Mon Oct 27 16:03:43 2008 -0400
+++ b/lib/galaxy/util/memdump.py Mon Oct 27 17:03:50 2008 -0400
@@ -22,22 +22,29 @@
             self.fname = fname
             signal.signal( signum, self.dump )
             self.heapy = guppy.hpy()
+            self.heap = None
         def dump( self, signum, stack ):
             file = open( self.fname, "a" )
             print >> file, "Memdump for pid %d at %s" % ( os.getpid(), time.asctime() )
             print >> file
             try:
-                h = self.heapy.heap()
+                self.heap = self.heapy.heap()
                 print >> file, "heap():"
-                print >> file, h
+                print >> file, self.heap
                 print >> file, "\nbyrcs:"
-                print >> file, h.byrcs
+                print >> file, self.heap.byrcs
                 print >> file, "\nbyrcs[0].byid:"
-                print >> file, h.byrcs[0].byid
+                print >> file, self.heap.byrcs[0].byid
                 print >> file, "\nget_rp():"
-                print >> file, h.get_rp()
+                print >> file, self.heap.get_rp()
                 self.heapy.setref()
             except AssertionError:
                 pass
             print >> file, "\nEnd dump\n"
             file.close()
+        def setref( self ):
+            self.heapy.setref()
+        def get( self, update=False ):
+            if update:
+                self.heap = self.heapy.heap()
+            return self.heap
diff -r 415cc6dc8e35 -r 8eec48aaca6e lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py Mon Oct 27 16:03:43 2008 -0400
+++ b/lib/galaxy/web/controllers/admin.py Mon Oct 27 17:03:50 2008 -0400
@@ -22,3 +22,42 @@
         else:
             msg = 'Invalid password'
         return msg
+    @web.expose
+    def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ):
+        if self.app.memdump is None:
+            return trans.show_error_message( "Memdump is not enabled (set <code>use_memdump = True</code> in universe_wsgi.ini)" )
+        heap = self.app.memdump.get()
+        p = util.Params( kwd )
+        msg = None
+        if p.dump:
+            heap = self.app.memdump.get( update = True )
+            msg = "Heap dump complete"
+        elif p.setref:
+            self.app.memdump.setref()
+            msg = "Reference point set (dump to see delta from this point)"
+        ids = ids.split( ',' )
+        sorts = sorts.split( ',' )
+        if new_id is not None:
+            ids.append( new_id )
+            sorts.append( 'None' )
+        elif new_sort is not None:
+            sorts[-1] = new_sort
+        breadcrumb = "<a href='%s' class='breadcrumb'>heap</a>" % web.url_for()
+        # new lists so we can assemble breadcrumb links
+        new_ids = []
+        new_sorts = []
+        for id, sort in zip( ids, sorts ):
+            new_ids.append( id )
+            if id != 'None':
+                breadcrumb += "<a href='%s' class='breadcrumb'>[%s]</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id )
+                heap = heap[int(id)]
+            new_sorts.append( sort )
+            if sort != 'None':
+                breadcrumb += "<a href='%s' class='breadcrumb'>.by('%s')</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), sort )
+                heap = heap.by( sort )
+        ids = ','.join( new_ids )
+        sorts = ','.join( new_sorts )
+        if p.theone:
+            breadcrumb += ".theone"
+            heap = heap.theone
+        return trans.fill_template( '/admin/memdump.mako', heap = heap, ids = ids, sorts = sorts, breadcrumb = breadcrumb, msg = msg )
diff -r 415cc6dc8e35 -r 8eec48aaca6e templates/admin/memdump.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/admin/memdump.mako Mon Oct 27 17:03:50 2008 -0400
@@ -0,0 +1,75 @@
+<%inherit file="/base.mako"/>
+
+<%def name="title()">Memory Profiling</%def>
+<%
+    import re
+    from xml.sax.saxutils import escape, unescape
+%>
+
+<style type="text/css">
+    a.breadcrumb:link,
+    a.breadcrumb:visited,
+    a.breadcrumb:active {
+        text-decoration: none;
+    }
+    a.breadcrumb:hover {
+        text-decoration: underline;
+    }
+</style>
+
+<h2>Memory Profiling</h2>
+
+<ul class="manage-table-actions">
+    <li><a class="action-button" href="${h.url_for( controller='admin', action='memdump', dump=True )}">Dump memory (warning: hangs server!)</a></li>
+    <li><a class="action-button" href="${h.url_for( controller='admin', action='memdump', setref=True )}">Set reference point</a></li>
+</ul>
+
+<%def name="htmlize( heap )">
+<%
+    s = escape( str( heap ) )
+    new_s = ""
+    id_re = re.compile('^(\s+)([0-9]+)')
+    for line in s.split( '\n' ):
+        try:
+            id = id_re.search( line ).group( 2 )
+        except:
+            id = None
+        new_s += re.sub( id_re, r'\1<a href="' + h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_id=id ) + r'">\2</a>', line )
+        if id and heap[int(id)].count == 1:
+            new_s += " <a href='%s'>theone</a>\n" % h.url_for( ids=ids, sorts=sorts, new_id=id, theone=True )
+        else:
+            new_s += "\n"
+    return new_s
+%>
+</%def>
+
+%if msg:
+    <div class="donemessage">${msg}</div>
+%endif
+
+%if heap is None:
+    No memory dump available.  Click "Dump memory" to create one.
+%else:
+    <pre>
+    <br/>
+You are here: ${breadcrumb}<br/>
+    %if breadcrumb.endswith( 'theone' ):
+        ${heap}
+    %else:
+    <nobr>
+Sort:
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Class')}">Class</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Clodo' )}">Clodo</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Id' )}">Id</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Idset' )}">Idset</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Module' )}">Module</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Unity' )}">Unity</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Rcs' )}">Rcs</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Size' )}">Size</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Type' )}">Type</a> |
+        <a href="${h.url_for( controller='admin', action='memdump', ids=ids, sorts=sorts, new_sort='Via' )}">Via</a>
+    </nobr>
+    ${htmlize( heap )}
+    %endif
+    </pre>
+%endif