Deleted Added
full compact
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()