fix the profile mode

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-11-08 07:07:55 +01:00
parent 5eb131ef2b
commit 673edb0b9f
2 changed files with 26 additions and 30 deletions

View File

@ -31,7 +31,8 @@ import offlineimap.virtual_imaplib2 as imaplib
# Ensure that `ui` gets loaded before `threadutil` in order to # Ensure that `ui` gets loaded before `threadutil` in order to
# break the circular dependency between `threadutil` and `Curses`. # break the circular dependency between `threadutil` and `Curses`.
from offlineimap.ui import UI_LIST, setglobalui, getglobalui from offlineimap.ui import UI_LIST, setglobalui, getglobalui
from offlineimap import globals, threadutil, accounts, folder, mbnames from offlineimap import threadutil, accounts, folder, mbnames
from offlineimap import globals as glob
from offlineimap.CustomConfig import CustomConfigParser from offlineimap.CustomConfig import CustomConfigParser
from offlineimap.utils import stacktrace from offlineimap.utils import stacktrace
from offlineimap.repository import Repository from offlineimap.repository import Repository
@ -176,7 +177,7 @@ class OfflineImap(object):
help="remove mbnames entries for accounts not in accounts") help="remove mbnames entries for accounts not in accounts")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
globals.set_options (options) glob.set_options(options)
if options.version: if options.version:
print("offlineimap v%s, imaplib2 v%s (%s), Python v%s"% ( print("offlineimap v%s, imaplib2 v%s (%s), Python v%s"% (
@ -220,7 +221,6 @@ class OfflineImap(object):
options.profiledir) options.profiledir)
else: else:
os.mkdir(options.profiledir) os.mkdir(options.profiledir)
threadutil.ExitNotifyThread.set_profiledir(options.profiledir)
# TODO, make use of chosen ui for logging # TODO, make use of chosen ui for logging
logging.warn("Profile mode: Potentially large data will be " logging.warn("Profile mode: Potentially large data will be "
"created in '%s'"% options.profiledir) "created in '%s'"% options.profiledir)
@ -452,7 +452,7 @@ class OfflineImap(object):
if options.singlethreading: if options.singlethreading:
# Singlethreaded. # Singlethreaded.
self.__sync_singlethreaded(activeaccounts) self.__sync_singlethreaded(activeaccounts, options.profiledir)
else: else:
# Multithreaded. # Multithreaded.
t = threadutil.ExitNotifyThread( t = threadutil.ExitNotifyThread(
@ -476,15 +476,32 @@ class OfflineImap(object):
self.ui.terminate() self.ui.terminate()
return 1 return 1
def __sync_singlethreaded(self, list_accounts): def __sync_singlethreaded(self, list_accounts, profiledir):
"""Executed in singlethreaded mode only. """Executed in singlethreaded mode only.
:param accs: A list of accounts that should be synced :param accs: A list of accounts that should be synced
""" """
for accountname in list_accounts: for accountname in list_accounts:
account = accounts.SyncableAccount(self.config, accountname) account = accounts.SyncableAccount(self.config, accountname)
threading.currentThread().name = "Account sync %s"% account.name threading.currentThread().name = \
account.syncrunner() "Account sync %s"% account.getname()
if not profiledir:
account.syncrunner()
# Profile mode.
else:
try:
import cProfile as profile
except ImportError:
import profile
prof = profile.Profile()
try:
prof = prof.runctx("account.syncrunner()", globals(), locals())
except SystemExit:
pass
from datetime import datetime
dt = datetime.now().strftime('%Y%m%d%H%M%S')
prof.dump_stats(os.path.join(
profiledir, "%s_%s.prof"% (dt, account.getname())))
def __serverdiagnostics(self, options): def __serverdiagnostics(self, options):
self.ui.info(" imaplib2: %s (%s)"% (imaplib.__version__, imaplib.DESC)) self.ui.info(" imaplib2: %s (%s)"% (imaplib.__version__, imaplib.DESC))

View File

@ -130,6 +130,7 @@ def monitor():
except Empty: except Empty:
pass pass
class ExitNotifyThread(Thread): class ExitNotifyThread(Thread):
"""This class is designed to alert a "monitor" to the fact that a """This class is designed to alert a "monitor" to the fact that a
thread has exited and to provide for the ability for it to find out thread has exited and to provide for the ability for it to find out
@ -142,9 +143,6 @@ class ExitNotifyThread(Thread):
There is one instance of this class at runtime. The main thread waits for There is one instance of this class at runtime. The main thread waits for
the monitor to end.""" the monitor to end."""
profiledir = None
"""Class variable that is set to the profile directory if required."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ExitNotifyThread, self).__init__(*args, **kwargs) super(ExitNotifyThread, self).__init__(*args, **kwargs)
# These are all child threads that are supposed to go away when # These are all child threads that are supposed to go away when
@ -159,20 +157,7 @@ class ExitNotifyThread(Thread):
global exitedThreads global exitedThreads
try: try:
if not ExitNotifyThread.profiledir: # normal case Thread.run(self)
Thread.run(self)
else:
try:
import cProfile as profile
except ImportError:
import profile
prof = profile.Profile()
try:
prof = prof.runctx("Thread.run(self)", globals(), locals())
except SystemExit:
pass
prof.dump_stats(os.path.join(ExitNotifyThread.profiledir,
"%s_%s.prof"% (self.ident, self.getName())))
except Exception as e: except Exception as e:
# Thread exited with Exception, store it # Thread exited with Exception, store it
tb = traceback.format_exc() tb = traceback.format_exc()
@ -201,12 +186,6 @@ class ExitNotifyThread(Thread):
return self._exit_stacktrace return self._exit_stacktrace
@classmethod
def set_profiledir(cls, directory):
"""If set, will output profile information to 'directory'"""
cls.profiledir = directory
###################################################################### ######################################################################
# Instance-limited threads # Instance-limited threads