home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / util / perfmon.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  10.8 KB  |  309 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import division
  5. import os
  6. import sys
  7. from threading import Thread
  8. from ctypes import WinError, byref, c_ulonglong
  9. from time import clock, sleep
  10. from traceback import print_exc
  11. from cStringIO import StringIO
  12. from datetime import datetime
  13. from common.commandline import where
  14. from util.threads.bgthread import BackgroundThread
  15. from logging import getLogger
  16. log = getLogger('perfmon')
  17. PROCESS_QUERY_INFORMATION = 1024
  18. THREAD_QUERY_INFORMATION = 64
  19. from ctypes import windll
  20. kernel32 = windll.kernel32
  21. GetProcessTimes = kernel32.GetProcessTimes
  22. GetThreadTimes = kernel32.GetThreadTimes
  23. OpenProcess = kernel32.OpenProcess
  24. CloseHandle = kernel32.CloseHandle
  25. OpenThread = kernel32.OpenThread
  26. if getattr(sys, 'DEV', False):
  27.     NUM_CONSECUTIVE_HIGHS = 5
  28. else:
  29.     NUM_CONSECUTIVE_HIGHS = 10
  30. TICK_FREQUENCY = 5
  31. PROFILE_TICKS = 5
  32. CPU_THRESHOLD = 0.95
  33. TICKS_PER_SEC = 1e+07
  34. from util.introspect import all_profilers
  35.  
  36. def enable_profilers():
  37.     profilers = all_profilers().values()
  38.     for profiler in profilers:
  39.         profiler.enable()
  40.     
  41.     _log_enabled_profilers(profilers)
  42.  
  43.  
  44. def disable_profilers():
  45.     profilers = all_profilers().values()
  46.     for profiler in profilers:
  47.         profiler.disable()
  48.     
  49.     _log_enabled_profilers(profilers)
  50.  
  51.  
  52. def _log_enabled_profilers(profilers):
  53.     len([] % ([](_[1]), len(profilers)))
  54.  
  55.  
  56. def profilers_enabled():
  57.     return all((lambda .0: for p in .0:
  58. p.enabled)(all_profilers().itervalues()))
  59.  
  60.  
  61. def get_stack_info():
  62.     io = StringIO()
  63.     where(duplicates = True, stream = io)
  64.     stack_info = io.getvalue()
  65.     return '\n\n'.join([
  66.         datetime.now().isoformat(),
  67.         stack_info])
  68.  
  69.  
  70. class CPUWatch(object):
  71.     
  72.     def usage(self, user, kernel):
  73.         return getattr(self, self.state + '_usage')(user, kernel)
  74.  
  75.     
  76.     def watching_usage(self, user, kernel):
  77.         self.user = user
  78.         self.kernel = kernel
  79.         if user + kernel >= self.threshold:
  80.             self.count += 1
  81.             log.info('cpu usage is high (not profiling yet: %s/%s): %s', self.count, NUM_CONSECUTIVE_HIGHS, user + kernel)
  82.             if self.count > NUM_CONSECUTIVE_HIGHS:
  83.                 import wx
  84.                 wx.CallAfter(self.prompt_for_profiling)
  85.             
  86.         else:
  87.             self.count = 0
  88.  
  89.     
  90.     def profiling_usage(self, user, kernel):
  91.         self.user = user
  92.         self.kernel = kernel
  93.         if user + kernel >= self.threshold:
  94.             log.info('cpu usage is high: %s' % (user + kernel))
  95.             self.stack_info.append(get_stack_info())
  96.             self.count += 1
  97.             if self.count > PROFILE_TICKS:
  98.                 self.disable()
  99.                 self.send_info()
  100.             
  101.         else:
  102.             log.info('cpu usage was low again: %s' % (user + kernel))
  103.             log.info('')
  104.             self.count = 0
  105.             self.state = 'watching'
  106.  
  107.     
  108.     def disabled_usage(self, user, kernel):
  109.         pass
  110.  
  111.     
  112.     def send_info(self):
  113.         log.info('sending diagnostic information...')
  114.         Diagnostic = Diagnostic
  115.         import util.diagnostic
  116.         import wx
  117.         
  118.         try:
  119.             d = Diagnostic(description = 'CPU usage was too high.')
  120.             d.prepare_data()
  121.             if d.do_no_thread_post():
  122.                 return wx.CallAfter(wx.MessageBox, _('A log of the problem has been sent to digsby.com.\n\nThanks for helping!'), _('Diagnostic Log'))
  123.         except Exception:
  124.             print_exc()
  125.  
  126.         wx.CallAfter(wx.MessageBox, _('There was an error when submitting the diagnostic log.'))
  127.  
  128.     
  129.     def prompt_for_profiling(self):
  130.         if self._CPUWatch__in:
  131.             return None
  132.         self._CPUWatch__in = True
  133.         log.info('prompting for profiling info')
  134.         dev = getattr(sys, 'DEV', False)
  135.         if profilers_enabled():
  136.             self.state = 'profiling'
  137.             return log.info('profiler is already enabled')
  138.         import wx
  139.         self._CPUWatch__in = False
  140.  
  141.     
  142.     def disable(self):
  143.         self.state = 'disabled'
  144.         disable_profilers()
  145.         self.cpu_monitor.done = True
  146.  
  147.     
  148.     def __init__(self, threshold = CPU_THRESHOLD):
  149.         if threshold < threshold:
  150.             pass
  151.         elif not threshold <= 1:
  152.             raise ValueError('0 < threshold <= 1')
  153.         
  154.         self.state = 'watching'
  155.         self.threshold = threshold
  156.         self.count = 0
  157.         self.ignore = False
  158.         self.cpu_monitor = CPUMonitor(self.usage)
  159.         self.cpu_monitor.start()
  160.         self._CPUWatch__in = False
  161.         self.stack_info = []
  162.  
  163.  
  164.  
  165. class CPUMonitor(BackgroundThread):
  166.     
  167.     def __init__(self, usage_cb, update_freq_secs = TICK_FREQUENCY):
  168.         BackgroundThread.__init__(self, name = 'CPUMonitor')
  169.         self.setDaemon(True)
  170.         self.done = False
  171.         self.update_freq_secs = 5
  172.         self.perfinfo = ProcessPerfInfo()
  173.         self.usage_cb = usage_cb
  174.  
  175.     
  176.     def run(self):
  177.         self.BeforeRun()
  178.         while not self.done:
  179.             setattr(self, 'loopcount', getattr(self, 'loopcount', 0) + 1)
  180.             self.usage_cb(*self.perfinfo.update())
  181.             sleep(self.update_freq_secs)
  182.         self.AfterRun()
  183.  
  184.  
  185.  
  186. class PerfInfo(object):
  187.     __slots__ = [
  188.         'last_update',
  189.         'handle',
  190.         'creationTime',
  191.         'exitTime',
  192.         'kernelTime',
  193.         'userTime',
  194.         'oldKernel',
  195.         'oldUser']
  196.     
  197.     def __init__(self):
  198.         self.last_update = clock()
  199.         for name in ('creationTime', 'exitTime', 'kernelTime', 'userTime', 'oldKernel', 'oldUser'):
  200.             setattr(self, name, c_ulonglong())
  201.         
  202.         self.handle = self.get_handle()
  203.         self.update()
  204.  
  205.     
  206.     def get_handle(self):
  207.         raise NotImplementedError
  208.  
  209.     
  210.     def update(self):
  211.         if not self.times_func(self.handle, byref(self.creationTime), byref(self.exitTime), byref(self.kernelTime), byref(self.userTime)):
  212.             raise WinError()
  213.         self.times_func(self.handle, byref(self.creationTime), byref(self.exitTime), byref(self.kernelTime), byref(self.userTime))
  214.         now = clock()
  215.         diff = now - self.last_update
  216.         userPercent = (self.userTime.value - self.oldUser.value) / TICKS_PER_SEC / diff
  217.         kernelPercent = (self.kernelTime.value - self.oldKernel.value) / TICKS_PER_SEC / diff
  218.         self.last_update = now
  219.         self.oldUser.value = self.userTime.value
  220.         self.oldKernel.value = self.kernelTime.value
  221.         return (userPercent, kernelPercent)
  222.  
  223.     
  224.     def __del__(self):
  225.         CloseHandle(self.handle)
  226.  
  227.  
  228.  
  229. class ProcessPerfInfo(PerfInfo):
  230.     __slots__ = []
  231.     
  232.     def __init__(self):
  233.         PerfInfo.__init__(self)
  234.  
  235.     
  236.     def get_handle(self):
  237.         return obtain_process_handle()
  238.  
  239.     
  240.     def times_func(self):
  241.         return GetProcessTimes
  242.  
  243.     times_func = property(times_func)
  244.  
  245.  
  246. class ThreadPerfInfo(PerfInfo):
  247.     __slots__ = [
  248.         'thread_id']
  249.     
  250.     def __init__(self, thread_id):
  251.         self.thread_id = thread_id
  252.         PerfInfo.__init__(self)
  253.  
  254.     
  255.     def get_handle(self):
  256.         return obtain_thread_handle(self.thread_id)
  257.  
  258.     
  259.     def times_func(self):
  260.         return GetThreadTimes
  261.  
  262.     times_func = property(times_func)
  263.  
  264.  
  265. def num_processors():
  266.     return os.environ.get('NUMBER_OF_PROCESSORS', 1)
  267.  
  268.  
  269. def obtain_process_handle(pid = None):
  270.     handle = None(OpenProcess, PROCESS_QUERY_INFORMATION, False if pid is None else pid)
  271.     if not handle:
  272.         raise WinError()
  273.     handle
  274.     return handle
  275.  
  276.  
  277. def obtain_thread_handle(thread_id):
  278.     handle = OpenThread(THREAD_QUERY_INFORMATION, False, thread_id)
  279.     if not handle:
  280.         raise WinError()
  281.     handle
  282.     return handle
  283.  
  284.  
  285. def main():
  286.     import wx
  287.     a = wx.PySimpleApp()
  288.     f = wx.Frame(None)
  289.     b = wx.Button(f, -1, 'info')
  290.     
  291.     def foo():
  292.         while True:
  293.             pass
  294.  
  295.     t = Thread(target = foo)
  296.     cpumonitor = CPUMonitor()
  297.     cpumonitor.start()
  298.     
  299.     def onbutton(e):
  300.         t.start()
  301.  
  302.     b.Bind(wx.EVT_BUTTON, onbutton)
  303.     f.Show()
  304.     a.MainLoop()
  305.  
  306. if __name__ == '__main__':
  307.     main()
  308.  
  309.