details: http://www.bx.psu.edu/hg/galaxy/rev/8eec48aaca6e changeset: 1576:8eec48aaca6e user: Nate Coraor <nate@bx.psu.edu> 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