Author: jhb
Date: Tue Jan 13 16:33:10 2009
New Revision: 187155
URL: http://svn.freebsd.org/changeset/base/187155

Log:
  - Add some rudimentary support for sorting the list of event sources
    (threads, CPU load counters, etc.).  Each source is tagged with a group
    and an order similar to the SYSINIT SI_SUB_* and SI_ORDER_*.  After
    the file is parsed, all the sources are then sorted.  Currently, the only
    affects of this are that the CPU loads are now sorted by CPU ID (so
    CPU 0 is always first).  However, this makes it easier to add new types
    of event sources in the future and have them all clustered together
    instead of intertwined with threads.
  - Python lists perform insertions at the tail much faster than insertions
    at the head.  For a trace that had a lot of events for a single event
    source, the constant insertions of new events to the head of the
    per-source event list caused a noticable slow down.  To compensate,
    append new events to the end of the list during parsing and then
    reverse the list prior to drawing.
  - Somewhere in the tkinter internals the coordinates of a canvas are
    stored in a signed 32-bit integer.  As a result, if an the box for
    an event spans 2^31, it would actually end up having a negative
    X offset at one end.  The result was a single box that covered the
    entire event source.  Kris worked around this for some traces by
    bumping up the initial ticks/pixel ratio from 1 to 10.  However, a
    divisor of 10 can still be too small for large tracefiles (e.g.
    with 4 million entries).  Instead of hardcoding the initial scaling
    ratio, calculate it from the time span of the trace file.
  - Add support for using the mouse wheel to scroll the graph window
    up and down.

Modified:
  head/tools/sched/schedgraph.py

Modified: head/tools/sched/schedgraph.py
==============================================================================
--- head/tools/sched/schedgraph.py      Tue Jan 13 16:27:04 2009        
(r187154)
+++ head/tools/sched/schedgraph.py      Tue Jan 13 16:33:10 2009        
(r187155)
@@ -739,24 +739,36 @@ class Wokeup(PointEvent):
 
 configtypes.append(Wokeup)
 
+(DEFAULT, LOAD, COUNT, THREAD) = range(4)
+
 class EventSource:
-       def __init__(self, name):
+       def __init__(self, name, group=DEFAULT, order=0):
                self.name = name
                self.events = []
                self.cpu = 0
                self.cpux = 0
+               self.group = group
+               self.order = order
 
+       def __cmp__(self, other):
+               if (self.group == other.group):
+                       return cmp(self.order, other.order)
+               return cmp(self.group, other.group)
+
+       # It is much faster to append items to a list then to insert them
+       # at the beginning.  As a result, we add events in reverse order
+       # and then swap the list during fixup.
        def fixup(self):
-               pass
+               self.events.reverse()
 
        def event(self, event):
-               self.events.insert(0, event)
+               self.events.append(event)
 
        def remove(self, event):
                self.events.remove(event)
 
        def lastevent(self, event):
-               self.events.append(event)
+               self.events.insert(0, event)
 
        def draw(self, canvas, ypos):
                xpos = 10
@@ -819,7 +831,7 @@ class EventSource:
 class Thread(EventSource):
        names = {}
        def __init__(self, td, pcomm):
-               EventSource.__init__(self, pcomm)
+               EventSource.__init__(self, pcomm, THREAD)
                self.str = td
                try:
                        cnt = Thread.names[pcomm]
@@ -829,6 +841,7 @@ class Thread(EventSource):
                Thread.names[pcomm] = cnt + 1
 
        def fixup(self):
+               EventSource.fixup(self)
                cnt = Thread.names[self.name]
                if (cnt == 0):
                        return
@@ -842,7 +855,7 @@ class Thread(EventSource):
 class Counter(EventSource):
        max = 0
        def __init__(self, name):
-               EventSource.__init__(self, name)
+               EventSource.__init__(self, name, COUNT)
 
        def event(self, event):
                EventSource.event(self, event)
@@ -863,6 +876,11 @@ class Counter(EventSource):
        def yscale(self):
                return (self.ysize() / Counter.max)
 
+class CPULoad(Counter):
+       def __init__(self, cpu):
+               Counter.__init__(self, "cpu" + str(cpu) + " load")
+               self.group = LOAD
+               self.order = cpu
 
 class KTRFile:
        def __init__(self, file):
@@ -1100,9 +1118,9 @@ class KTRFile:
                try:
                        load = self.load[cpu]
                except:
-                       load = Counter("cpu" + str(cpu) + " load")
+                       load = CPULoad(cpu)
                        self.load[cpu] = load
-                       self.sources.insert(0, load)
+                       self.sources.append(load)
                Count(load, cpu, timestamp, count)
 
        def cpuload2(self, cpu, timestamp, ncpu, count):
@@ -1113,9 +1131,9 @@ class KTRFile:
                try:
                        load = self.load[cpu]
                except:
-                       load = Counter("cpu" + str(cpu) + " load")
+                       load = CPULoad(cpu)
                        self.load[cpu] = load
-                       self.sources.insert(0, load)
+                       self.sources.append(load)
                Count(load, cpu, timestamp, count)
 
        def loadglobal(self, cpu, timestamp, count):
@@ -1128,7 +1146,7 @@ class KTRFile:
                except:
                        load = Counter("CPU load")
                        self.load[cpu] = load
-                       self.sources.insert(0, load)
+                       self.sources.append(load)
                Count(load, cpu, timestamp, count)
 
        def critsec(self, cpu, timestamp, td, pcomm, to):
@@ -1141,7 +1159,7 @@ class KTRFile:
                except:
                        crit = Counter("Critical Section")
                        self.crit[cpu] = crit
-                       self.sources.insert(0, crit)
+                       self.sources.append(crit)
                Count(crit, cpu, timestamp, to)
 
        def findtd(self, td, pcomm):
@@ -1158,12 +1176,14 @@ class KTRFile:
                        Padevent(source, -1, self.timestamp_l)
                        Padevent(source, -1, self.timestamp_f, last=1)
                        source.fixup()
+               self.sources.sort()
 
 class SchedDisplay(Canvas):
        def __init__(self, master):
-               self.ratio = 10
+               self.ratio = 1
                self.ktrfile = None
                self.sources = None
+               self.parent = master
                self.bdheight = 10 
                self.events = {}
 
@@ -1174,6 +1194,11 @@ class SchedDisplay(Canvas):
                self.ktrfile = ktrfile
                self.sources = ktrfile.sources
 
+               # Compute a ratio to ensure that the file's timespan fits into
+               # 2^31.  Although python may handle larger values for X
+               # values, the Tk internals do not.
+               self.ratio = (ktrfile.timespan() - 1) / 2**31 + 1
+
        def draw(self):
                ypos = 0
                xsize = self.xsize()
@@ -1195,6 +1220,8 @@ class SchedDisplay(Canvas):
                self.tag_bind("event", "<Enter>", self.mouseenter)
                self.tag_bind("event", "<Leave>", self.mouseexit)
                self.tag_bind("event", "<Button-1>", self.mousepress)
+               self.bind("<Button-4>", self.wheelup)
+               self.bind("<Button-5>", self.wheeldown)
 
        def mouseenter(self, event):
                item, = self.find_withtag(CURRENT)
@@ -1211,6 +1238,12 @@ class SchedDisplay(Canvas):
                event = self.events[item]
                event.mousepress(self, item)
 
+       def wheeldown(self, event):
+               self.parent.display_yview("scroll", 1, "units")
+
+       def wheelup(self, event):
+               self.parent.display_yview("scroll", -1, "units")
+
        def drawnames(self, canvas):
                status.startup("Drawing names")
                ypos = 0
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to