svn commit: r187358 - head/tools/sched
Jeff Roberson
jeff at FreeBSD.org
Fri Jan 16 23:24:25 PST 2009
Author: jeff
Date: Sat Jan 17 07:24:25 2009
New Revision: 187358
URL: http://svn.freebsd.org/changeset/base/187358
Log:
- Rewrite the parser to support the new generic schedgraph interface.
This no longer requires any custom classes or parsers to support new
event types.
- Add an optional command line argument for specifying the clock frequency
in ghz. This is useful for traces that do not include KTR_SCHED.
Sponsored by: Nokia
- Add support for sorting rows by clicking and dragging them to their new
position.
- Add support for configuring the cpu background colors.
- Improve the scaling so a better center is maintained as you zoom. This
is not perfect due to precision loss with floats used in the window
views.
- Add new colors and a random assignment for unknown event types. A table
is used for known event types. This is the only event specific
information.
Modified:
head/tools/sched/schedgraph.py
Modified: head/tools/sched/schedgraph.py
==============================================================================
--- head/tools/sched/schedgraph.py Sat Jan 17 07:17:57 2009 (r187357)
+++ head/tools/sched/schedgraph.py Sat Jan 17 07:24:25 2009 (r187358)
@@ -28,6 +28,7 @@
import sys
import re
+import random
from Tkinter import *
# To use:
@@ -53,30 +54,96 @@ from Tkinter import *
# while the workload is still running is to avoid wasting log entries on
# "idle" time at the end.
# - Dump the trace to a file: 'ktrdump -ct > ktr.out'
-# - Run the python script: 'python schedgraph.py ktr.out'
+# - Run the python script: 'python schedgraph.py ktr.out' optionally provide
+# your cpu frequency in ghz: 'python schedgraph.py ktr.out 2.4'
#
# To do:
-# 1) Add a per-thread summary display
-# 2) Add bounding box style zoom.
-# 3) Click to center.
-# 4) Implement some sorting mechanism.
-# 5) Widget to display variable-range data (e.g. q length)
-# 6) Reorder rows, hide rows, etc.
-# 7) "Vertical rule" to help relate data in different rows
-# 8) Mouse-over popup of full thread/event/row lable (currently truncated)
-# 9) More visible anchors for popup event windows
+# Add a per-source summary display
+# Click to move.
+# Hide rows
+# "Vertical rule" to help relate data in different rows
+# Mouse-over popup of full thread/event/row label (currently truncated)
+# More visible anchors for popup event windows
#
# BUGS: 1) Only 8 CPUs are supported, more CPUs require more choices of
# colours to represent them ;-)
-# 2) Extremely short traces may cause a crash because the code
-# assumes there is always at least one stathz entry logged, and
-# the number of such events is used as a denominator
+
+eventcolors = [
+ ("count", "red"),
+ ("running", "green"),
+ ("idle", "grey"),
+ ("yielding", "yellow"),
+ ("swapped", "violet"),
+ ("suspended", "purple"),
+ ("iwait", "grey"),
+ ("sleep", "blue"),
+ ("blocked", "dark red"),
+ ("runq add", "yellow"),
+ ("runq rem", "yellow"),
+ ("thread exit", "grey"),
+ ("proc exit", "grey"),
+ ("callwheel idle", "grey"),
+ ("callout running", "green"),
+ ("lock acquire", "blue"),
+ ("lock contest", "purple"),
+ ("failed lock try", "red"),
+ ("lock release", "grey"),
+ ("tick", "black"),
+ ("prio", "black"),
+ ("lend prio", "black"),
+ ("wokeup", "black")
+]
+
+cpucolors = [
+ ("CPU 0", "light grey"),
+ ("CPU 1", "dark grey"),
+ ("CPU 2", "light blue"),
+ ("CPU 3", "light pink"),
+ ("CPU 4", "blanched almond"),
+ ("CPU 5", "slate grey"),
+ ("CPU 6", "tan"),
+ ("CPU 7", "thistle"),
+ ("CPU 8", "white")
+]
+
+colors = [
+ "white", "thistle", "blanched almond", "tan", "chartreuse",
+ "dark red", "red", "pale violet red", "pink", "light pink",
+ "dark orange", "orange", "coral", "light coral",
+ "goldenrod", "gold", "yellow", "light yellow",
+ "dark green", "green", "light green", "light sea green",
+ "dark blue", "blue", "light blue", "steel blue", "light slate blue",
+ "dark violet", "violet", "purple", "blue violet",
+ "dark grey", "slate grey", "light grey",
+ "black",
+]
+colors.sort()
ticksps = None
status = None
-configtypes = []
+colormap = None
+ktrfile = None
+clockfreq = None
+sources = []
lineno = -1
+class Colormap:
+ def __init__(self, table):
+ self.table = table
+ self.map = {}
+ for entry in table:
+ self.map[entry[0]] = entry[1]
+
+ def lookup(self, name):
+ try:
+ color = self.map[name]
+ except:
+ color = colors[random.randrange(0, len(colors))]
+ print "Picking random color", color, "for", name
+ self.map[name] = color
+ self.table.append((name, color))
+ return (color)
+
def ticks2sec(ticks):
us = ticksps / 1000000
ticks /= us
@@ -124,9 +191,13 @@ class Status(Frame):
self.set(str)
root.update()
-class EventConf(Frame):
- def __init__(self, master, name, color, enabled):
+class ColorConf(Frame):
+ def __init__(self, master, name, color):
Frame.__init__(self, master)
+ if (graph.getstate(name) == "hidden"):
+ enabled = 0
+ else:
+ enabled = 1
self.name = name
self.color = StringVar()
self.color_default = color
@@ -144,16 +215,8 @@ class EventConf(Frame):
bg='grey')
self.rect = self.sample.create_rectangle(0, 0, 24, 24,
fill=self.color.get())
- self.list = OptionMenu(self, self.color,
- "dark red", "red", "pink",
- "dark orange", "orange",
- "yellow", "light yellow",
- "dark green", "green", "light green",
- "dark blue", "blue", "light blue",
- "dark violet", "violet", "purple",
- "dark grey", "light grey",
- "white", "black",
- command=self.setcolor)
+ self.list = OptionMenu(self, self.color, command=self.setcolor,
+ *colors)
self.checkbox = Checkbutton(self, text="enabled",
variable=self.enabled)
self.label.grid(row=0, column=0, sticky=E+W)
@@ -161,7 +224,7 @@ class EventConf(Frame):
self.list.grid(row=0, column=2, sticky=E+W)
self.checkbox.grid(row=0, column=3)
self.columnconfigure(0, weight=1)
- self.columnconfigure(2, minsize=110)
+ self.columnconfigure(2, minsize=150)
def setcolor(self, color):
self.color.set(color)
@@ -186,19 +249,15 @@ class EventConf(Frame):
graph.setcolor(self.name, self.color_current)
def revert(self):
- self.setcolor(self.color_current)
- self.enabled.set(self.enabled_current)
-
- def default(self):
self.setcolor(self.color_default)
self.enabled.set(self.enabled_default)
-class EventConfigure(Toplevel):
- def __init__(self):
+class ColorConfigure(Toplevel):
+ def __init__(self, table, name):
Toplevel.__init__(self)
self.resizable(0, 0)
- self.title("Event Configuration")
- self.items = LabelFrame(self, text="Event Type")
+ self.title(name)
+ self.items = LabelFrame(self, text="Item Type")
self.buttons = Frame(self)
self.drawbuttons()
self.items.grid(row=0, column=0, sticky=E+W)
@@ -206,11 +265,13 @@ class EventConfigure(Toplevel):
self.buttons.grid(row=1, column=0, sticky=E+W)
self.types = []
self.irow = 0
- for type in configtypes:
- self.additem(type.name, type.color, type.enabled)
+ for type in table:
+ color = graph.getcolor(type[0])
+ if (color != ""):
+ self.additem(type[0], color)
- def additem(self, name, color, enabled=1):
- item = EventConf(self.items, name, color, enabled)
+ def additem(self, name, color):
+ item = ColorConf(self.items, name, color)
self.types.append(item)
item.grid(row=self.irow, column=0, sticky=E+W)
self.irow += 1
@@ -218,16 +279,12 @@ class EventConfigure(Toplevel):
def drawbuttons(self):
self.apply = Button(self.buttons, text="Apply",
command=self.apress)
- self.revert = Button(self.buttons, text="Revert",
+ self.default = Button(self.buttons, text="Revert",
command=self.rpress)
- self.default = Button(self.buttons, text="Default",
- command=self.dpress)
self.apply.grid(row=0, column=0, sticky=E+W)
- self.revert.grid(row=0, column=1, sticky=E+W)
- self.default.grid(row=0, column=2, sticky=E+W)
+ self.default.grid(row=0, column=1, sticky=E+W)
self.buttons.columnconfigure(0, weight=1)
self.buttons.columnconfigure(1, weight=1)
- self.buttons.columnconfigure(2, weight=1)
def apress(self):
for item in self.types:
@@ -237,20 +294,16 @@ class EventConfigure(Toplevel):
for item in self.types:
item.revert()
- def dpress(self):
- for item in self.types:
- item.default()
-
class EventView(Toplevel):
def __init__(self, event, canvas):
Toplevel.__init__(self)
self.resizable(0, 0)
self.title("Event")
self.event = event
- self.frame = Frame(self)
- self.frame.grid(row=0, column=0, sticky=N+S+E+W)
self.buttons = Frame(self)
- self.buttons.grid(row=1, column=0, sticky=E+W)
+ self.buttons.grid(row=0, column=0, sticky=E+W)
+ self.frame = Frame(self)
+ self.frame.grid(row=1, column=0, sticky=N+S+E+W)
self.canvas = canvas
self.drawlabels()
self.drawbuttons()
@@ -272,9 +325,12 @@ class EventView(Toplevel):
ypos = 0
labels = self.event.labels()
while (len(labels) < 7):
- labels.append(("", "", 0))
+ labels.append(("", ""))
for label in labels:
- name, value, linked = label
+ name, value = label
+ linked = 0
+ if (name == "linkedto"):
+ linked = 1
l = Label(self.frame, text=name, bd=1, width=15,
relief=SUNKEN, anchor=W)
if (linked):
@@ -313,7 +369,7 @@ class EventView(Toplevel):
prev = self.event.prev()
if (prev == None):
return
- while (prev.real == 0):
+ while (prev.type == "pad"):
prev = prev.prev()
if (prev == None):
return
@@ -323,7 +379,7 @@ class EventView(Toplevel):
next = self.event.next()
if (next == None):
return
- while (next.real == 0):
+ while (next.type == "pad"):
next = next.next()
if (next == None):
return
@@ -335,60 +391,67 @@ class EventView(Toplevel):
self.newevent(event)
class Event:
- name = "none"
- color = "grey"
- def __init__(self, source, cpu, timestamp, last=0):
+ def __init__(self, source, name, cpu, timestamp, attrs):
self.source = source
+ self.name = name
self.cpu = cpu
self.timestamp = int(timestamp)
- self.entries = []
- self.real = 1
+ self.attrs = attrs
self.idx = None
- self.state = 0
self.item = None
self.dispcnt = 0
- self.linked = None
self.recno = lineno
- if (last):
- source.lastevent(self)
- else:
- source.event(self)
def status(self):
statstr = self.name + " " + self.source.name
statstr += " on: cpu" + str(self.cpu)
statstr += " at: " + str(self.timestamp)
- statstr += self.stattxt()
+ statstr += " attributes: "
+ for i in range(0, len(self.attrs)):
+ attr = self.attrs[i]
+ statstr += attr[0] + ": " + str(attr[1])
+ if (i != len(self.attrs) - 1):
+ statstr += ", "
status.set(statstr)
- def stattxt(self):
- return ""
-
- def textadd(self, tuple):
- pass
- self.entries.append(tuple)
-
def labels(self):
- return [("Source:", self.source.name, 0),
- ("Event:", self.name, 0),
- ("CPU:", self.cpu, 0),
- ("Timestamp:", self.timestamp, 0),
- ("Record: ", self.recno, 0)
- ] + self.entries
- def mouseenter(self, canvas, item):
+ return [("Source", self.source.name),
+ ("Event", self.name),
+ ("CPU", self.cpu),
+ ("Timestamp", self.timestamp),
+ ("KTR Line ", self.recno)
+ ] + self.attrs
+
+ def mouseenter(self, canvas):
self.displayref(canvas)
self.status()
- def mouseexit(self, canvas, item):
+ def mouseexit(self, canvas):
self.displayunref(canvas)
status.clear()
- def mousepress(self, canvas, item):
+ def mousepress(self, canvas):
EventView(self, canvas)
+ def draw(self, canvas, xpos, ypos, item):
+ self.item = item
+ if (item != None):
+ canvas.items[item] = self
+
+ def move(self, canvas, x, y):
+ if (self.item == None):
+ return;
+ canvas.move(self.item, x, y);
+
def next(self):
return self.source.eventat(self.idx + 1)
+ def nexttype(self, type):
+ next = self.next()
+ while (next != None and next.type != type):
+ next = next.next()
+ return (next)
+
def prev(self):
return self.source.eventat(self.idx - 1)
@@ -404,435 +467,106 @@ class Event:
canvas.tag_raise("point", "state")
def getlinked(self):
- return self.linked.findevent(self.timestamp)
+ for attr in self.attrs:
+ if (attr[0] != "linkedto"):
+ continue
+ source = ktrfile.findid(attr[1])
+ return source.findevent(self.timestamp)
+ return None
class PointEvent(Event):
- def __init__(self, thread, cpu, timestamp, last=0):
- Event.__init__(self, thread, cpu, timestamp, last)
+ type = "point"
+ def __init__(self, source, name, cpu, timestamp, attrs):
+ Event.__init__(self, source, name, cpu, timestamp, attrs)
def draw(self, canvas, xpos, ypos):
+ color = colormap.lookup(self.name)
l = canvas.create_oval(xpos - 6, ypos + 1, xpos + 6, ypos - 11,
- fill=self.color, tags=("all", "point", "event")
- + (self.name,), width=0)
- canvas.events[l] = self
- self.item = l
- if (self.enabled == 0):
- canvas.itemconfigure(l, state="hidden")
+ fill=color, tags=("all", "point", "event", self.name),
+ width=0)
+ Event.draw(self, canvas, xpos, ypos, l)
- return (xpos)
+ return xpos
class StateEvent(Event):
- def __init__(self, thread, cpu, timestamp, last=0):
- Event.__init__(self, thread, cpu, timestamp, last)
- self.duration = 0
- self.skipnext = 0
- self.skipself = 0
- self.state = 1
+ type = "state"
+ def __init__(self, source, name, cpu, timestamp, attrs):
+ Event.__init__(self, source, name, cpu, timestamp, attrs)
def draw(self, canvas, xpos, ypos):
- next = self.nextstate()
- if (self.skipself == 1 or next == None):
+ next = self.nexttype("state")
+ if (next == None):
return (xpos)
- while (self.skipnext):
- skipped = next
- next.skipself = 1
- next.real = 0
- next = next.nextstate()
- if (next == None):
- next = skipped
- self.skipnext -= 1
- self.duration = next.timestamp - self.timestamp
- if (self.duration < 0):
- self.duration = 0
+ duration = next.timestamp - self.timestamp
+ self.attrs.insert(0, ("duration", ticks2sec(duration)))
+ color = colormap.lookup(self.name)
+ if (duration < 0):
+ duration = 0
print "Unsynchronized timestamp"
print self.cpu, self.timestamp
print next.cpu, next.timestamp
- delta = self.duration / canvas.ratio
+ delta = duration / canvas.ratio
l = canvas.create_rectangle(xpos, ypos,
- xpos + delta, ypos - 10, fill=self.color, width=0,
- tags=("all", "state", "event") + (self.name,))
- canvas.events[l] = self
- self.item = l
- if (self.enabled == 0):
- canvas.itemconfigure(l, state="hidden")
+ xpos + delta, ypos - 10, fill=color, width=0,
+ tags=("all", "state", "event", self.name))
+ Event.draw(self, canvas, xpos, ypos, l)
return (xpos + delta)
- def stattxt(self):
- return " duration: " + ticks2sec(self.duration)
-
- def nextstate(self):
- next = self.next()
- while (next != None and next.state == 0):
- next = next.next()
- return (next)
-
- def labels(self):
- return [("Source:", self.source.name, 0),
- ("Event:", self.name, 0),
- ("Timestamp:", self.timestamp, 0),
- ("CPU:", self.cpu, 0),
- ("Record:", self.recno, 0),
- ("Duration:", ticks2sec(self.duration), 0)
- ] + self.entries
-
-class Count(Event):
- name = "Count"
- color = "red"
- enabled = 1
- def __init__(self, source, cpu, timestamp, count):
- self.count = int(count)
- Event.__init__(self, source, cpu, timestamp)
- self.duration = 0
- self.textadd(("count:", self.count, 0))
+class CountEvent(Event):
+ type = "count"
+ def __init__(self, source, count, cpu, timestamp, attrs):
+ count = int(count)
+ self.count = count
+ Event.__init__(self, source, "count", cpu, timestamp, attrs)
def draw(self, canvas, xpos, ypos):
- next = self.next()
- self.duration = next.timestamp - self.timestamp
- delta = self.duration / canvas.ratio
+ next = self.nexttype("count")
+ if (next == None):
+ return (xpos)
+ color = colormap.lookup("count")
+ duration = next.timestamp - self.timestamp
+ self.attrs.insert(0, ("count", self.count))
+ self.attrs.insert(1, ("duration", ticks2sec(duration)))
+ delta = duration / canvas.ratio
yhight = self.source.yscale() * self.count
l = canvas.create_rectangle(xpos, ypos - yhight,
- xpos + delta, ypos, fill=self.color, width=0,
- tags=("all", "count", "event") + (self.name,))
- canvas.events[l] = self
- self.item = l
- if (self.enabled == 0):
- canvas.itemconfigure(l, state="hidden")
+ xpos + delta, ypos, fill=color, width=0,
+ tags=("all", "count", "event", self.name))
+ Event.draw(self, canvas, xpos, ypos, l)
return (xpos + delta)
- def stattxt(self):
- return " count: " + str(self.count)
-
-configtypes.append(Count)
-
-class Running(StateEvent):
- name = "running"
- color = "green"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Running)
-
-class Idle(StateEvent):
- name = "idle"
- color = "grey"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Idle)
-
-class Yielding(StateEvent):
- name = "yielding"
- color = "yellow"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.skipnext = 0
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Yielding)
-
-class Swapped(StateEvent):
- name = "swapped"
- color = "violet"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Swapped)
-
-class Suspended(StateEvent):
- name = "suspended"
- color = "purple"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Suspended)
-
-class Iwait(StateEvent):
- name = "iwait"
- color = "grey"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Iwait)
-
-class Preempted(StateEvent):
- name = "preempted"
- color = "red"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio, bythread):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.skipnext = 1
- self.prio = prio
- self.linked = bythread
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("by thread:", self.linked.name, 1))
-
-configtypes.append(Preempted)
-
-class Sleep(StateEvent):
- name = "sleep"
- color = "blue"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio, wmesg):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.wmesg = wmesg
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("wmesg:", self.wmesg, 0))
-
- def stattxt(self):
- statstr = StateEvent.stattxt(self)
- statstr += " sleeping on: " + self.wmesg
- return (statstr)
-
-configtypes.append(Sleep)
-
-class Blocked(StateEvent):
- name = "blocked"
- color = "dark red"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio, lock):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.lock = lock
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("lock:", self.lock, 0))
-
- def stattxt(self):
- statstr = StateEvent.stattxt(self)
- statstr += " blocked on: " + self.lock
- return (statstr)
-
-configtypes.append(Blocked)
-
-class KsegrpRunq(StateEvent):
- name = "KsegrpRunq"
- color = "orange"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio, bythread):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.linked = bythread
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("by thread:", self.linked.name, 1))
-
-configtypes.append(KsegrpRunq)
-
-class Runq(StateEvent):
- name = "Runq"
- color = "yellow"
- enabled = 1
- def __init__(self, thread, cpu, timestamp, prio, bythread):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.linked = bythread
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("by thread:", self.linked.name, 1))
-
-configtypes.append(Runq)
-
-class Sched_exit_thread(StateEvent):
- name = "exit_thread"
- color = "grey"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.name = "sched_exit_thread"
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Sched_exit_thread)
-
-class Sched_exit(StateEvent):
- name = "exit"
- color = "grey"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio):
- StateEvent.__init__(self, thread, cpu, timestamp)
- self.name = "sched_exit"
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Sched_exit)
-
-# Events for running callout routines
-
-class CalloutIdle(StateEvent):
- name = "callwheel idle"
- color = "grey"
- enabled = 0
- def __init__(self, wheel, cpu, timestamp):
- StateEvent.__init__(self, wheel, cpu, timestamp)
-
-configtypes.append(CalloutIdle)
-
-class CalloutRunning(StateEvent):
- name = "callout running"
- color = "green"
- enabled = 1
- def __init__(self, wheel, cpu, timestamp, func, arg):
- StateEvent.__init__(self, wheel, cpu, timestamp)
- self.textadd(("function:", func, 0))
- self.textadd(("argument:", arg, 0))
- self.arg = arg
- self.func = func
-
- def stattxt(self):
- statstr = StateEvent.stattxt(self)
- statstr += " executing %s(%s)" % (self.func, self.arg)
- return (statstr)
-
-configtypes.append(CalloutRunning)
-
-# Events on locks
-#
-# XXX: No support for upgrade/downgrade currently or differentiating
-# between read/write in general.
-#
-# XXX: Point events for recursion perhaps?
-
-class LockAcquire(StateEvent):
- name = "lock acquire"
- color = "blue"
- enabled = 1
- def __init__(self, lock, cpu, timestamp, file, line):
- StateEvent.__init__(self, lock, cpu, timestamp)
- self.textadd(("file:", file, 0))
- self.textadd(("line:", line, 0))
-
-configtypes.append(LockAcquire)
-
-class LockContest(StateEvent):
- name = "lock contest"
- color = "purple"
- enabled = 1
- def __init__(self, lock, cpu, timestamp, file, line):
- StateEvent.__init__(self, lock, cpu, timestamp)
- self.textadd(("file:", file, 0))
- self.textadd(("line:", line, 0))
-
-configtypes.append(LockContest)
-
-class LockFailedTry(PointEvent):
- name = "failed lock try"
- color = "red"
- enabled = 1
- def __init__(self, lock, cpu, timestamp, file, line):
- PointEvent.__init__(self, lock, cpu, timestamp)
- self.textadd(("file:", file, 0))
- self.textadd(("line:", line, 0))
-
-configtypes.append(LockFailedTry)
-
-class LockRelease(StateEvent):
- name = "lock release"
- color = "grey"
- enabled = 0
- def __init__(self, lock, cpu, timestamp, file, line):
- StateEvent.__init__(self, lock, cpu, timestamp)
- self.textadd(("file:", file, 0))
- self.textadd(("line:", line, 0))
-
-configtypes.append(LockRelease)
-
-class Padevent(StateEvent):
- def __init__(self, thread, cpu, timestamp, last=0):
- StateEvent.__init__(self, thread, cpu, timestamp, last)
- self.name = "pad"
- self.real = 0
-
+class PadEvent(StateEvent):
+ type = "pad"
+ def __init__(self, source, cpu, timestamp, last=0):
+ if (last):
+ cpu = source.events[len(source.events) -1].cpu
+ else:
+ cpu = source.events[0].cpu
+ StateEvent.__init__(self, source, "pad", cpu, timestamp, [])
def draw(self, canvas, xpos, ypos):
next = self.next()
if (next == None):
return (xpos)
- self.duration = next.timestamp - self.timestamp
- delta = self.duration / canvas.ratio
+ duration = next.timestamp - self.timestamp
+ delta = duration / canvas.ratio
+ Event.draw(self, canvas, xpos, ypos, None)
return (xpos + delta)
-class Tick(PointEvent):
- name = "tick"
- color = "black"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio, stathz):
- PointEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.textadd(("prio:", self.prio, 0))
-
-configtypes.append(Tick)
-
-class Prio(PointEvent):
- name = "prio"
- color = "black"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio, newprio, bythread):
- PointEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.newprio = newprio
- self.linked = bythread
- self.textadd(("new prio:", self.newprio, 0))
- self.textadd(("prio:", self.prio, 0))
- if (self.linked != self.source):
- self.textadd(("by thread:", self.linked.name, 1))
- else:
- self.textadd(("by thread:", self.linked.name, 0))
-
-configtypes.append(Prio)
-
-class Lend(PointEvent):
- name = "lend"
- color = "black"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, prio, tothread):
- PointEvent.__init__(self, thread, cpu, timestamp)
- self.prio = prio
- self.linked = tothread
- self.textadd(("prio:", self.prio, 0))
- self.textadd(("to thread:", self.linked.name, 1))
-
-configtypes.append(Lend)
-
-class Wokeup(PointEvent):
- name = "wokeup"
- color = "black"
- enabled = 0
- def __init__(self, thread, cpu, timestamp, ranthread):
- PointEvent.__init__(self, thread, cpu, timestamp)
- self.linked = ranthread
- self.textadd(("ran thread:", self.linked.name, 1))
-
-configtypes.append(Wokeup)
-
-(DEFAULT, LOAD, COUNT, CALLWHEEL, LOCK, THREAD) = range(6)
-
class EventSource:
- def __init__(self, name, group=DEFAULT, order=0):
- self.name = name
+ def __init__(self, group, id):
+ self.name = id
self.events = []
- self.cpu = 0
- self.cpux = 0
+ self.cpuitems = []
self.group = group
- self.order = order
+ self.y = 0
+ self.item = None
def __cmp__(self, other):
+ if (other == None):
+ return -1
if (self.group == other.group):
- return cmp(self.order, other.order)
+ return cmp(self.name, other.name)
return cmp(self.group, other.group)
# It is much faster to append items to a list then to insert them
@@ -841,60 +575,54 @@ class EventSource:
def fixup(self):
self.events.reverse()
- def event(self, event):
+ def addevent(self, event):
self.events.append(event)
- def remove(self, event):
- self.events.remove(event)
-
- def lastevent(self, event):
+ def addlastevent(self, event):
self.events.insert(0, event)
def draw(self, canvas, ypos):
xpos = 10
- self.cpux = 10
- self.cpu = self.events[1].cpu
+ cpux = 10
+ cpu = self.events[1].cpu
for i in range(0, len(self.events)):
self.events[i].idx = i
for event in self.events:
- if (event.cpu != self.cpu and event.cpu != -1):
- self.drawcpu(canvas, xpos, ypos)
- self.cpux = xpos
- self.cpu = event.cpu
+ if (event.cpu != cpu and event.cpu != -1):
+ self.drawcpu(canvas, cpu, cpux, xpos, ypos)
+ cpux = xpos
+ cpu = event.cpu
xpos = event.draw(canvas, xpos, ypos)
- self.drawcpu(canvas, xpos, ypos)
+ self.drawcpu(canvas, cpu, cpux, xpos, ypos)
def drawname(self, canvas, ypos):
+ self.y = ypos
ypos = ypos - (self.ysize() / 2)
- canvas.create_text(10, ypos, anchor="w", text=self.name)
+ self.item = canvas.create_text(10, ypos, anchor="w", text=self.name)
+ return (self.item)
- def drawcpu(self, canvas, xpos, ypos):
- cpu = int(self.cpu)
- if (cpu == 0):
- color = 'light grey'
- elif (cpu == 1):
- color = 'dark grey'
- elif (cpu == 2):
- color = 'light blue'
- elif (cpu == 3):
- color = 'light green'
- elif (cpu == 4):
- color = 'blanched almond'
- elif (cpu == 5):
- color = 'slate grey'
- elif (cpu == 6):
- color = 'light slate blue'
- elif (cpu == 7):
- color = 'thistle'
- else:
- color = "white"
- l = canvas.create_rectangle(self.cpux,
+ def drawcpu(self, canvas, cpu, fromx, tox, ypos):
+ cpu = "CPU " + str(cpu)
+ color = cpucolormap.lookup(cpu)
+ # Create the cpu background colors default to hidden
+ l = canvas.create_rectangle(fromx,
ypos - self.ysize() - canvas.bdheight,
- xpos, ypos + canvas.bdheight, fill=color, width=0,
- tags=("all", "cpuinfo"))
+ tox, ypos + canvas.bdheight, fill=color, width=0,
+ tags=("all", "cpuinfo", cpu), state="hidden")
+ self.cpuitems.append(l)
+
+ def move(self, canvas, xpos, ypos):
+ for event in self.events:
+ event.move(canvas, xpos, ypos)
+ for item in self.cpuitems:
+ canvas.move(item, xpos, ypos)
+
+ def movename(self, canvas, xpos, ypos):
+ self.y += ypos
+ canvas.move(self.item, xpos, ypos)
def ysize(self):
- return (None)
+ return (10)
def eventat(self, i):
if (i >= len(self.events)):
@@ -904,93 +632,45 @@ class EventSource:
def findevent(self, timestamp):
for event in self.events:
- if (event.timestamp >= timestamp and event.real):
+ if (event.timestamp >= timestamp and event.type != "pad"):
return (event)
return (None)
-class Thread(EventSource):
- names = {}
- def __init__(self, td, pcomm):
- EventSource.__init__(self, pcomm, THREAD)
- self.str = td
+class Counter(EventSource):
+ #
+ # Store a hash of counter groups that keeps the max value
+ # for a counter in this group for scaling purposes.
+ #
+ groups = {}
+ def __init__(self, group, id):
try:
- cnt = Thread.names[pcomm]
+ Counter.cnt = Counter.groups[group]
except:
- Thread.names[pcomm] = 0
- return
- Thread.names[pcomm] = cnt + 1
-
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list