schedgraph.py (187376) | schedgraph.py (187379) |
---|---|
1#!/usr/local/bin/python 2 3# Copyright (c) 2002-2003, Jeffrey Roberson <jeff@freebsd.org> 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: --- 10 unchanged lines hidden (view full) --- 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# | 1#!/usr/local/bin/python 2 3# Copyright (c) 2002-2003, Jeffrey Roberson <jeff@freebsd.org> 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: --- 10 unchanged lines hidden (view full) --- 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# |
27# $FreeBSD: head/tools/sched/schedgraph.py 187376 2009-01-18 04:49:01Z jeff $ | 27# $FreeBSD: head/tools/sched/schedgraph.py 187379 2009-01-18 05:44:31Z jeff $ |
28 29import sys 30import re 31import random 32from Tkinter import * 33 34# To use: 35# - Install the ports/x11-toolkits/py-tkinter package; e.g. --- 45 unchanged lines hidden (view full) --- 81 ("thread exit", "grey"), 82 ("proc exit", "grey"), 83 ("callwheel idle", "grey"), 84 ("callout running", "green"), 85 ("lock acquire", "blue"), 86 ("lock contest", "purple"), 87 ("failed lock try", "red"), 88 ("lock release", "grey"), | 28 29import sys 30import re 31import random 32from Tkinter import * 33 34# To use: 35# - Install the ports/x11-toolkits/py-tkinter package; e.g. --- 45 unchanged lines hidden (view full) --- 81 ("thread exit", "grey"), 82 ("proc exit", "grey"), 83 ("callwheel idle", "grey"), 84 ("callout running", "green"), 85 ("lock acquire", "blue"), 86 ("lock contest", "purple"), 87 ("failed lock try", "red"), 88 ("lock release", "grey"), |
89 ("tick", "black"), | 89 ("statclock", "black"), |
90 ("prio", "black"), 91 ("lend prio", "black"), 92 ("wokeup", "black") 93] 94 95cpucolors = [ 96 ("CPU 0", "light grey"), 97 ("CPU 1", "dark grey"), --- 22 unchanged lines hidden (view full) --- 120ticksps = None 121status = None 122colormap = None 123ktrfile = None 124clockfreq = None 125sources = [] 126lineno = -1 127 | 90 ("prio", "black"), 91 ("lend prio", "black"), 92 ("wokeup", "black") 93] 94 95cpucolors = [ 96 ("CPU 0", "light grey"), 97 ("CPU 1", "dark grey"), --- 22 unchanged lines hidden (view full) --- 120ticksps = None 121status = None 122colormap = None 123ktrfile = None 124clockfreq = None 125sources = [] 126lineno = -1 127 |
128Y_BORDER = 10 129X_BORDER = 10 130Y_COUNTER = 80 131Y_EVENTSOURCE = 10 132XY_POINT = 4 133 |
|
128class Colormap: 129 def __init__(self, table): 130 self.table = table 131 self.map = {} 132 for entry in table: 133 self.map[entry[0]] = entry[1] 134 135 def lookup(self, name): --- 533 unchanged lines hidden (view full) --- 669 670class PointEvent(Event): 671 type = "point" 672 def __init__(self, source, name, cpu, timestamp, attrs): 673 Event.__init__(self, source, name, cpu, timestamp, attrs) 674 675 def draw(self, canvas, xpos, ypos): 676 color = colormap.lookup(self.name) | 134class Colormap: 135 def __init__(self, table): 136 self.table = table 137 self.map = {} 138 for entry in table: 139 self.map[entry[0]] = entry[1] 140 141 def lookup(self, name): --- 533 unchanged lines hidden (view full) --- 675 676class PointEvent(Event): 677 type = "point" 678 def __init__(self, source, name, cpu, timestamp, attrs): 679 Event.__init__(self, source, name, cpu, timestamp, attrs) 680 681 def draw(self, canvas, xpos, ypos): 682 color = colormap.lookup(self.name) |
677 l = canvas.create_oval(xpos - 6, ypos + 1, xpos + 6, ypos - 11, | 683 l = canvas.create_oval(xpos - XY_POINT, ypos, 684 xpos + XY_POINT, ypos - (XY_POINT * 2), |
678 fill=color, width=0, | 685 fill=color, width=0, |
679 tags=("all", "point", "event", self.name, self.source.tag)) | 686 tags=("event", self.type, self.name, self.source.tag)) |
680 Event.draw(self, canvas, xpos, ypos, l) 681 682 return xpos 683 684class StateEvent(Event): 685 type = "state" 686 def __init__(self, source, name, cpu, timestamp, attrs): 687 Event.__init__(self, source, name, cpu, timestamp, attrs) --- 8 unchanged lines hidden (view full) --- 696 if (duration < 0): 697 duration = 0 698 print "Unsynchronized timestamp" 699 print self.cpu, self.timestamp 700 print next.cpu, next.timestamp 701 delta = duration / canvas.ratio 702 l = canvas.create_rectangle(xpos, ypos, 703 xpos + delta, ypos - 10, fill=color, width=0, | 687 Event.draw(self, canvas, xpos, ypos, l) 688 689 return xpos 690 691class StateEvent(Event): 692 type = "state" 693 def __init__(self, source, name, cpu, timestamp, attrs): 694 Event.__init__(self, source, name, cpu, timestamp, attrs) --- 8 unchanged lines hidden (view full) --- 703 if (duration < 0): 704 duration = 0 705 print "Unsynchronized timestamp" 706 print self.cpu, self.timestamp 707 print next.cpu, next.timestamp 708 delta = duration / canvas.ratio 709 l = canvas.create_rectangle(xpos, ypos, 710 xpos + delta, ypos - 10, fill=color, width=0, |
704 tags=("all", "state", "event", self.name, self.source.tag)) | 711 tags=("event", self.type, self.name, self.source.tag)) |
705 Event.draw(self, canvas, xpos, ypos, l) 706 707 return (xpos + delta) 708 709class CountEvent(Event): 710 type = "count" 711 def __init__(self, source, count, cpu, timestamp, attrs): 712 count = int(count) --- 7 unchanged lines hidden (view full) --- 720 color = colormap.lookup("count") 721 self.duration = duration = next.timestamp - self.timestamp 722 self.attrs.insert(0, ("count", self.count)) 723 self.attrs.insert(1, ("duration", ticks2sec(duration))) 724 delta = duration / canvas.ratio 725 yhight = self.source.yscale() * self.count 726 l = canvas.create_rectangle(xpos, ypos - yhight, 727 xpos + delta, ypos, fill=color, width=0, | 712 Event.draw(self, canvas, xpos, ypos, l) 713 714 return (xpos + delta) 715 716class CountEvent(Event): 717 type = "count" 718 def __init__(self, source, count, cpu, timestamp, attrs): 719 count = int(count) --- 7 unchanged lines hidden (view full) --- 727 color = colormap.lookup("count") 728 self.duration = duration = next.timestamp - self.timestamp 729 self.attrs.insert(0, ("count", self.count)) 730 self.attrs.insert(1, ("duration", ticks2sec(duration))) 731 delta = duration / canvas.ratio 732 yhight = self.source.yscale() * self.count 733 l = canvas.create_rectangle(xpos, ypos - yhight, 734 xpos + delta, ypos, fill=color, width=0, |
728 tags=("all", "count", "event", self.name, self.source.tag)) | 735 tags=("event", self.type, self.name, self.source.tag)) |
729 Event.draw(self, canvas, xpos, ypos, l) 730 return (xpos + delta) 731 732class PadEvent(StateEvent): 733 type = "pad" 734 def __init__(self, source, cpu, timestamp, last=0): 735 if (last): 736 cpu = source.events[len(source.events) -1].cpu --- 55 unchanged lines hidden (view full) --- 792 cpux = xpos 793 cpu = event.cpu 794 xpos = event.draw(canvas, xpos, ypos) 795 self.drawcpu(canvas, cpu, cpux, xpos, ypos) 796 797 def drawname(self, canvas, ypos): 798 self.y = ypos 799 ypos = ypos - (self.ysize() / 2) | 736 Event.draw(self, canvas, xpos, ypos, l) 737 return (xpos + delta) 738 739class PadEvent(StateEvent): 740 type = "pad" 741 def __init__(self, source, cpu, timestamp, last=0): 742 if (last): 743 cpu = source.events[len(source.events) -1].cpu --- 55 unchanged lines hidden (view full) --- 799 cpux = xpos 800 cpu = event.cpu 801 xpos = event.draw(canvas, xpos, ypos) 802 self.drawcpu(canvas, cpu, cpux, xpos, ypos) 803 804 def drawname(self, canvas, ypos): 805 self.y = ypos 806 ypos = ypos - (self.ysize() / 2) |
800 self.item = canvas.create_text(10, ypos, anchor="w", text=self.name) | 807 self.item = canvas.create_text(X_BORDER, ypos, anchor="w", 808 text=self.name) |
801 return (self.item) 802 803 def drawcpu(self, canvas, cpu, fromx, tox, ypos): 804 cpu = "CPU " + str(cpu) 805 color = cpucolormap.lookup(cpu) 806 # Create the cpu background colors default to hidden 807 l = canvas.create_rectangle(fromx, 808 ypos - self.ysize() - canvas.bdheight, 809 tox, ypos + canvas.bdheight, fill=color, width=0, | 809 return (self.item) 810 811 def drawcpu(self, canvas, cpu, fromx, tox, ypos): 812 cpu = "CPU " + str(cpu) 813 color = cpucolormap.lookup(cpu) 814 # Create the cpu background colors default to hidden 815 l = canvas.create_rectangle(fromx, 816 ypos - self.ysize() - canvas.bdheight, 817 tox, ypos + canvas.bdheight, fill=color, width=0, |
810 tags=("all", "cpuinfo", cpu, self.tag), state="hidden") | 818 tags=("cpubg", cpu, self.tag), state="hidden") |
811 self.cpuitems.append(l) 812 813 def move(self, canvas, xpos, ypos): 814 canvas.move(self.tag, xpos, ypos) 815 816 def movename(self, canvas, xpos, ypos): 817 self.y += ypos 818 canvas.move(self.item, xpos, ypos) 819 820 def ysize(self): | 819 self.cpuitems.append(l) 820 821 def move(self, canvas, xpos, ypos): 822 canvas.move(self.tag, xpos, ypos) 823 824 def movename(self, canvas, xpos, ypos): 825 self.y += ypos 826 canvas.move(self.item, xpos, ypos) 827 828 def ysize(self): |
821 return (10) | 829 return (Y_EVENTSOURCE) |
822 823 def eventat(self, i): 824 if (i >= len(self.events)): 825 return (None) 826 event = self.events[i] 827 return (event) 828 829 def findevent(self, timestamp): --- 23 unchanged lines hidden (view full) --- 853 if (count > Counter.groups[self.group]): 854 Counter.groups[self.group] = count 855 EventSource.fixup(self) 856 857 def ymax(self): 858 return (Counter.groups[self.group]) 859 860 def ysize(self): | 830 831 def eventat(self, i): 832 if (i >= len(self.events)): 833 return (None) 834 event = self.events[i] 835 return (event) 836 837 def findevent(self, timestamp): --- 23 unchanged lines hidden (view full) --- 861 if (count > Counter.groups[self.group]): 862 Counter.groups[self.group] = count 863 EventSource.fixup(self) 864 865 def ymax(self): 866 return (Counter.groups[self.group]) 867 868 def ysize(self): |
861 return (80) | 869 return (Y_COUNTER) |
862 863 def yscale(self): 864 return (self.ysize() / self.ymax()) 865 866class KTRFile: 867 def __init__(self, file): 868 self.timestamp_f = None 869 self.timestamp_l = None 870 self.locks = {} 871 self.callwheels = {} 872 self.ticks = {} 873 self.load = {} 874 self.crit = {} 875 self.stathz = 0 | 870 871 def yscale(self): 872 return (self.ysize() / self.ymax()) 873 874class KTRFile: 875 def __init__(self, file): 876 self.timestamp_f = None 877 self.timestamp_l = None 878 self.locks = {} 879 self.callwheels = {} 880 self.ticks = {} 881 self.load = {} 882 self.crit = {} 883 self.stathz = 0 |
884 self.eventcnt = 0 |
|
876 877 self.parse(file) 878 self.fixup() 879 global ticksps 880 ticksps = self.ticksps() | 885 886 self.parse(file) 887 self.fixup() 888 global ticksps 889 ticksps = self.ticksps() |
881 timespan = self.timespan() 882 print "first tick", self.timestamp_f, 883 print "last tick", self.timestamp_l 884 print "Ticks per second", ticksps 885 print "time span", timespan, "ticks", ticks2sec(timespan) | 890 span = self.timespan() 891 ghz = float(ticksps) / 1000000000.0 892 # 893 # Update the title with some stats from the file 894 # 895 titlestr = "SchedGraph: " 896 titlestr += ticks2sec(span) + " at %.3f ghz, " % ghz 897 titlestr += str(len(sources)) + " event sources, " 898 titlestr += str(self.eventcnt) + " events" 899 root.title(titlestr) |
886 887 def parse(self, file): 888 try: 889 ifp = open(file) 890 except: 891 print "Can't open", file 892 sys.exit(1) 893 --- 91 unchanged lines hidden (view full) --- 985 source = self.makeid(group, id, type) 986 if (type == "state"): 987 e = StateEvent(source, *args) 988 elif (type == "counter"): 989 e = CountEvent(source, *args) 990 elif (type == "point"): 991 e = PointEvent(source, *args) 992 if (e != None): | 900 901 def parse(self, file): 902 try: 903 ifp = open(file) 904 except: 905 print "Can't open", file 906 sys.exit(1) 907 --- 91 unchanged lines hidden (view full) --- 999 source = self.makeid(group, id, type) 1000 if (type == "state"): 1001 e = StateEvent(source, *args) 1002 elif (type == "counter"): 1003 e = CountEvent(source, *args) 1004 elif (type == "point"): 1005 e = PointEvent(source, *args) 1006 if (e != None): |
1007 self.eventcnt += 1 |
|
993 source.addevent(e); 994 return e 995 996 def setstathz(self, val, cpu): 997 self.stathz = int(val) 998 cpu = int(cpu) 999 try: 1000 ticks = self.ticks[cpu] --- 126 unchanged lines hidden (view full) --- 1127 status.startup("Drawing " + source.name) 1128 l = self.create_line(0, ypos, xsize, ypos, 1129 width=1, fill="black", tags=("all",)) 1130 self.lines.append(l) 1131 ypos += self.bdheight 1132 ypos += source.ysize() 1133 source.draw(self, ypos) 1134 ypos += self.bdheight | 1008 source.addevent(e); 1009 return e 1010 1011 def setstathz(self, val, cpu): 1012 self.stathz = int(val) 1013 cpu = int(cpu) 1014 try: 1015 ticks = self.ticks[cpu] --- 126 unchanged lines hidden (view full) --- 1142 status.startup("Drawing " + source.name) 1143 l = self.create_line(0, ypos, xsize, ypos, 1144 width=1, fill="black", tags=("all",)) 1145 self.lines.append(l) 1146 ypos += self.bdheight 1147 ypos += source.ysize() 1148 source.draw(self, ypos) 1149 ypos += self.bdheight |
1135 try: 1136 self.tag_raise("point", "state") 1137 self.tag_lower("cpuinfo", "all") 1138 except: 1139 pass | 1150 self.tag_raise("point", "state") 1151 self.tag_lower("cpubg", ALL) |
1140 self.create_line(0, ypos, xsize, ypos, | 1152 self.create_line(0, ypos, xsize, ypos, |
1141 width=1, fill="black", tags=("all",)) | 1153 width=1, fill="black", tags=("lines",)) |
1142 self.tag_bind("event", "<Enter>", self.mouseenter) 1143 self.tag_bind("event", "<Leave>", self.mouseexit) 1144 self.bind("<Button-1>", self.mousepress) 1145 self.bind("<Button-3>", self.master.mousepressright); 1146 self.bind("<Button-4>", self.wheelup) 1147 self.bind("<Button-5>", self.wheeldown) 1148 self.bind("<ButtonRelease-1>", self.master.mouserelease); 1149 self.bind("<B1-Motion>", self.master.mousemotion); --- 32 unchanged lines hidden (view full) --- 1182 1183 def wheeldown(self, event): 1184 self.parent.display_yview("scroll", 1, "units") 1185 1186 def wheelup(self, event): 1187 self.parent.display_yview("scroll", -1, "units") 1188 1189 def xsize(self): | 1154 self.tag_bind("event", "<Enter>", self.mouseenter) 1155 self.tag_bind("event", "<Leave>", self.mouseexit) 1156 self.bind("<Button-1>", self.mousepress) 1157 self.bind("<Button-3>", self.master.mousepressright); 1158 self.bind("<Button-4>", self.wheelup) 1159 self.bind("<Button-5>", self.wheeldown) 1160 self.bind("<ButtonRelease-1>", self.master.mouserelease); 1161 self.bind("<B1-Motion>", self.master.mousemotion); --- 32 unchanged lines hidden (view full) --- 1194 1195 def wheeldown(self, event): 1196 self.parent.display_yview("scroll", 1, "units") 1197 1198 def wheelup(self, event): 1199 self.parent.display_yview("scroll", -1, "units") 1200 1201 def xsize(self): |
1190 return ((ktrfile.timespan() / self.ratio) + 20) | 1202 return ((ktrfile.timespan() / self.ratio) + (X_BORDER * 2)) |
1191 1192 def ysize(self): 1193 ysize = 0 1194 for source in sources: 1195 if (source.hidden == 1): 1196 continue 1197 ysize += self.parent.sourcesize(source) 1198 return ysize 1199 1200 def scaleset(self, ratio): 1201 if (ktrfile == None): 1202 return 1203 oldratio = self.ratio 1204 xstart, xend = self.xview() 1205 midpoint = xstart + ((xend - xstart) / 2) 1206 1207 self.ratio = ratio 1208 self.updatescroll() | 1203 1204 def ysize(self): 1205 ysize = 0 1206 for source in sources: 1207 if (source.hidden == 1): 1208 continue 1209 ysize += self.parent.sourcesize(source) 1210 return ysize 1211 1212 def scaleset(self, ratio): 1213 if (ktrfile == None): 1214 return 1215 oldratio = self.ratio 1216 xstart, xend = self.xview() 1217 midpoint = xstart + ((xend - xstart) / 2) 1218 1219 self.ratio = ratio 1220 self.updatescroll() |
1209 self.scale("all", 0, 0, float(oldratio) / ratio, 1) | 1221 self.scale(ALL, 0, 0, float(oldratio) / ratio, 1) |
1210 1211 xstart, xend = self.xview() 1212 xsize = (xend - xstart) / 2 1213 self.xview_moveto(midpoint - xsize) 1214 1215 def updatescroll(self): 1216 self.configure(scrollregion=(0, 0, self.xsize(), self.ysize())) 1217 --- 38 unchanged lines hidden (view full) --- 1256class SchedGraph(Frame): 1257 def __init__(self, master): 1258 Frame.__init__(self, master) 1259 self.menu = None 1260 self.names = None 1261 self.display = None 1262 self.scale = None 1263 self.status = None | 1222 1223 xstart, xend = self.xview() 1224 xsize = (xend - xstart) / 2 1225 self.xview_moveto(midpoint - xsize) 1226 1227 def updatescroll(self): 1228 self.configure(scrollregion=(0, 0, self.xsize(), self.ysize())) 1229 --- 38 unchanged lines hidden (view full) --- 1268class SchedGraph(Frame): 1269 def __init__(self, master): 1270 Frame.__init__(self, master) 1271 self.menu = None 1272 self.names = None 1273 self.display = None 1274 self.scale = None 1275 self.status = None |
1264 self.bdheight = 10 | 1276 self.bdheight = Y_BORDER |
1265 self.clicksource = None 1266 self.lastsource = None 1267 self.pack(expand=1, fill="both") 1268 self.buildwidgets() 1269 self.layout() 1270 1271 def buildwidgets(self): 1272 global status --- 281 unchanged lines hidden (view full) --- 1554if (len(sys.argv) != 2 and len(sys.argv) != 3): 1555 print "usage:", sys.argv[0], "<ktr file> [clock freq in ghz]" 1556 sys.exit(1) 1557 1558if (len(sys.argv) > 2): 1559 clockfreq = float(sys.argv[2]) 1560 1561root = Tk() | 1277 self.clicksource = None 1278 self.lastsource = None 1279 self.pack(expand=1, fill="both") 1280 self.buildwidgets() 1281 self.layout() 1282 1283 def buildwidgets(self): 1284 global status --- 281 unchanged lines hidden (view full) --- 1566if (len(sys.argv) != 2 and len(sys.argv) != 3): 1567 print "usage:", sys.argv[0], "<ktr file> [clock freq in ghz]" 1568 sys.exit(1) 1569 1570if (len(sys.argv) > 2): 1571 clockfreq = float(sys.argv[2]) 1572 1573root = Tk() |
1562root.title("Scheduler Graph") | 1574root.title("SchedGraph") |
1563colormap = Colormap(eventcolors) 1564cpucolormap = Colormap(cpucolors) 1565graph = SchedGraph(root) 1566ktrfile = KTRFile(sys.argv[1]) 1567graph.draw() 1568root.mainloop() | 1575colormap = Colormap(eventcolors) 1576cpucolormap = Colormap(cpucolors) 1577graph = SchedGraph(root) 1578ktrfile = KTRFile(sys.argv[1]) 1579graph.draw() 1580root.mainloop() |