summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@xander>2010-12-26 21:09:52 +0200
committerLars Wirzenius <liw@xander>2010-12-26 21:09:52 +0200
commit7f4ef9ae22d975fe67c6c8c80da331785eedfea8 (patch)
tree1d3563689da63a75f1e38e8085dfb8225ef29118
parent1bcd6d492709bcd3a8051474da175923aca64c62 (diff)
parent4ef1e4e4f478b28a6bf679f07756ecc99e7f4bbc (diff)
downloadobnam-7f4ef9ae22d975fe67c6c8c80da331785eedfea8.tar.gz
Merge changes to do memory profiling.
-rw-r--r--obnamlib/app.py7
-rw-r--r--obnamlib/plugins/backup_plugin.py41
2 files changed, 46 insertions, 2 deletions
diff --git a/obnamlib/app.py b/obnamlib/app.py
index d420c2e1..bea64c7d 100644
--- a/obnamlib/app.py
+++ b/obnamlib/app.py
@@ -63,6 +63,13 @@ class App(object):
'(default: %default)')
self.config['lru-size'] = '%s' % obnamlib.DEFAULT_LRU_SIZE
+ self.config.new_string(['dump-memory-profile'],
+ 'make memory profiling dumps '
+ 'after each checkpoint and at end? '
+ 'set to none, meliae, or heapy '
+ '(default: %default)')
+ self.config['dump-memory-profile'] = 'none'
+
self.pm = obnamlib.PluginManager()
self.pm.locations = [self.plugins_dir()]
self.pm.plugin_arguments = (self,)
diff --git a/obnamlib/plugins/backup_plugin.py b/obnamlib/plugins/backup_plugin.py
index a7a3982a..e3032e79 100644
--- a/obnamlib/plugins/backup_plugin.py
+++ b/obnamlib/plugins/backup_plugin.py
@@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import gc
import logging
import os
import re
@@ -76,6 +77,7 @@ class BackupPlugin(obnamlib.ObnamPlugin):
self.exclude_pats = [re.compile(x) for x in self.app.config['exclude']]
last_checkpoint = 0
+ self.memory_dump_counter = 0
interval = self.app.config['checkpoint']
if roots:
@@ -107,6 +109,10 @@ class BackupPlugin(obnamlib.ObnamPlugin):
self.app.hooks.call('error-message',
'Could not back up %s: %s' %
(pathname, e.strerror))
+ logging.debug('storefs.bytes_written: %d' %
+ storefs.bytes_written)
+ logging.debug('last_checkpoint: %d' % last_checkpoint)
+ logging.debug('interval: %d' % interval)
if storefs.bytes_written - last_checkpoint >= interval:
logging.debug('Making checkpoint')
self.backup_parents('.')
@@ -114,6 +120,7 @@ class BackupPlugin(obnamlib.ObnamPlugin):
self.store.lock_client(client_name)
self.store.start_generation()
last_checkpoint = storefs.bytes_written
+ self.dump_memory_profile('at end of checkpoint')
self.backup_parents('.')
@@ -124,6 +131,35 @@ class BackupPlugin(obnamlib.ObnamPlugin):
storefs.close()
logging.info('Backup finished.')
+ self.dump_memory_profile('at end of backup run')
+
+ def vmrss(self):
+ f = open('/proc/self/status')
+ rss = 0
+ for line in f:
+ if line.startswith('VmRSS'):
+ rss = line.split()[1]
+ f.close()
+ return rss
+
+ def dump_memory_profile(self, msg):
+ kind = self.app.config['dump-memory-profile']
+ if kind == 'none':
+ return
+ logging.debug('dumping memory profiling data: %s' % msg)
+ logging.debug('VmRSS: %s KiB' % self.vmrss())
+ logging.debug('# objects: %d' % len(gc.get_objects()))
+ logging.debug('# garbage: %d' % len(gc.garbage))
+ if kind == 'heapy':
+ from guppy import hpy
+ h = hpy()
+ logging.debug('memory profile:\n%s' % h.heap())
+ elif kind == 'meliae':
+ filename = 'obnam-%d.meliae' % self.memory_dump_counter
+ logging.debug('memory profile: see %s' % filename)
+ from meliae import scanner
+ scanner.dump_all_objects(filename)
+ self.memory_dump_counter += 1
def find_files(self, root):
'''Find all files and directories that need to be backed up.
@@ -167,8 +203,6 @@ class BackupPlugin(obnamlib.ObnamPlugin):
prune_list(subdirs)
prune_list(filenames)
- subdirs.sort()
- filenames.sort()
def needs_backup(self, pathname, current):
'''Does a given file need to be backed up?'''
@@ -222,11 +256,14 @@ class BackupPlugin(obnamlib.ObnamPlugin):
chunkids.append(self.backup_file_chunk(data))
if len(chunkids) >= obnamlib.DEFAULT_CHUNKIDS_PER_GROUP:
self.store.append_file_chunks(filename, chunkids)
+ self.dump_memory_profile('after appending some chunkids')
chunkids = []
self.app.hooks.call('progress-data-uploaded', len(data))
f.close()
if chunkids:
self.store.append_file_chunks(filename, chunkids)
+ self.dump_memory_profile('at end of file content backup for %s' %
+ filename)
def backup_file_chunk(self, data):
'''Back up a chunk of data by putting it into the store.'''