Beispiel #1
0
    def fillHistos(self, monComp):

        from App import DataSetMgr
        self.msg.debug("filling histograms...")

        # short-hands

        # milliseconds
        ms = Units.ms

        dsNames = DataSetMgr.names()
        yMinRead = []
        yMaxRead = []
        yMinWrite = []
        yMaxWrite = []
        for dsName in dsNames:
            if dsName not in monComp.data:
                continue
            data = monComp.data[dsName]
            if 'evt' not in data:
                continue
            data['evt']['io/cpu/rr'] = data['evt']['io/user/rr'] \
                                     + data['evt']['io/sys/rr' ]
            data['evt']['io/cpu/r'] = data['evt']['io/user/r'] \
                                    + data['evt']['io/sys/r' ]
            yMinRead += [data['evt']['io/cpu/r'][self.minEvt:].min() * ms]
            yMaxRead += [data['evt']['io/cpu/r'][self.minEvt:].max() * ms]

            data['evt']['io/cpu/w'] = data['evt']['io/user/w'] \
                                    + data['evt']['io/sys/w' ]
            yMinWrite += [data['evt']['io/cpu/w'][self.minEvt:].min() * ms]
            yMaxWrite += [data['evt']['io/cpu/w'][self.minEvt:].max() * ms]
        yMinRead = min(yMinRead)
        yMaxRead = max(yMaxRead)
        yMinWrite = min(yMinWrite)
        yMaxWrite = max(yMaxWrite)

        for dsName in dsNames:
            if dsName not in monComp.data:
                continue
            data = monComp.data[dsName]
            if 'evt' not in data:
                continue
            bins = DataSetMgr.instances[dsName].bins
            if 'evt/io' not in monComp.figs:
                monComp.figs['evt/io'] = pylab.figure()
                monComp.figs['evt/io'].add_subplot(221).hold(True)
                monComp.figs['evt/io'].add_subplot(223).hold(True)
                monComp.figs['evt/io'].add_subplot(222).hold(True)
                monComp.figs['evt/io'].add_subplot(224).hold(True)

            ## read
            fig = monComp.figs['evt/io']
            ax = fig.axes[0]
            _iy = self.minEvt + len(bins[self.minEvt:])
            pl = ax.plot(bins[self.minEvt:],
                         data['evt']['io/cpu/r'][self.minEvt:_iy] * ms,
                         linestyle='steps',
                         label=dsName)

            ax.grid(True)
            ax.set_title("[%s]" % monComp.name)
            ax.set_ylabel('(R) CPU time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h, b = numpy.histogram(data['evt']['io/cpu/r'][self.minEvt:] * ms +
                                   data['evt']['io/cpu/r'][self.minEvt:] * ms,
                                   bins=20,
                                   range=(yMinRead * 0.90, yMaxRead * 1.10))
            ax = fig.axes[1]
            ax.plot(b, h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('(R) CPU time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            ## write
            fig = monComp.figs['evt/io']
            ax = fig.axes[2]
            _iy = self.minEvt + len(bins[self.minEvt:])
            pl = ax.plot(bins[self.minEvt:],
                         data['evt']['io/cpu/w'][self.minEvt:_iy] * ms,
                         linestyle='steps',
                         label=dsName)
            ax.grid(True)
            ax.set_title("[%s]" % monComp.name)
            ax.set_ylabel('(W) CPU time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h, b = numpy.histogram(data['evt']['io/cpu/w'][self.minEvt:] * ms +
                                   data['evt']['io/cpu/w'][self.minEvt:] * ms,
                                   bins=20,
                                   range=(yMinWrite * 0.90, yMaxWrite * 1.10))
            ax = fig.axes[3]
            ax.plot(b, h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('(W) CPU time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            ## read
            h = data['histos']['io_r_%s' % dsName]
            hAvg = bookAvgHist(h, data['evt']['io/cpu/r'] * ms)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                cpuTime = data['evt']['io/cpu/r'][i] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            ## write
            h = data['histos']['io_w_%s' % dsName]
            hAvg = bookAvgHist(h, data['evt']['io/cpu/w'] * ms)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                cpuTime = data['evt']['io/cpu/w'][i] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            pass  # loop over datasets

        for ax in monComp.figs['evt/io'].axes:
            ax.legend(DataSetMgr.labels(), loc='best')

        ################################################
        # ROOT T/P separation overhead
        #
        for dsName in dsNames:
            if dsName not in monComp.data:
                continue
            data = monComp.data[dsName]
            if 'evt' not in data:
                continue
            bins = DataSetMgr.instances[dsName].bins
            if 'evt/rio' not in monComp.figs:
                monComp.figs['evt/rio'] = pylab.figure()
                monComp.figs['evt/rio'].add_subplot(221).hold(True)
                monComp.figs['evt/rio'].add_subplot(223).hold(True)
                monComp.figs['evt/rio'].add_subplot(222).hold(True)
                monComp.figs['evt/rio'].add_subplot(224).hold(True)

            ## read
            fig = monComp.figs['evt/rio']
            ax = fig.axes[0]
            _iy = self.minEvt + len(bins[self.minEvt:])
            pl = ax.plot(bins[self.minEvt:],
                         data['evt']['io/cpu/rr'][self.minEvt:_iy] * ms,
                         linestyle='steps',
                         label=dsName)
            ax.set_title("[%s]" % monComp.name)
            ax.set_ylabel('(RR) CPU time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h, b = numpy.histogram(
                data['evt']['io/cpu/rr'][self.minEvt:] * ms +
                data['evt']['io/cpu/rr'][self.minEvt:] * ms,
                bins=20,
                range=(yMinRead * 0.90, yMaxRead * 1.10))
            ax = fig.axes[1]
            ax.plot(b, h, label=dsName, ls='steps')
            ax.set_xlabel('(RR) CPU time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            _iy = self.minEvt + len(bins[self.minEvt:])
            ratios = []
            for idx, num in enumerate(
                    data['evt']['io/cpu/rr'][self.minEvt:_iy]):
                den = data['evt']['io/cpu/r'][idx]
                if den == 0.: r = 0
                else: r = num / den * 100.
                ratios.append(r)
##                 print "%3i %8.3f %8.3f %8.3f" % (idx,num,den,r)

            ratios = numpy.array(ratios)
            yMinRatio = min(ratios)
            yMaxRatio = max(ratios)

            ## pure ROOT read over T/P read
            fig = monComp.figs['evt/rio']
            ax = fig.axes[2]
            pl = ax.plot(bins[self.minEvt:],
                         ratios,
                         linestyle='steps',
                         label=dsName)
            ax.set_title("[%s]" % monComp.name)
            ax.set_ylabel('Pure-ROOT over Full read CPU time (%)')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h, b = numpy.histogram(ratios + ratios,
                                   bins=20,
                                   range=(yMinRatio * 0.90, yMaxRatio * 1.10))
            ax = fig.axes[3]
            ax.plot(b, h, label=dsName, ls='steps')
            ax.set_xlabel('Pure-ROOT over Full read CPU time (%)')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            ## read
            h = data['histos']['io_rr_%s' % dsName]
            hAvg = bookAvgHist(h, data['evt']['io/cpu/rr'] * ms)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                cpuTime = data['evt']['io/cpu/rr'][i] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            pass  # loop over datasets

        for ax in monComp.figs['evt/io'].axes:
            ax.legend(DataSetMgr.labels(), loc='best')

        self.msg.debug("filling histograms... [DONE]")
        return
Beispiel #2
0
    def fillHistos(self, monComp):
        
        from App import DataSetMgr
        self.msg.debug("filling histograms...")

        # short-hands
        msg = self.msg
        
        # convert page-size into MB
        Mb =  Units.Mb
        # convert page-size into kB
        kb =  Units.kb

        monName = monComp.name
        dsNames = DataSetMgr.names()
        ymin = {'vmem':[], 'malloc':[]}
        ymax = {'vmem':[], 'malloc':[]}
        allGood = True
        
        for dsName in dsNames:
            if not dsName in monComp.data:
                continue
            #print "---",dsName,monComp.name
            data = monComp.data[dsName]
            if not 'evt' in data:
                continue
            data = data['evt']
            if data is None:
                ## print "---",dsName,monComp.name,"data['evt'] is None"
                continue

            if not 'mem' in data.dtype.names:
                allGood = False
                msg.debug('component [%s] has empty mem infos for '
                          'dataset [%s]',
                          monComp.name,
                          dsName)
                ## print "--->",dsName,monComp.name,data.dtype.names
                continue

            ## print "+++",dsName,monComp.name
            mem = data['mem']
            dvmem = mem['vmem'][:,2]
            ymin['vmem'].append(dvmem[self.minEvt:].min()*kb)
            ymax['vmem'].append(dvmem[self.minEvt:].max()*kb)

            dmall = mem['mall'][:,2]
            ymin['malloc'].append(dmall[self.minEvt:].min()*kb)
            ymax['malloc'].append(dmall[self.minEvt:].max()*kb)
            pass

        if not allGood:
            msg.debug("Something bad happened for component [%s] "
                      "during 'MemAnalyzer.fillHistos' !!",
                      monComp.name)
            return

        if len(ymin['vmem']) == 0 and len(ymax['vmem']) == 0:
            self.msg.debug("Component [%s] has no 'evt' level data",
                           monComp.name)
            return
        
        for k in ymin.keys():
            ymin[k] = min(ymin[k])
            ymax[k] = max(ymax[k])
            pass

        
        for dsName in dsNames:
            if not dsName in monComp.data:
                continue
            data = monComp.data[dsName]
            if not 'evt' in data:
                continue
            data = data['evt']
            if data is None:
                continue
            
            if not 'mem' in data.dtype.names:
                continue

            bins = DataSetMgr.instances[dsName].bins
            if not 'evt/mem' in monComp.figs:
                monComp.figs['evt/mem'] = plt.figure()
                monComp.figs['evt/mem'].add_subplot(221).hold( True )
                monComp.figs['evt/mem'].add_subplot(222).hold( True )
                monComp.figs['evt/mem'].add_subplot(223).hold( True )
                monComp.figs['evt/mem'].add_subplot(224).hold( True )

            fig = monComp.figs['evt/mem']
            mem = data['mem']
            dvmem = mem['vmem'][:,2]
            dmall = mem['mall'][:,2]
            
            ## VMem
            ax = fig.axes[0]
            binMax = len(dvmem[self.minEvt:len(bins)])
            pl = ax.plot(bins[self.minEvt:binMax],
                         dvmem[self.minEvt:binMax] * kb,
                         linestyle = 'steps',
                         label     = dsName)
            ax.grid(True)
            ax.set_title ('Delta V-Mem\n[%s]' % monComp.name)
            ax.set_ylabel('Delta V-Mem [kb]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0]*0.9,
                         ax.get_ylim()[1]*1.1))
            
            h,b = numpy.histogram(
                dvmem[self.minEvt:binMax] * kb,
                bins  = 20,
                range = (ymin['vmem']*0.90, ymax['vmem']*1.10)
                )

            ax = fig.axes[2]
            ax.plot(b[:-1], h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('Delta V-Mem [kb]')
            ax.set_ylim((ax.get_ylim()[0]*0.9, ### ???
                         ax.get_ylim()[1]*1.1))

            ## Malloc
            ax = fig.axes[1]
            pl = ax.plot(bins[self.minEvt:binMax],
                         dmall[self.minEvt:binMax] * kb,
                         linestyle = 'steps',
                         label     = dsName)
            ax.grid(True)
            ax.set_title ('Delta Malloc\n[%s]' % monComp.name)
            ax.set_ylabel('Delta Malloc [kb]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0]*0.9,
                         ax.get_ylim()[1]*1.1))
            
            h,b = numpy.histogram(
                dmall[self.minEvt:binMax] * kb,
                bins  = 20,
                range = (ymin['malloc']*0.90, ymax['malloc']*1.10)
                )

            ax = fig.axes[3]
            ax.plot(b[:-1], h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('Delta Malloc [kb]')
            ax.set_ylim( (ax.get_ylim()[0]*0.9,
                          ax.get_ylim()[1]*1.1) )

            ## ROOT-histos
            data = monComp.data[dsName]
            hVmem    = data['histos']['mem_%s' % dsName]
            hAvgVmem = bookAvgHist(hVmem, dvmem * kb)
            data['histos'][hVmem.GetName()] = hAvgVmem
            hMall    = data['histos']['malloc_%s' % dsName]
            hAvgMall = bookAvgHist(hMall, dmall * kb)
            data['histos'][hMall.GetName()] = hAvgMall
            maxRange = min(len(dvmem), len(bins))

            for i in range(maxRange):
                dVmem = dvmem[i] * kb
                hVmem.Fill( float(bins[i]), dVmem )
                hAvgVmem.Fill( dVmem )
                dMall = dmall[i] * kb
                hMall.Fill( float(bins[i]), dMall )
                hAvgMall.Fill( dVmem )
            pass # loop over datasets

        for ax in monComp.figs['evt/mem'].axes:
            ax.legend(DataSetMgr.labels(), loc='best')

        self.msg.debug( "filling histograms... [DONE]" )
        return
    def processEvt(self, dataSetMgr, monCompMgr):
        from App import DataSetMgr

        from PyRootLib import importRoot
        ROOT = importRoot(batch=True)

        ## RootFct = ROOT.TF1
        ## dummyCanvas = ROOT.TCanvas("dummyFitCanvas")
        ## import PyRootLib as prl

        ## self.sum['evt']['histos'] = []
        ## self.sum['evt']['fig']    = []

        ## short-hand
        ms = Units.ms
        kb = Units.kb
        Mb = Units.Mb
        Mb2Kb = 1000.
        msg = self.msg

        ## get top-20 consumers
        dsNames = DataSetMgr.names()
        color = DataSetMgr.colorIter()

        _txt = self.txt['evt']

        monComp = monCompMgr['PerfMonSlice']
        yMinCpu = []
        yMaxCpu = []
        yMinIo = []
        yMaxIo = []
        for dsName in dsNames:
            data = monComp.data[dsName]
            histos = data['histos'] = {}
            if not 'evt' in data:
                continue
            data = data['evt']
            if data is None:
                continue
            cpu = data['cpu']
            cpu_u = cpu['user']
            cpu_s = cpu['sys']
            cpu_r = cpu['real']
            cpu_c = cpu['cpu']

            dcpu_u = cpu_u[:, 2]
            dcpu_s = cpu_s[:, 2]
            dcpu_r = cpu_r[:, 2]
            dcpu_c = cpu_c[:, 2]

            mem = data['mem']
            vmem = mem['vmem']
            dvmem = vmem[:, 2]
            rss = mem['rss']
            drss = rss[:, 2]
            mall = mem['mall']
            dmall = mall[:, 2]

            nallocs = mem['nmall'][:, 2]
            nfrees = mem['nfree'][:, 2]

            yMinCpu.append(dcpu_c[self.minEvt:].min() * ms)
            yMaxCpu.append(dcpu_c[self.minEvt:].max() * ms)

            io = monComp.data[dsName]['io']
            io_c = io['w']['cpu']
            yMinIo.append(io_c[self.minEvt:].min() * ms)
            yMaxIo.append(io_c[self.minEvt:].max() * ms)

            ##             data['mem/vmem/d'] = data['mem/vmem/1'] - data['mem/vmem/0']
            ##             data['mem/rss/d' ] = data['mem/rss/1' ] - data['mem/rss/0' ]

            ## fill-in some data for ASCII summary
            if dsName == '000':
                _txt['cpu']['slice'] += [
                    "%-20s %10.3f %10.3f %10.3f ms" % (
                        "[u/s/r]",
                        dcpu_u[self.minEvt:].mean() * ms,
                        dcpu_s[self.minEvt:].mean() * ms,
                        dcpu_r[self.minEvt:].mean() * ms,
                    ),
                ]
                _txt['mem']['slice'] += [
                    "%-20s %10.3f %10.3f %10.3f kB" % (
                        "[dVmem/dRss/dMalloc]",
                        dvmem[self.minEvt:].mean() * kb,
                        drss[self.minEvt:].mean() * kb,
                        dmall[self.minEvt:].mean() * kb,
                    ),
                ]
                _txt['allocs']['slice'] += [
                    "%-20s %10i %10i" % (
                        "[nallocs/nfrees]",
                        nallocs[self.minEvt:].mean(),
                        nfrees[self.minEvt:].mean(),
                    ),
                ]

            ## book ROOT histos
            nEntries = len(dataSetMgr[dsName].bins) - 1
            minEvt = dataSetMgr[dsName].bins[self.minEvt]
            maxEvt = dataSetMgr[dsName].bins[-1]

            hId = 'cpu_%s.%s' % (monComp.name, dsName)
            hName = 'cpu_%s' % dsName
            histos[hName] = ROOT.TH1F(
                hId, "[%s] CPU usage [%s];%s;%s" %
                (monComp.name, dsName, "event nbr", "Timing [ms]"), nEntries,
                minEvt, maxEvt)

            hId = 'vmem_%s.%s' % (monComp.name, dsName)
            hName = 'vmem_%s' % dsName
            histos[hName] = ROOT.TH1F(
                hId, "[%s] VMem usage [%s];%s;%s" %
                (monComp.name, dsName, "event nbr", "V-Mem [MB]"), nEntries,
                minEvt, maxEvt)

            hId = 'rss_%s.%s' % (monComp.name, dsName)
            hName = 'rss_%s' % dsName
            histos[hName] = ROOT.TH1F(
                hId, "[%s] RSS usage [%s];%s;%s" %
                (monComp.name, dsName, "event nbr", "RSS [MB]"), nEntries,
                minEvt, maxEvt)

            hId = 'io_%s.%s' % (monComp.name, dsName)
            hName = 'io_%s' % dsName
            histos[hName] = ROOT.TH1F(
                hId, "[%s] I/O time [%s];%s;%s" %
                (monComp.name, dsName, "event nbr", "I/O time [ms]"), nEntries,
                minEvt, maxEvt)
            pass

        yMinIo = min(yMinIo)
        yMaxIo = max(yMaxIo)
        yMinCpu = min(yMinCpu)
        yMaxCpu = max(yMaxCpu)

        def markForLegend(p):
            setattr(p, '_markedForLegend', True)

        def isMarked(p):
            return hasattr(p, '_markedForLegend')

        memLeak = []
        for dsName in dsNames:

            if not 'evt' in monComp.data[dsName]:
                continue

            data = monComp.data[dsName]

            cpu = data['evt']['cpu']
            cpu_c = cpu['cpu']
            dcpu_c = cpu_c[:, 2]

            ## CPU
            bins = dataSetMgr[dsName].bins
            xbins = bins[self.minEvt:]
            if not 'evt/cpu' in monComp.figs:
                monComp.figs['evt/cpu'] = plt.figure()
                monComp.figs['evt/cpu'].add_subplot(211).hold(True)
                monComp.figs['evt/cpu'].add_subplot(212).hold(True)
            fig = monComp.figs['evt/cpu']
            ax = fig.axes[0]
            pl = ax.plot(xbins,
                         dcpu_c[self.minEvt:] * ms,
                         linestyle='steps',
                         label=dsName)
            ax.grid(True)
            ax.set_title("CPU time [Begin/End-Event]")
            ax.set_ylabel('CPU time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0] * 0.9, ax.get_ylim()[1] * 1.1))
            markForLegend(pl[0])

            h, b = numpy.histogram(dcpu_c[self.minEvt:] * ms,
                                   bins=20,
                                   range=(yMinCpu * 0.90, yMaxCpu * 1.10))
            ax = fig.axes[1]
            pl = ax.plot(b[:-1], h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('CPU time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))
            markForLegend(pl[0])

            h = data['histos']['cpu_%s' % dsName]
            hAvg = bookAvgHist(h, dcpu_c * ms)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                cpuTime = dcpu_c[i] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            ## Mem
            mem = data['evt']['mem']
            vmem = mem['vmem']
            dvmem = vmem[:, 2]
            dmall = mem['mall'][:, 2]

            if not 'evt/mem' in monComp.figs:
                monComp.figs['evt/mem'] = plt.figure()
                monComp.figs['evt/mem'].add_subplot(311).hold(True)
                monComp.figs['evt/mem'].add_subplot(312).hold(True)
                monComp.figs['evt/mem'].add_subplot(313).hold(True)

            fig = monComp.figs['evt/mem']
            ax = fig.axes[0]
            pl = ax.plot(
                xbins,
                vmem[self.minEvt:, 1] * Mb,
                linestyle='steps',
                #'o',
                label=dsName)
            ax.set_title("Memory usage [Begin/End-Event]")
            ax.set_ylabel('VMem [MB]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0] * 0.9, ax.get_ylim()[1] * 1.1))
            ax.grid(True)
            markForLegend(pl[0])

            ## fit
            #nFit = int(len(bins)/2.)
            #x = bins[-nFit:]
            #y = data['evt']['mem/vmem/1'][-nFit:] * Mb
            begFit = self._fitSlice[0]
            endFit = self._fitSlice[1]
            x = bins[begFit:endFit]
            y = vmem[begFit:endFit, 1] * Mb
            coeffs = numpy.lib.polyfit(x, y, deg=1)
            memLeak += [coeffs[0] * kb]
            ax.plot(x, numpy.lib.polyval(coeffs, x), '-', color='y', lw=2.)
            if dsName == '000':
                _txt['mem']['slice'] += [
                    "%-20s p[0] = %8.3f MB \tp[1] = %8.3f kB" % (
                        "vmem fit:",
                        coeffs[1] * Mb,
                        coeffs[0] * kb,  #
                    )
                ]

            ax = fig.axes[1]
            pl = ax.plot(xbins,
                         mem['rss'][self.minEvt:, 1] * Mb,
                         linestyle='steps',
                         label=dsName)
            ax.set_ylabel('RSS [MB]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0] * 0.9, ax.get_ylim()[1] * 1.1))
            ax.grid(True)
            markForLegend(pl[0])

            ax = fig.axes[2]
            pl = ax.plot(xbins,
                         dmall[self.minEvt:] * Mb,
                         linestyle='steps',
                         label=dsName)
            ax.set_ylabel('Delta Malloc [MB]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0] * 0.9, ax.get_ylim()[1] * 1.1))
            ax.grid(True)
            markForLegend(pl[0])

            h = data['histos']['vmem_%s' % dsName]
            hAvg = bookAvgHist(h, mem['vmem'][:, 1] * Mb)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                vmem = mem['vmem'][i, 1] * Mb
                h.Fill(float(bins[i]), vmem)
                hAvg.Fill(vmem)

            h = data['histos']['rss_%s' % dsName]
            hAvg = bookAvgHist(h, mem['rss'][:, 1] * Mb)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                rss = mem['rss'][i, 1] * Mb
                h.Fill(float(bins[i]), rss)
                hAvg.Fill(rss)

            ## I/O
            if not 'evt/io' in monComp.figs:
                monComp.figs['evt/io'] = plt.figure()
                monComp.figs['evt/io'].add_subplot(211).hold(True)
                monComp.figs['evt/io'].add_subplot(212).hold(True)
            fig = monComp.figs['evt/io']
            ax = fig.axes[0]
            io_c = data['io']['w']['cpu']
            pl = ax.plot(xbins,
                         io_c[self.minEvt:] * ms,
                         linestyle='steps',
                         label=dsName)
            ax.set_title("I/O time [CommitOutput]")
            ax.set_ylabel('I/O time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))
            ax.grid(True)
            markForLegend(pl[0])

            yMinIo *= 0.9
            yMaxIo *= 1.1
            yMinIo, yMaxIo = min(yMinIo, yMaxIo), max(yMinIo, yMaxIo)
            h, b = numpy.histogram(io_c[self.minEvt:] * ms,
                                   bins=20,
                                   range=(yMinIo, yMaxIo))
            ax = fig.axes[1]
            pl = ax.plot(b[:-1], h, label=dsName, ls='steps')
            ax.set_xlabel('I/O time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))
            ax.grid(True)
            markForLegend(pl[0])

            h = data['histos']['io_%s' % dsName]
            hAvg = bookAvgHist(h, io_c * ms)
            data['histos'][h.GetName()] = hAvg
            for i in range(len(bins)):
                cpuTime = io_c[i] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            pass  # loop over data sets

        ## handle mem-leak text
        ax = monComp.figs['evt/mem'].axes[0]
        ax.text(
            0.025,
            0.97,
            "\n".join("[%s] Leak: %8.3f kB" % (n, leak)
                      for n, leak in zip(DataSetMgr.labels(), memLeak)),
            bbox=dict(facecolor='w'),
            #color = '',
            fontweight='bold',
            #fontsize   = 'x-larger',
            verticalalignment='top',
            transform=ax.transAxes)
        for figName, fig in monComp.figs.items():
            loc = 'best'
            if figName == 'evt/mem': loc = 'lower right'
            for ax in fig.axes:
                objs = [l for l in ax.lines if isMarked(l)]
                ax.legend(
                    objs,
                    DataSetMgr.labels(),
                    #loc='lower right'
                    #loc='best'
                    loc=loc)

        ## get top-20 consumers
        self._top_consumers(dataSetMgr,
                            monCompMgr,
                            compTypes=('alg', ),
                            title='Event loop',
                            storeName='evt',
                            sliceName='evt',
                            begSlice=self.minEvt,
                            endSlice=None)
        return
    def fillHistos(self, monComp):

        from App import DataSetMgr
        self.msg.debug("filling histograms...")

        # short-hands
        msg = self.msg

        # milliseconds
        ms = Units.ms

        monName = monComp.name
        dsNames = DataSetMgr.names()
        yMin = []
        yMax = []
        allGood = True

        figs = monComp.figs

        for dsName in dsNames:
            if not monComp.data.has_key(dsName):
                continue
            data = monComp.data[dsName]
            ## print "..",dsName,data.keys()
            if not 'evt' in data:
                continue
            data = data['evt']
            if data is None:
                continue

            ## print "..",dsName,data.keys()

            if not 'cpu' in data.dtype.names:
                allGood = False
                msg.debug(
                    'component [%s] has empty cpu/user infos for '
                    'dataset [%s]', monComp.name, dsName)
                continue
            cpu = data['cpu']['cpu']
            yMin.append(cpu[self.minEvt:, 2].min() * ms)
            yMax.append(cpu[self.minEvt:, 2].max() * ms)

        if not allGood:
            msg.debug(
                "Something bad happened for component [%s] "
                "during 'CpuAnalyzer.fillHistos' !!", monComp.name)
            return

        if len(yMin) == 0 and len(yMax) == 0:
            msg.debug("Component [%s] has no 'evt' level data", monComp.name)
            return

        yMin = min(yMin)
        yMax = max(yMax)

        for dsName in dsNames:
            if not monComp.data.has_key(dsName):
                continue
            data = monComp.data[dsName]
            if not 'evt' in data:
                continue
            bins = DataSetMgr.instances[dsName].bins
            if not 'evt/cpu' in monComp.figs:
                monComp.figs['evt/cpu'] = plt.figure()
                monComp.figs['evt/cpu'].add_subplot(211).hold(True)
                monComp.figs['evt/cpu'].add_subplot(212).hold(True)
            fig = monComp.figs['evt/cpu']
            ax = fig.axes[0]
            cpu = data['evt']['cpu']
            cpu_c = cpu['cpu']
            cpu_u = cpu['user']
            cpu_s = cpu['sys']

            binMax = len(cpu_c[self.minEvt:len(bins)])
            pl = ax.plot(bins[self.minEvt:binMax],
                         cpu_c[self.minEvt:binMax, 2] * ms,
                         linestyle='steps',
                         label=dsName)
            ax.grid(True)
            ax.set_title("CPU time [%s]" % monComp.name)
            ax.set_ylabel('CPU time [ms]')
            ax.set_xlabel('Event number')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h, b = numpy.histogram(cpu_c[self.minEvt:binMax, 2] * ms,
                                   bins=20,
                                   range=(yMin * 0.90, yMax * 1.10))
            ax = fig.axes[1]
            ax.plot(b[:-1], h, label=dsName, ls='steps')
            ax.grid(True)
            ax.set_xlabel('CPU time [ms]')
            ax.set_ylim((ax.get_ylim()[0], ax.get_ylim()[1] * 1.1))

            h = data['histos']['cpu_%s' % dsName]
            hAvg = bookAvgHist(h, cpu_c[:, 2] * ms)
            data['histos'][h.GetName()] = hAvg
            maxRange = min(len(cpu_c), len(bins))

            for i in range(maxRange):
                cpuTime = cpu_c[i, 2] * ms
                h.Fill(float(bins[i]), cpuTime)
                hAvg.Fill(cpuTime)

            pass  # loop over datasets

        for ax in monComp.figs['evt/cpu'].axes:
            ax.legend(DataSetMgr.labels(dsNames), loc='best')

        self.msg.debug("filling histograms... [DONE]")
        return