diff --git a/lib/galaxy/app.py b/lib/galaxy/app.py index 743af730b0f..0c35c12a4be 100644 --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -35,6 +35,7 @@ class UniverseApplication( object ): 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 --git a/lib/galaxy/util/memdump.py b/lib/galaxy/util/memdump.py index 69a25f3d285..524d98d9534 100644 --- a/lib/galaxy/util/memdump.py +++ b/lib/galaxy/util/memdump.py @@ -22,22 +22,29 @@ else: 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 --git a/lib/galaxy/web/controllers/admin.py b/lib/galaxy/web/controllers/admin.py index fd9b4be90d8..81315558db1 100644 --- a/lib/galaxy/web/controllers/admin.py +++ b/lib/galaxy/web/controllers/admin.py @@ -22,3 +22,42 @@ class Admin( BaseController ): 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 use_memdump = True 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 = "heap" % 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 += "[%s]" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id ) + heap = heap[int(id)] + new_sorts.append( sort ) + if sort != 'None': + breadcrumb += ".by('%s')" % ( 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 --git a/templates/admin/memdump.mako b/templates/admin/memdump.mako new file mode 100644 index 00000000000..e99c5585c19 --- /dev/null +++ b/templates/admin/memdump.mako @@ -0,0 +1,75 @@ +<%inherit file="/base.mako"/> + +<%def name="title()">Memory Profiling +<% + import re + from xml.sax.saxutils import escape, unescape +%> + + + +

Memory Profiling

+ + + +<%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\2', line ) + if id and heap[int(id)].count == 1: + new_s += " theone\n" % h.url_for( ids=ids, sorts=sorts, new_id=id, theone=True ) + else: + new_s += "\n" + return new_s +%> + + +%if msg: +
${msg}
+%endif + +%if heap is None: + No memory dump available. Click "Dump memory" to create one. +%else: +
+    
+You are here: ${breadcrumb}
+ %if breadcrumb.endswith( 'theone' ): + ${heap} + %else: + +Sort: + Class | + Clodo | + Id | + Idset | + Module | + Unity | + Rcs | + Size | + Type | + Via + + ${htmlize( heap )} + %endif +
+%endif