From owner-svn-src-all@FreeBSD.ORG Tue Jan 13 16:33:10 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 956AE106566B; Tue, 13 Jan 2009 16:33:10 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 81E108FC1A; Tue, 13 Jan 2009 16:33:10 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0DGXAjw008677; Tue, 13 Jan 2009 16:33:10 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0DGXAo6008675; Tue, 13 Jan 2009 16:33:10 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200901131633.n0DGXAo6008675@svn.freebsd.org> From: John Baldwin Date: Tue, 13 Jan 2009 16:33:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187155 - head/tools/sched X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Jan 2009 16:33:11 -0000 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", "", self.mouseenter) self.tag_bind("event", "", self.mouseexit) self.tag_bind("event", "", self.mousepress) + self.bind("", self.wheelup) + self.bind("", 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