mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-21 21:57:36 +00:00
--debug-profile: use msgpack instead of marshal by default
This commit is contained in:
parent
4c441c75b1
commit
a07463c96a
3 changed files with 47 additions and 8 deletions
18
scripts/msgpack2marshal.py
Executable file
18
scripts/msgpack2marshal.py
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import marshal
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import msgpack
|
||||||
|
|
||||||
|
if len(sys.argv) not in (2, 3):
|
||||||
|
print('Synopsis:', sys.argv[0], '<msgpack input>', '[marshal output]', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if len(sys.argv) == 2:
|
||||||
|
outfile = sys.stdout
|
||||||
|
else:
|
||||||
|
outfile = open(sys.argv[2], 'wb')
|
||||||
|
|
||||||
|
with outfile:
|
||||||
|
with open(sys.argv[1], 'rb') as infile:
|
||||||
|
marshal.dump(msgpack.unpack(infile, use_list=False, encoding='utf-8'), outfile)
|
|
@ -2050,7 +2050,8 @@ def define_common_options(add_common_option):
|
||||||
action='store_true', default=False,
|
action='store_true', default=False,
|
||||||
help='treat part files like normal files (e.g. to list/extract them)')
|
help='treat part files like normal files (e.g. to list/extract them)')
|
||||||
add_common_option('--debug-profile', dest='debug_profile', default=None, metavar='FILE',
|
add_common_option('--debug-profile', dest='debug_profile', default=None, metavar='FILE',
|
||||||
help='Store a Python profile at FILE')
|
help='Write Python profile in msgpack format into FILE. For local use a cProfile-'
|
||||||
|
'compatible file can be generated by suffixing FILE with ".pyprof".')
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(prog=self.prog, description='Borg - Deduplicated Backups',
|
parser = argparse.ArgumentParser(prog=self.prog, description='Borg - Deduplicated Backups',
|
||||||
add_help=False)
|
add_help=False)
|
||||||
|
@ -3545,7 +3546,7 @@ def run(self, args):
|
||||||
if is_slow_msgpack():
|
if is_slow_msgpack():
|
||||||
logger.warning("Using a pure-python msgpack! This will result in lower performance.")
|
logger.warning("Using a pure-python msgpack! This will result in lower performance.")
|
||||||
if args.debug_profile:
|
if args.debug_profile:
|
||||||
# Import these only when needed - avoids a further increase in startup time
|
# Import only when needed - avoids a further increase in startup time
|
||||||
import cProfile
|
import cProfile
|
||||||
import marshal
|
import marshal
|
||||||
logger.debug('Writing execution profile to %s', args.debug_profile)
|
logger.debug('Writing execution profile to %s', args.debug_profile)
|
||||||
|
@ -3554,10 +3555,24 @@ def run(self, args):
|
||||||
with open(args.debug_profile, 'wb') as fd:
|
with open(args.debug_profile, 'wb') as fd:
|
||||||
profiler = cProfile.Profile()
|
profiler = cProfile.Profile()
|
||||||
variables = dict(locals())
|
variables = dict(locals())
|
||||||
profiler.runctx('rc = set_ec(func(args))', globals(), variables)
|
profiler.enable()
|
||||||
profiler.snapshot_stats()
|
try:
|
||||||
marshal.dump(profiler.stats, fd)
|
return set_ec(func(args))
|
||||||
return variables['rc']
|
finally:
|
||||||
|
profiler.disable()
|
||||||
|
profiler.snapshot_stats()
|
||||||
|
if args.debug_profile.endswith('.pyprof'):
|
||||||
|
marshal.dump(profiler.stats, fd)
|
||||||
|
else:
|
||||||
|
# We use msgpack here instead of the marshal module used by cProfile itself,
|
||||||
|
# because the latter is insecure. Since these files may be shared over the
|
||||||
|
# internet we don't want a format that is impossible to interpret outside
|
||||||
|
# an insecure implementation.
|
||||||
|
# See scripts/msgpack2marshal.py for a small script that turns a msgpack file
|
||||||
|
# into a marshal file that can be read by e.g. pyprof2calltree.
|
||||||
|
# For local use it's unnecessary hassle, though, that's why .pyprof makes
|
||||||
|
# it compatible (see above).
|
||||||
|
msgpack.pack(profiler.stats, fd, use_bin_type=True)
|
||||||
else:
|
else:
|
||||||
return set_ec(func(args))
|
return set_ec(func(args))
|
||||||
|
|
||||||
|
|
|
@ -1686,10 +1686,16 @@ def test_debug_profile(self):
|
||||||
self.create_test_files()
|
self.create_test_files()
|
||||||
self.cmd('init', '--encryption=repokey', self.repository_location)
|
self.cmd('init', '--encryption=repokey', self.repository_location)
|
||||||
self.cmd('create', self.repository_location + '::test', 'input', '--debug-profile=create.prof')
|
self.cmd('create', self.repository_location + '::test', 'input', '--debug-profile=create.prof')
|
||||||
stats = pstats.Stats('create.prof')
|
stats = pstats.Stats()
|
||||||
|
with open('create.prof', 'rb') as fd:
|
||||||
|
stats.stats = msgpack.unpack(fd, use_list=False, encoding='utf-8')
|
||||||
|
stats.strip_dirs()
|
||||||
|
stats.sort_stats('cumtime')
|
||||||
|
|
||||||
|
self.cmd('create', self.repository_location + '::test2', 'input', '--debug-profile=create.pyprof')
|
||||||
|
stats = pstats.Stats('create.pyprof') # Only do this on trusted data!
|
||||||
stats.strip_dirs()
|
stats.strip_dirs()
|
||||||
stats.sort_stats('cumtime')
|
stats.sort_stats('cumtime')
|
||||||
# Ok, stats can be loaded, good enough.
|
|
||||||
|
|
||||||
def test_common_options(self):
|
def test_common_options(self):
|
||||||
self.create_test_files()
|
self.create_test_files()
|
||||||
|
|
Loading…
Reference in a new issue