mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-03 06:58:42 +00:00
[UI] Add --profile to GTKUI and console and allow custom filename
Add --profile to commonoptions making the option now available for daemon and all UIs. --profile option now prints to stdout unless an optional filename is specified.
This commit is contained in:
parent
7b54a2a1ee
commit
c90af1ce6c
7 changed files with 77 additions and 49 deletions
|
@ -726,7 +726,6 @@ class VersionSplit(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, ver):
|
def __init__(self, ver):
|
||||||
import re
|
|
||||||
version_re = re.compile(r'''
|
version_re = re.compile(r'''
|
||||||
^
|
^
|
||||||
(?P<version>\d+\.\d+) # minimum 'N.N'
|
(?P<version>\d+\.\d+) # minimum 'N.N'
|
||||||
|
@ -993,3 +992,40 @@ def unicode_argv():
|
||||||
encoding = encoding or "utf-8"
|
encoding = encoding or "utf-8"
|
||||||
|
|
||||||
return [arg.decode(encoding) for arg in sys.argv]
|
return [arg.decode(encoding) for arg in sys.argv]
|
||||||
|
|
||||||
|
|
||||||
|
def run_profiled(func, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Profile a function with cProfile
|
||||||
|
|
||||||
|
Args:
|
||||||
|
func (func): The function to profile
|
||||||
|
*args (tuple): The arguments to pass to the function
|
||||||
|
do_profile (bool, optional): If profiling should be performed. Defaults to True.
|
||||||
|
output_file (str, optional): Filename to save profile results. If None, print to stdout.
|
||||||
|
Defaults to None.
|
||||||
|
"""
|
||||||
|
if kwargs.get("do_profile", True) is not False:
|
||||||
|
import cProfile
|
||||||
|
profiler = cProfile.Profile()
|
||||||
|
|
||||||
|
def on_shutdown():
|
||||||
|
output_file = kwargs.get("output_file", None)
|
||||||
|
if output_file:
|
||||||
|
profiler.dump_stats(output_file)
|
||||||
|
log.info("Profile stats saved to %s", output_file)
|
||||||
|
print "Profile stats saved to %s" % output_file
|
||||||
|
else:
|
||||||
|
import pstats
|
||||||
|
import StringIO
|
||||||
|
strio = StringIO.StringIO()
|
||||||
|
ps = pstats.Stats(profiler, stream=strio).sort_stats('cumulative')
|
||||||
|
ps.print_stats()
|
||||||
|
print strio.getvalue()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return profiler.runcall(func, *args)
|
||||||
|
finally:
|
||||||
|
on_shutdown()
|
||||||
|
else:
|
||||||
|
return func(*args)
|
||||||
|
|
|
@ -214,19 +214,5 @@ def start_daemon(skip_start=False):
|
||||||
if options.pidfile:
|
if options.pidfile:
|
||||||
os.remove(options.pidfile)
|
os.remove(options.pidfile)
|
||||||
|
|
||||||
if options.profile:
|
return deluge.common.run_profiled(run_daemon, options, output_file=options.profile,
|
||||||
import cProfile
|
do_profile=options.profile)
|
||||||
profiler = cProfile.Profile()
|
|
||||||
profile_output = deluge.configmanager.get_config_dir("deluged.profile")
|
|
||||||
|
|
||||||
# Twisted catches signals to terminate
|
|
||||||
def save_profile_stats():
|
|
||||||
profiler.dump_stats(profile_output)
|
|
||||||
print("Profile stats saved to %s" % profile_output)
|
|
||||||
|
|
||||||
from twisted.internet import reactor
|
|
||||||
reactor.addSystemEventTrigger("before", "shutdown", save_profile_stats)
|
|
||||||
print("Running with profiler...")
|
|
||||||
profiler.runcall(run_daemon, options)
|
|
||||||
else:
|
|
||||||
return run_daemon(options)
|
|
||||||
|
|
|
@ -106,6 +106,9 @@ class BaseArgParser(argparse.ArgumentParser):
|
||||||
help="Sets the log level to 'none', this is the same as `-L none`")
|
help="Sets the log level to 'none', this is the same as `-L none`")
|
||||||
self.group.add_argument("-r", "--rotate-logs", action="store_true", default=False,
|
self.group.add_argument("-r", "--rotate-logs", action="store_true", default=False,
|
||||||
help="Rotate logfiles.")
|
help="Rotate logfiles.")
|
||||||
|
self.group.add_argument("--profile", metavar="<results file>", action="store", nargs="?", default=False,
|
||||||
|
help="Profile %(prog)s with cProfile. Prints results to stdout"
|
||||||
|
"unless a filename is specififed.")
|
||||||
self.group.add_argument("-h", "--help", action=HelpAction, help='Show this help message and exit')
|
self.group.add_argument("-h", "--help", action=HelpAction, help='Show this help message and exit')
|
||||||
|
|
||||||
def parse_args(self, *args):
|
def parse_args(self, *args):
|
||||||
|
|
|
@ -8,12 +8,15 @@
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import deluge.common
|
||||||
from deluge.ui.baseargparser import DelugeTextHelpFormatter
|
from deluge.ui.baseargparser import DelugeTextHelpFormatter
|
||||||
from deluge.ui.console import UI_PATH
|
from deluge.ui.console import UI_PATH
|
||||||
from deluge.ui.ui import UI
|
from deluge.ui.ui import UI
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Note: Cannot import from console.main here because it imports the twisted reactor.
|
# Note: Cannot import from console.main here because it imports the twisted reactor.
|
||||||
|
@ -76,4 +79,13 @@ class Console(UI):
|
||||||
def start(self, args=None):
|
def start(self, args=None):
|
||||||
super(Console, self).start(args)
|
super(Console, self).start(args)
|
||||||
from deluge.ui.console.main import ConsoleUI # import here because (see top)
|
from deluge.ui.console.main import ConsoleUI # import here because (see top)
|
||||||
|
|
||||||
|
def run(options):
|
||||||
|
try:
|
||||||
ConsoleUI(self.options, self.console_cmds)
|
ConsoleUI(self.options, self.console_cmds)
|
||||||
|
except Exception as ex:
|
||||||
|
log.exception(ex)
|
||||||
|
raise
|
||||||
|
|
||||||
|
deluge.common.run_profiled(run, self.options, output_file=self.options.profile,
|
||||||
|
do_profile=self.options.profile)
|
||||||
|
|
|
@ -184,7 +184,7 @@ class ConsoleUI(component.Component):
|
||||||
curses.wrapper(self.run)
|
curses.wrapper(self.run)
|
||||||
elif self.interactive and deluge.common.windows_check():
|
elif self.interactive and deluge.common.windows_check():
|
||||||
print("""\nDeluge-console does not run in interactive mode on Windows. \n
|
print("""\nDeluge-console does not run in interactive mode on Windows. \n
|
||||||
Please use commands from the command line, eg:\n
|
Please use commands from the command line, e.g.:\n
|
||||||
deluge-console.exe help
|
deluge-console.exe help
|
||||||
deluge-console.exe info
|
deluge-console.exe info
|
||||||
deluge-console.exe "add --help"
|
deluge-console.exe "add --help"
|
||||||
|
|
|
@ -146,9 +146,17 @@ class Gtk(UI):
|
||||||
" to a currently running Deluge GTK instance")
|
" to a currently running Deluge GTK instance")
|
||||||
|
|
||||||
def start(self, args=None):
|
def start(self, args=None):
|
||||||
from gtkui import GtkUI
|
|
||||||
super(Gtk, self).start(args)
|
super(Gtk, self).start(args)
|
||||||
GtkUI(self.options)
|
|
||||||
|
def run(options):
|
||||||
|
try:
|
||||||
|
GtkUI(options)
|
||||||
|
except Exception as ex:
|
||||||
|
log.exception(ex)
|
||||||
|
raise
|
||||||
|
|
||||||
|
deluge.common.run_profiled(run, self.options, output_file=self.options.profile,
|
||||||
|
do_profile=self.options.profile)
|
||||||
|
|
||||||
|
|
||||||
class GtkUI(object):
|
class GtkUI(object):
|
||||||
|
|
|
@ -9,17 +9,14 @@
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from deluge.common import osx_check, windows_check
|
from deluge.common import osx_check, run_profiled, windows_check
|
||||||
from deluge.configmanager import get_config_dir
|
from deluge.configmanager import get_config_dir
|
||||||
from deluge.ui.ui import UI
|
from deluge.ui.ui import UI
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
#
|
|
||||||
# Note: Cannot import twisted.internet.reactor because Web is imported from
|
|
||||||
# from web/__init__.py loaded by the script entry points defined in setup.py
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
class WebUI(object):
|
class WebUI(object):
|
||||||
|
@ -56,8 +53,6 @@ class Web(UI):
|
||||||
help="Binds the webserver to a specific IP address")
|
help="Binds the webserver to a specific IP address")
|
||||||
group.add_argument("-p", "--port", metavar="<port>", type=int, action="store", default=None,
|
group.add_argument("-p", "--port", metavar="<port>", type=int, action="store", default=None,
|
||||||
help="Sets the port to be used for the webserver")
|
help="Sets the port to be used for the webserver")
|
||||||
group.add_argument("--profile", action="store_true", default=False,
|
|
||||||
help="Profile the web server code")
|
|
||||||
try:
|
try:
|
||||||
import OpenSSL
|
import OpenSSL
|
||||||
assert OpenSSL.__version__
|
assert OpenSSL.__version__
|
||||||
|
@ -123,26 +118,14 @@ class Web(UI):
|
||||||
|
|
||||||
self.server.https = self.options.ssl
|
self.server.https = self.options.ssl
|
||||||
|
|
||||||
def run_server():
|
def run():
|
||||||
|
try:
|
||||||
self.server.install_signal_handlers()
|
self.server.install_signal_handlers()
|
||||||
self.server.start()
|
self.server.start()
|
||||||
|
except Exception as ex:
|
||||||
if self.options.profile:
|
log.exception(ex)
|
||||||
import cProfile
|
raise
|
||||||
profiler = cProfile.Profile()
|
run_profiled(run, output_file=self.options.profile, do_profile=self.options.profile)
|
||||||
profile_output = get_config_dir("delugeweb.profile")
|
|
||||||
|
|
||||||
# Twisted catches signals to terminate
|
|
||||||
def save_profile_stats():
|
|
||||||
profiler.dump_stats(profile_output)
|
|
||||||
print("Profile stats saved to %s" % profile_output)
|
|
||||||
|
|
||||||
from twisted.internet import reactor # import here because (see top)
|
|
||||||
reactor.addSystemEventTrigger("before", "shutdown", save_profile_stats)
|
|
||||||
print("Running with profiler...")
|
|
||||||
profiler.runcall(run_server)
|
|
||||||
else:
|
|
||||||
run_server()
|
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue