From 673edb0b9f76da22f9519125a0a219212d9ab952 Mon Sep 17 00:00:00 2001 From: Nicolas Sebrecht Date: Tue, 8 Nov 2016 07:07:55 +0100 Subject: [PATCH] fix the profile mode Signed-off-by: Nicolas Sebrecht --- offlineimap/init.py | 31 ++++++++++++++++++++++++------- offlineimap/threadutil.py | 25 ++----------------------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/offlineimap/init.py b/offlineimap/init.py index efa438a..7f193d1 100644 --- a/offlineimap/init.py +++ b/offlineimap/init.py @@ -31,7 +31,8 @@ import offlineimap.virtual_imaplib2 as imaplib # Ensure that `ui` gets loaded before `threadutil` in order to # break the circular dependency between `threadutil` and `Curses`. 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.utils import stacktrace from offlineimap.repository import Repository @@ -176,7 +177,7 @@ class OfflineImap(object): help="remove mbnames entries for accounts not in accounts") (options, args) = parser.parse_args() - globals.set_options (options) + glob.set_options(options) if options.version: print("offlineimap v%s, imaplib2 v%s (%s), Python v%s"% ( @@ -220,7 +221,6 @@ class OfflineImap(object): options.profiledir) else: os.mkdir(options.profiledir) - threadutil.ExitNotifyThread.set_profiledir(options.profiledir) # TODO, make use of chosen ui for logging logging.warn("Profile mode: Potentially large data will be " "created in '%s'"% options.profiledir) @@ -452,7 +452,7 @@ class OfflineImap(object): if options.singlethreading: # Singlethreaded. - self.__sync_singlethreaded(activeaccounts) + self.__sync_singlethreaded(activeaccounts, options.profiledir) else: # Multithreaded. t = threadutil.ExitNotifyThread( @@ -476,15 +476,32 @@ class OfflineImap(object): self.ui.terminate() return 1 - def __sync_singlethreaded(self, list_accounts): + def __sync_singlethreaded(self, list_accounts, profiledir): """Executed in singlethreaded mode only. :param accs: A list of accounts that should be synced """ for accountname in list_accounts: account = accounts.SyncableAccount(self.config, accountname) - threading.currentThread().name = "Account sync %s"% account.name - account.syncrunner() + threading.currentThread().name = \ + "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): self.ui.info(" imaplib2: %s (%s)"% (imaplib.__version__, imaplib.DESC)) diff --git a/offlineimap/threadutil.py b/offlineimap/threadutil.py index 29272db..0df5a21 100644 --- a/offlineimap/threadutil.py +++ b/offlineimap/threadutil.py @@ -130,6 +130,7 @@ def monitor(): except Empty: pass + class ExitNotifyThread(Thread): """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 @@ -142,9 +143,6 @@ class ExitNotifyThread(Thread): There is one instance of this class at runtime. The main thread waits for the monitor to end.""" - profiledir = None - """Class variable that is set to the profile directory if required.""" - def __init__(self, *args, **kwargs): super(ExitNotifyThread, self).__init__(*args, **kwargs) # These are all child threads that are supposed to go away when @@ -159,20 +157,7 @@ class ExitNotifyThread(Thread): global exitedThreads try: - if not ExitNotifyThread.profiledir: # normal case - 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()))) + Thread.run(self) except Exception as e: # Thread exited with Exception, store it tb = traceback.format_exc() @@ -201,12 +186,6 @@ class ExitNotifyThread(Thread): return self._exit_stacktrace - @classmethod - def set_profiledir(cls, directory): - """If set, will output profile information to 'directory'""" - - cls.profiledir = directory - ###################################################################### # Instance-limited threads