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%def>
+<%
+ import re
+ from xml.sax.saxutils import escape, unescape
+%>
+
+
+
+
++%endif
+You are here: ${breadcrumb}
+ %if breadcrumb.endswith( 'theone' ): + ${heap} + %else: ++Sort: + Class | + Clodo | + Id | + Idset | + Module | + Unity | + Rcs | + Size | + Type | + Via + + ${htmlize( heap )} + %endif +