From 71e37f9217f6818d53f4c2cae2b9b8f0d25c8349 Mon Sep 17 00:00:00 2001 From: Peace Lee Date: Tue, 27 Jul 2021 21:14:33 +0900 Subject: [PATCH] disktop: Fix per-disk I/O stats for macOS and Windows Signed-off-by: Peace Lee --- README.md | 155 ++++++++++++++--------- guider/guider.py | 322 +++++++++++++++++++++++++++++++++++++---------- setup.py | 2 +- 3 files changed, 354 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 839405c7..74b1dbdd 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ Table of contents * [Guider](#Guider) * [Output](#Output) * [How to use](#How-to-use) - * [Requirement](#Requirement) * [Build & Installation](#Build--Installation) * [Kernel Configuration](#Kernel-Configuration) * [Help](#Help) @@ -55,7 +54,7 @@ It supports almost all platforms based on the Linux kernel as shown below. Output ======= - $ guider/guider.py top -a + $ python3 guider/guider.py top -a [Top Info] [Time: 4588832.570] [Inter: 1.0] [Ctxt: 314463] [Life: +0/-0] [IRQ: 26606] [Core: 40] [Task: 498/625] [Load: 0/0/0] [RAM: 125.7G] [Swap: 4.0G] [Cycle: 8.3G / Inst: 5.7G / IPC: 0.69 / CacheMiss : 13.7M(23%) / BrcMiss: 25.7M(1%) / Clk: 38.7G / MinFlt: 358 / MajFlt: 0] @@ -99,7 +98,7 @@ Output >>> - $ guider/guider.py top -R 5 -o + $ python3 guider/guider.py top -R 5 -o $ cat guider.out [Top Summary Info] @@ -137,7 +136,7 @@ Output >>> - $ guider/guider.py ttop + $ python3 guider/guider.py ttop [Top Info] [Time: 194025.590] [Interval: 1.0] [Ctxt: 4995] [Life: +0/-0] [OOM: 0] [IRQ: 1879] [Core: 8] [Task: 333/1188] [Load: 3.1/1.9/0.9] [RAM: 62.8G] ========================================================================================================================================================== @@ -159,7 +158,7 @@ Output >>> - # guider/guider.py utop -g yes -H + # python3 guider/guider.py utop -g yes -H [Top Usercall Info] [Time: 82094.260000] [Interval: 1.001784] [NrSamples: 955] [yes(7202): 28%(Usr/27%+Sys/0%)] [SampleTime: 0.000100] ========================================================================================================================================================== @@ -183,7 +182,7 @@ Output >>> - # guider/guider.py systop -g yes -H + # python3 guider/guider.py systop -g yes -H [Top Syscall Info] [Time: 82043.230000] [Interval: 1.000940] [NrSamples: 634] [yes(7202): 5%(Usr/4%+Sys/0%)] ========================================================================================================================================================== @@ -198,7 +197,7 @@ Output >>> - # guider/guider.py btop -g a.out -H + # python3 guider/guider.py btop -g a.out -H [Top Breakcall Info] [Time: 4542869.660] [Interval: 1.001] [NrSamples: 994] [a.out(1219772): 7%(Usr/0%+Sys/6%)] [guider(1219775): 97%] ========================================================================================================================================================== @@ -244,7 +243,7 @@ Output >>> - # guider/guider.py pytop -g iotop -H + # python3 guider/guider.py pytop -g iotop -H [Top Pycall Info] [Time: 7469667.000] [Interval: 1.003] [NrSamples: 283] [iotop(2943070): 13%(Usr/10%+Sys/2%)] [guider(2943073): 53%] [SampleRate: 0.001] ========================================================================================================================================================== @@ -288,7 +287,7 @@ Output >>> - # guider/guider.py ftop -g nginx + # python3 guider/guider.py ftop -g nginx [Top File Info] [Time: 497555.620] [Proc: 41] [FD: 2,047] [File: 87] [CPU: 95%(Usr:54%/Sys:41%)] (Unit: %/MB/NR) ========================================================================================================================================================== @@ -313,7 +312,7 @@ Output >>> - # guider/guider.py stacktop -g syslog + # python3 guider/guider.py stacktop -g syslog [Top Info] [Time: 7176163.830] [Interval: 1.0] [Ctxt: 2914] [Life: +13/-12] [IRQ: 5103] [Core: 24] [Task: 328/435] [RAM: 63876] [Swap: 65491] (Unit: %/MB/NR) [Cycle: 2G / Inst: 3G / IPC: 1.34 / CacheMiss: 6M(34%) / BranchMiss: 4M(0%) / Clock: 23G / MinFlt: 53,257 / MajFlt: 0] @@ -339,7 +338,7 @@ Output >>> - # guider/guider.py ptop -g yes + # python3 guider/guider.py ptop -g yes [Top Info] [Time: 7181955.420] [Interval: 1.0] [Ctxt: 121] [Life: +0/-0] [IRQ: 1947] [Core: 24] [Task: 317/424] [RAM: 63876] [Swap: 65491] (Unit: %/MB/NR) ========================================================================================================================================================== @@ -355,7 +354,7 @@ Output >>> - # guider/guider.py mtop + # python3 guider/guider.py mtop [Top Info] [Time: 1144292.910] [Inter: 1.0] [Ctxt: 739] [Life: +0/-0] [IRQ: 10740] [Core: 40] [Task: 509/725] [Load: 38/38/38] [RAM: 125.7G] [Swap: 4.0G] [N0-DMA > diff: 0 / free: 15.5M / high: 32.0K / low: 20.0K / managed: 15.5M / min: 8.0K / present: 15.6M / spanned: 16.0M ] @@ -380,7 +379,7 @@ Output >>> - # guider/guider.py ntop + # python3 guider/guider.py ntop [Top Info] [Time: 186473.960] [Interval: 1.0] [Ctxt: 7865] [Life: +0/-0] [OOM: 0] [IRQ: 4229] [Core: 8] [Task: 328/1171] [Load: 0.5/0.3/0.3] [RAM: 62.8G] ========================================================================================================================================================== @@ -403,7 +402,7 @@ Output >>> - # guider/guider.py disktop + # python3 guider/guider.py disktop [Top Info] [Time: 262411.830] [Inter: 1.0] [Ctxt: 802] [Life: +0/-0] [IRQ: 10675] [Core: 40] [Task: 481/700] [Load: 38/38/38] [RAM: 125.7G] [Swap: 4.0G] ========================================================================================================================================================== @@ -431,7 +430,7 @@ Output >>> - # guider/guider.py wtop -g yes + # python3 guider/guider.py wtop -g yes [Top Info] [Time: 7176629.490] [Interval: 1.0] [Ctxt: 195] [Life: +0/-0] [IRQ: 2688] [Core: 24] [Task: 327/434] [RAM: 63876] [Swap: 65491] (Unit: %/MB/NR) [Cycle: 2G / Inst: 6G / IPC: 2.75 / CacheMiss: 202K(19%) / BranchMiss: 325K(0%) / Clock: 23G / MinFlt: 4 / MajFlt: 0] @@ -455,7 +454,7 @@ Output >>> - # guider/guider.py btrace -g a.out -H + # python3 guider/guider.py btrace -g a.out -H _start/0x55e321d151ee [/home/peacelee/test/a.out] __libc_start_main/0x7ffb520af0b3 [/lib/x86_64-linux-gnu/libc-2.31.so] @@ -483,7 +482,7 @@ Output >>> - # guider/guider.py btrace -g yes -H -c \|getret + # python3 guider/guider.py btrace -g yes -H -c \|getret 0.532473 0x2cf0/0x560d7fd28cf0(0x1,0x560d81815440,0x2000,0x7faab23c8640,0x560d81815440,0x7c) [/usr/bin/yes] 0.532488 0x4c40/0x560d7fd2ac40(0x1,0x560d81815440,0x2000,0x7faab23c8640,0x560d81815440,0x7c) [/usr/bin/yes] @@ -506,7 +505,7 @@ Output >>> - $ guider/guider.py rtop & + $ python3 guider/guider.py rtop & $ cat /tmp/guider.report { @@ -637,7 +636,7 @@ Output >>> - # guider/guider.py limitcpu -g 22371:50 -v + # python3 guider/guider.py limitcpu -g 22371:50 -v [Info] limited cpu usage of yes(22371) process to 50%, it used 50% @@ -647,7 +646,7 @@ Output >>> - # guider/guider.py sigtrace -g a.out + # python3 guider/guider.py sigtrace -g a.out [INFO] start profiling a.out(3100585)... @@ -686,19 +685,19 @@ Output >>> - # guider/guider.py setsched r:90:22371 + # python3 guider/guider.py setsched r:90:22371 [Info] changed the priority of guider(22371) to 90[R] >>> - # guider/guider.py remote -g a.out -c usercall:write#1#HOOK#4 + # python3 guider/guider.py remote -g a.out -c usercall:write#1#HOOK#4 [usercall] write(7f94ed747140)(1, HOOK, 4) = 0x4(4) >>> - # guider/guider.py printenv -g systemd + # python3 guider/guider.py printenv -g systemd [ systemd(1) ] ----------------------------------------------------------------------------- @@ -741,13 +740,13 @@ Output >>> - # guider/guider.py kill -stop yes + # python3 guider/guider.py kill -stop yes [Info] sent SIGSTOP to yes(10594) >>> - # guider/guider.py printbind -g yes + # python3 guider/guider.py printbind -g yes [Function Bind Info] [Target: yes(410113)] ========================================================================================================================================================== @@ -774,7 +773,7 @@ Output >>> - # guider/guider.py rec -a -e m,b + # python3 guider/guider.py rec -a -e m,b [Thread Info] [ Elapsed: 2.050 ] [ Start: 2849868.198 ] [ Running: 112 ] [ CtxSwc: 3357 ] [ LogSize: 4054 KB ] [ Unit: Sec/MB/NR ] ========================================================================================================================================================== @@ -808,8 +807,8 @@ Output >>> - # guider/guider.py iorec -s - # guider/guider.py report -a + # python3 guider/guider.py iorec -s + # python3 guider/guider.py report -a [Thread Block Info] (Unit: NR) ========================================================================================================================================================== @@ -882,9 +881,9 @@ Output >>> - # guider/guider.py iorec -s - # guider/guider.py report -q RALIST - # guider/guider.py readahead readahead.list + # python3 guider/guider.py iorec -s + # python3 guider/guider.py report -q RALIST + # python3 guider/guider.py readahead readahead.list [INFO] start readahead from '/home/peacelee/guider/guider/readahead.list' @@ -896,7 +895,7 @@ Output >>> - # guider/guider.py sysrec + # python3 guider/guider.py sysrec [Thread Syscall Info] (Unit: Sec/NR) ========================================================================================================================================================== @@ -937,7 +936,7 @@ Output >>> - # guider/guider.py rec -e L + # python3 guider/guider.py rec -e L [Thread Futex Lock Info] [ Elapsed : 1.225 ] (Unit: Sec/NR) ========================================================================================================================================================== @@ -959,7 +958,7 @@ Output >>> - # guider/guider.py rec -s . -K openfile:getname::**string + # python3 guider/guider.py rec -s . -K openfile:getname::**string [Thread KERNEL Event Info] ========================================================================================================================================================== @@ -1008,8 +1007,8 @@ Output >>> - # guider/guider.py funcrec -s . - # guider/guider.py report -a + # python3 guider/guider.py funcrec -s . + # python3 guider/guider.py report -a # cat guider.out [Function CPU Info] [Cnt: 394] [Interval: 8ms] (USER) @@ -1043,8 +1042,8 @@ Output >>> - # guider/guider.py funcrec -e m -s . - # guider/guider.py report -a + # python3 guider/guider.py funcrec -e m -s . + # python3 guider/guider.py report -a # cat guider.out [Function Page Info] [Total: 11.4M] [Alloc: 11.4M(817)] [Free: 188.0K(47)] (USER) @@ -1088,7 +1087,7 @@ Output >>> - # guider/guider.py filerec + # python3 guider/guider.py filerec [File Usage Info] [ File: 281 ] [ RAM: 78.0M ] [ Keys: Foward/Back/Save/Quit ] ========================================================================================================================================================== @@ -1128,62 +1127,98 @@ Output >>> - # guider/guider.py draw guider.out + $ python3 guider/guider.py top -o guider.out + $ python3 guider/guider.py draw guider.out + +>>> graph chart -dashboard + +>>> + + # python3 guider/guider.py rec -s guider.dat + # python3 guider/guider.py draw guider.dat + +>>> + timeline + +>>> + + # python3 guider/guider.py utop -g testTask -H -o guider.out + # python3 guider/guider.py drawflame guider.out + +>>> + flamegraph + +>>> + + $ python3 guider/guider.py top -o test1.out + $ python3 guider/guider.py top -o test2.out + $ python3 guider/guider.py top -o test3.out + $ python3 guider/guider.py top -o test4.out + $ python3 guider/guider.py top -o test5.out + $ python3 guider/guider.py drawavg "test1.out, test2.out, test3.out, test4.out, test5.out" + +>>> + drawavg + +>>> + + $ python3 guider/guider.py req "https://www.google.com|https://www.naver.com" -R 1000 -o guider.out + $ python3 guider/guider.py drawreq guider.out + +>>> + drawreq +>>> + + webservice + +>>> + +dashboard + How to use ======= ``` Enter the following command to see all commands supported by the guider: - $ guider/guider.py --help - $ python -m guider --help + $ python3 guider/guider.py --help + $ python3 -m guider --help $ guider --help Enter the following command to start tracing for all threads: - # guider/guider.py record -a + # python3 guider/guider.py record -a Enter the following command to start monitoring for all processes: - $ guider/guider.py top -a + $ python3 guider/guider.py top -a Enter the command in the format shown bellow to see options and examples for each command: - $ guider/guider.py record -h - $ guider/guider.py top -h + $ python3 guider/guider.py record -h + $ python3 guider/guider.py top -h Visit the following link to see the output of guider: - https://github.com/iipeace/guider/wiki ``` -Requirement -======= - -``` -- Linux Kernel (>= 2.6) -- Python (>= 2.7) -``` - - Build & Installation ======= ``` If you can run 'pip' on your system then just enter the following commands: - # pip install guider # pip3 install guider and just run the following commands: - # python -m guider + # python3 -m guider # guider Otherwise, download the source from https://github.com/iipeace/guider, -and just run "guider/guider.py" on shell. +and just run "python3 guider/guider.py" on shell. If you want to run guider faster and lighter after downloading the source, then build and install it on your system as below. @@ -1283,7 +1318,7 @@ COMMAND: event (Linux) list (Linux/macOS/Windows) send (Linux) - server (Linux) + server (Linux/macOS) start (Linux) [PROFILE] filerec (Linux) diff --git a/guider/guider.py b/guider/guider.py index a516cddd..416d8bb5 100755 --- a/guider/guider.py +++ b/guider/guider.py @@ -7,7 +7,7 @@ __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" -__revision__ = "210725" +__revision__ = "210727" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" @@ -6910,9 +6910,10 @@ def setRemoteServer(value, tcp=False): SysMgr.printErr(( "wrong value for remote connection, " "local address and remote address are same " - "with %s:%s") % (ip, port)) + "(%s:%s)") % (ip, port)) sys.exit(0) + # check request # if not ip or not port or \ not SysMgr.isValidRequest(service): reqList = '' @@ -18508,6 +18509,7 @@ def __init__(self, onlyInstance=False): self.diskData = {} self.storageData = {} self.prevStorageData = {} + self.storageMapData = {} self.ipcData = {} self.prevIpcData = {} self.userData = {} @@ -21048,6 +21050,18 @@ def getFdName(pid, fd): @staticmethod def getPwd(pid): + if not SysMgr.isLinux: + try: + psutil = SysMgr.getPkg('psutil', False) + if psutil: + return psutil.Process(long(pid)).environ()['PWD'] + else: + return None + except SystemExit: + sys.exit(0) + except: + return None + try: pwdPath = '%s/%s/cwd' % (SysMgr.procPath, pid) pwd = os.readlink(pwdPath) @@ -21090,7 +21104,7 @@ def getComm(pid, cache=False, save=False): except SystemExit: sys.exit(0) except: - pass + return None comm = None commPath = \ @@ -21990,6 +22004,8 @@ def _checkMode(): not SysMgr.checkMode('report') and \ not SysMgr.checkMode('req') and \ not SysMgr.checkMode('rtop') and \ + not (SysMgr.checkMode('server') and \ + (SysMgr.isLinux or SysMgr.isDarwin)) and \ not SysMgr.checkMode('strings') and \ not SysMgr.checkMode('sym2addr') and \ not SysMgr.checkMode('tail') and \ @@ -22049,6 +22065,9 @@ def _checkMode(): (sys.argv[1], sys.platform)) sys.exit(0) + # set default SIGINT handler # + signal.signal(signal.SIGINT, SysMgr.stopHandler) + # macOS # elif sys.platform.startswith('darwin'): SysMgr.isLinux = False @@ -22286,7 +22305,7 @@ def getCmdList(): 'event': ('Event', 'Linux'), 'list': ('List', 'Linux/macOS/Windows'), 'send': ('Signal', 'Linux'), - 'server': ('Server', 'Linux'), + 'server': ('Server', 'Linux/macOS'), 'start': ('Signal', 'Linux'), }, 'test': { @@ -33747,10 +33766,15 @@ def getRuntime(sec=False): def getUptime(): if not SysMgr.isLinux: # get psutil object # - psutil = SysMgr.getPkg('psutil', False) - if not psutil: + try: + psutil = SysMgr.getPkg('psutil', False) + if not psutil: + return -1 + return time.time() - psutil.boot_time() + except SystemExit: + sys.exit(0) + except: return -1 - return time.time() - psutil.boot_time() try: SysMgr.uptimeFd.seek(0) @@ -36604,18 +36628,19 @@ def getIdleTime(): try: cpuBuf = None SysMgr.statFd.seek(0) - cpuBuf = SysMgr.statFd.readline() + cpuBuf = SysMgr.statFd.readlines()[0] except SystemExit: sys.exit(0) except: try: cpuPath = "%s/stat" % SysMgr.procPath SysMgr.statFd = open(cpuPath, 'r') - cpuBuf = SysMgr.statFd.readline() + cpuBuf = SysMgr.statFd.readlines()[0] except SystemExit: sys.exit(0) except: SysMgr.printOpenWarn(cpuPath) + return 0 return long(cpuBuf.split()[4]) @@ -42122,6 +42147,8 @@ def _openStatFd(tid, isProcess): if not SysMgr.isLinux: try: return SysMgr.getPkg('psutil').Process(long(tid)) + except SystemExit: + sys.exit(0) except: return None @@ -45885,6 +45912,134 @@ def saveUserInfo(self): + def getStorageMapInfo(self): + if not SysMgr.isDarwin and not SysMgr.isWindows: + return {} + + # get subprocess object # + subprocess = SysMgr.getPkg('subprocess') + + if SysMgr.isDarwin: + command = ["diskutil", "list"] + shell = False + else: + # find powershell path # + powershellPath = None + for item in os.environ['PATH'].split(';'): + if 'WindowsPowerShell' in item: + powershellPath = '%s/powershell.exe' % item + break + if not powershellPath: + return + + command = [powershellPath, "get-partition"] + shell = True + + # start diskutil process # + try: + proc = subprocess.Popen( + command, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, bufsize=-1, shell=shell) + except SystemExit: + sys.exit(0) + except: + SysMgr.printErr( + "fail to execute '%s'" % ' '.join(command), reason=True) + sys.exit(0) + + mapTable = {} + path = None + node = None + prev = None + devnum = -1 + + while 1: + try: + # read a line from diskutil process # + line = proc.stdout.readline() + except SystemExit: + sys.exit(0) + except: + SysMgr.printErr( + "fail to read from '%s'" % ' '.join(command), reason=True) + sys.exit(0) + + # handle error # + if not line: + err = proc.stderr.read() + if err: + try: + proc.terminate() + except: + pass + SysMgr.printErr(err[err.find(':') + 2:]) + sys.exit(0) + break + + # decode data # + try: + line = line.decode() + except SystemExit: + sys.exit(0) + except: + pass + + # macOS # + if SysMgr.isDarwin: + # disk node # + if line.startswith('/'): + path, attr = line.split(' ', 1) + continue + + line = line.strip() + if not line: + continue + elif line[0].isdigit(): + prev = node + node = '/dev/%s' % line.split()[-1] + mapTable[node] = path + elif line.startswith('Physical Store '): + # change previous map info # + prevValue = mapTable[node] + mapTable.pop(node, None) + path = node = '/dev/%s' % line.split()[-1] + + # update new physical path # + while 1: + try: + if path == mapTable[path]: + break + else: + path = mapTable[path] + except: + break + # Windows # + else: + line = line.strip() + if not line: + continue + elif line.startswith('PartitionNumber'): + devnum += 1 + continue + elif line[0].isdigit(): + items = line.split() + # drive # + if items[1].isalpha(): + node = '%s:\\' % items[1] + path = 'PhysicalDrive%s' % devnum + else: + continue + + # check values # + if not node or not path: + continue + + mapTable[node] = path + + return mapTable + + + def updateStorageInfoGen(self): # get psutil object # psutil = SysMgr.getPkg('psutil') @@ -45926,44 +46081,38 @@ def updateStorageInfoGen(self): 'fail to get disk stats') return - # only one physical device # - if len(stats) == 1: - value = stats[list(stats.keys())[0]] - for dev in list(self.storageData.keys()): - try: - target = self.storageData[dev] - target['read'] = value[2] >> 20 - target['write'] = value[3] >> 20 - target['readtime'] = value[4] - target['writetime'] = value[5] - except SystemExit: - sys.exit(0) - except: - SysMgr.printWarn( - "fail to get disk stat for '%s'" % dev, - reason=True) - # multiple physical devices and partitions (same number) # - elif len(stats) == len(partition): - statList = list(stats.keys()) - for idx, dev in enumerate(list(self.storageData.keys())): - try: - value = stats[statList[idx]] - target = self.storageData[dev] - target['read'] = value[2] >> 20 - target['write'] = value[3] >> 20 - target['readtime'] = value[4] - target['writetime'] = value[5] - except SystemExit: - sys.exit(0) - except: - SysMgr.printWarn( - "fail to get disk stat for '%s'" % dev, - reason=True) - # different number for physical devices and partitions # - else: - # TODO: map disk name for physical device to logical device # - SysMgr.printWarn( - 'fail to map multiple physical storage to logical storage') + # get logical to physical disk map table # + if not self.storageMapData: + self.storageMapData = self.getStorageMapInfo() + mapTable = self.storageMapData + + for dev in list(self.storageData.keys()): + try: + # get physical device path # + if dev in mapTable: + if SysMgr.isWindows: + rpath = mapTable[dev] + else: + rpath = mapTable[dev].split('/')[-1] + else: + continue + + # apply stat # + value = stats[rpath] + target = self.storageData[dev] + target['read'] = value[2] >> 20 + target['write'] = value[3] >> 20 + target['readtime'] = value[4] + target['writetime'] = value[5] + except SystemExit: + sys.exit(0) + except: + # reset map table # + self.storageMapData = {} + + SysMgr.printWarn( + "fail to get disk stat for '%s'" % dev, + reason=True) except SystemExit: sys.exit(0) except: @@ -48662,10 +48811,13 @@ def _updateTaskInfo(dbusData, sentData, recvData): else: avr = long(0) + # check error # if data['err'] > 0: errstr = ', Err: %s' % data['err'] + color = 'RED' else: errstr = '' + color = 'CYAN' if data['max'] > 0: name = \ @@ -48675,7 +48827,7 @@ def _updateTaskInfo(dbusData, sentData, recvData): count = convertNum(value['cnt']) size = convertSize(data['size']) - name = convertColor(name, 'CYAN') + name = convertColor(name, color) dbusList.append( "{0:>4}({1:>6}/{2:>3}%) {3:1}".format( @@ -48739,13 +48891,16 @@ def _checkRepeatCnt(): _updateTaskInfo(prevDbusData, prevSentData, prevRecvData) if DbusMgr.dbgObj: - cpuUsage = DbusMgr.dbgObj.getCpuUsage() - ttime = cpuUsage[0] / SysMgr.uptimeDiff - utime = cpuUsage[1] / SysMgr.uptimeDiff - stime = cpuUsage[2] / SysMgr.uptimeDiff - cpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime) + cpuUsage = DbusMgr.dbgObj.getCpuUsage(system=True) + diff = SysMgr.uptimeDiff + ttime = cpuUsage[0] / diff + utime = cpuUsage[1] / diff + stime = cpuUsage[2] / diff + ctime = 100 - (cpuUsage[3] / diff) + mcpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime) + sysCpuStr = '%d%%' % ctime else: - cpuStr = '?' + cpuStr = mcpuStr = '?' # set error # nrErr = prevDbusData['totalErr'] @@ -48757,9 +48912,10 @@ def _checkRepeatCnt(): # print title # SysMgr.addPrint( ("[%s] [Time: %7.3f] [Interval: %.1f] " - "[NrMsg: %s] [NrErr: %s] [CPU: %s]\n") % \ + "[NrMsg: %s] [NrErr: %s] [CPU: %s] [%s(%s): %s] \n") % \ ('D-Bus Info', SysMgr.uptime, SysMgr.uptimeDiff, - convertNum(prevDbusData['totalCnt']), nrErr, cpuStr)) + convertNum(prevDbusData['totalCnt']), nrErr, + sysCpuStr, DbusMgr.dbgObj.comm, DbusMgr.dbgObj.pid, mcpuStr)) # print resource usage of tasks # taskManager.printSystemUsage() @@ -49397,7 +49553,7 @@ def _getDefaultTasks(comm, sibling=True): # initialize task stat # DbusMgr.dbgObj = Debugger(SysMgr.pid, attach=False) DbusMgr.dbgObj.initValues() - DbusMgr.dbgObj.getCpuUsage() + DbusMgr.dbgObj.getCpuUsage(system=True) # define common list # busList = [] @@ -49703,6 +49859,7 @@ class DltAnalyzer(object): pids = [] procInfo = None dltData = {'cnt': long(0)} + dbgObj = None @staticmethod def printSummary(): @@ -49712,12 +49869,28 @@ def printSummary(): # update uptime # SysMgr.updateUptime() + # update CPU usage # + if DltAnalyzer.dbgObj: + cpuUsage = DltAnalyzer.dbgObj.getCpuUsage(system=True) + diff = SysMgr.uptimeDiff + ttime = cpuUsage[0] / diff + utime = cpuUsage[1] / diff + stime = cpuUsage[2] / diff + ctime = 100 - (cpuUsage[3] / diff) + mcpuStr = '%d%%(Usr:%d%%/Sys:%d%%)' % (ttime, utime, stime) + procInfo = '%s(%s)' % \ + (DltAnalyzer.dbgObj.comm, DltAnalyzer.dbgObj.pid) + sysCpuStr = '%d%%' % ctime + else: + procInfo = cpuStr = mcpuStr = '?' + # print title # - SysMgr.addPrint( - ("[%s] [Time: %7.3f] [Interval: %.1f] [NrMsg: %s]\n") % \ - ('DLT Info', SysMgr.uptime, - SysMgr.uptimeDiff, - convertFunc(DltAnalyzer.dltData['cnt']))) + SysMgr.addPrint(( + "[%s] [Time: %7.3f] [Interval: %.1f] [NrMsg: %s] " + "[CPU: %s] [%s: %s]\n") % \ + ('DLT Info', SysMgr.uptime, SysMgr.uptimeDiff, + convertFunc(DltAnalyzer.dltData['cnt']), + sysCpuStr, procInfo, mcpuStr)) # update daemon stat # DltAnalyzer.procInfo.saveProcInstance() @@ -50538,6 +50711,17 @@ class DLTFile(Structure): DltAnalyzer.msgColorList.append( UtilMgr.convColor(item, color, 5, 'left')) + # initialize task stat # + try: + DltAnalyzer.dbgObj = Debugger(SysMgr.pid, attach=False) + DltAnalyzer.dbgObj.initValues() + DltAnalyzer.dbgObj.getCpuUsage(system=True) + except SystemExit: + sys.exit(0) + except: + SysMgr.printWarn( + 'fail to read CPU usage', reason=True) + # get log level option # try: if SysMgr.customCmd: @@ -59291,7 +59475,7 @@ def getCpuUsage(self, system=False): # get system CPU usage # if system: itime = SysMgr.getIdleTime() - if self.prevCpuStat and self.prevCpuStat[3]: + if itime and self.prevCpuStat and self.prevCpuStat[3]: nrCore = SysMgr.getNrCore() diff = itime - self.prevCpuStat[3] ctime = diff / float(nrCore) @@ -64035,6 +64219,8 @@ def getSymOffset(symbol, binPath, objdumpPath=None, loadAddr=False): proc = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1) + except SystemExit: + sys.exit(0) except: SysMgr.printErr( "fail to execute %s to get address from binary" % objdumpPath) @@ -64044,6 +64230,8 @@ def getSymOffset(symbol, binPath, objdumpPath=None, loadAddr=False): try: # read a line from objdump process # line = proc.stdout.readline() + except SystemExit: + sys.exit(0) except: SysMgr.printErr( "fail to read output from objdump", True) @@ -86903,11 +87091,17 @@ def printTaskUsageGen(self, idIndex=False): else: vss = value['vss'] # MB # + # user # + if value['user']: + user = value['user'][:6] + else: + user = ' ' + + # etc # code = 0 shr = 0 swap = 0 pri = value['nice'] - user = value['user'][:6] if ppid in self.procData: etc = '%s(%s)' % (self.procData[ppid]['comm'], ppid) diff --git a/setup.py b/setup.py index b64186b9..cf80ec0a 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name = 'guider', - version = '3.9.84', + version = '3.9.85', license = 'GPL2', description = 'A system-wide analyzer of performance', author = 'Peace Lee',