def report(self, reportName=None, benchmarkPaths=None, classifier=DefaultClassifier(), txnFilter=None, reportThreshold=3000, resultOrder=ResultOrder.WorstToBest): """ Ends active profile session and generates reports. This method executes the following steps 1. Ends samples collection and disconnects tcp connection to target 2. Gathers sample files for the current profile session and loads elapsed time and pmu counters 3. Groups related counters to build transactions and timelines 4. Generates html report and stores results :param reportName: Name of the profile report (Default value = None) :type reportName: str :param benchmarkPaths: List of stored reports from previous runs, for benchmarking (Default value = None) :param classifier: Predicate to classify transactions into different categories (Default value = DefaultClassifier() :type classifier: xpedite.txn.classifier.ProbeDataClassifier :param txnFilter: Lambda to filter transactions prior to report generation :type txnFilter: callable accepting a txn instance and returns a bool :param reportThreshold: Threshold for number of transactions rendered in html reports (Default value = 3000) :type reportThreshold: int :param resultOrder: Default sort order of transactions in latency constituent reports :type resultOrder: xpedite.pmu.ResultOrder """ from xpedite.profiler.reportgenerator import ReportGenerator from xpedite.txn.repo import TxnRepoFactory from xpedite.pmu.event import Event try: if not self.app.dryRun: try: self.app.endProfile() except Exception as ex: LOGGER.warn('Detected unclean profile termination - %s', ex) if self.eventSet: self.app.disablePMU() repoFactory = TxnRepoFactory() pmc = [ Event(req.name, req.uarchName) for req in self.eventSet.requests() ] if self.eventSet else [] repo = repoFactory.buildTxnRepo(self.app, self.cpuInfo, self.probes, self.topdownCache, self.topdownMetrics, pmc, self.benchmarkProbes, benchmarkPaths) reportName = reportName if reportName else self.app.name reportGenerator = ReportGenerator(reportName) return reportGenerator.generateReport(self.app, repo, classifier, resultOrder, reportThreshold, txnFilter, benchmarkPaths) except Exception as ex: LOGGER.exception('failed to generate report') raise ex
def groupElapsedTime(txnSubCollection, cpuInfo, classifier=DefaultClassifier()): """ Aggregates elapsed time by category This method computes elapsed wall time for each transaction in the subcollection and aggregates computed duration by its soruce transaction's category :param txnSubCollection: Transaction subcollection to be aggregated :param classifier: Predicate to classify transactions into different categories :param cpuInfo: Cpu info to convert cycles to duration (micro seconds) """ elapsedTscGroup = {} for txn in txnSubCollection: if txn: time = cpuInfo.convertCyclesToTime(txn.getElapsedTsc()) TxnAggregator._addOrUpdateContainer(elapsedTscGroup, lambda v: [v], classifier, txn, time) return elapsedTscGroup
def groupTxns(txnSubCollection, classifier=DefaultClassifier(), mustHaveProbes=None): """ Aggregates transactions by their resepective categories :param txnSubCollection: Transaction subcollection to be aggregated :param classifier: Predicate to classify transactions into different categories :param mustHaveProbes: Probes used to exclude transaction from aggregation """ groupMap = {} # classifiy the counter breakups into categories for txn in txnSubCollection: if not mustHaveProbes or txn.hasProbes(mustHaveProbes): TxnAggregator._addOrUpdateContainer( groupMap, lambda t: txnSubCollectionFactory(txnSubCollection, t), classifier, txn, txn ) return groupMap
def groupElapsedTscByScope(txnSubCollection, beginProbe, endProbe, classifier=DefaultClassifier()): """ Aggregates elapsed tsc values by category :param txnSubCollection: Transaction subcollection to be aggregated :param beginProbe: Begin probe used for elapsed tsc computation :param endProbe: End probe used for elapsed tsc computation :param classifier: Predicate to classify transactions into different categories """ elapsedTscGroup = {} for txn in txnSubCollection: if txn.hasProbes([beginProbe, endProbe]): beginCounter = txn.getCounterForProbe(beginProbe) endCounter = txn.getCounterForProbe(endProbe) TxnAggregator._addOrUpdateContainer( elapsedTscGroup, lambda v: [v], classifier, txn, endCounter.tsc - beginCounter.tsc ) return elapsedTscGroup
def profile(app, profileInfo, reportName, reportPath, dryRun, # pylint: disable=too-many-locals heartbeatInterval=120, samplesFileSize=None, interactive=True, duration=None, cprofile=None): """ Orchestrates a Xpedite profile session The method starts a profile session by instantiating a xpedite runtime. The runtime is kept alive till one of the following conditions are met 1. The user ends the interactive session by a key press 2. The total duration for the session elapses 3. The connection to the profiling target gets closed or disconnected Reports and benchmarks are generated at the end of the session :param app: An instance of xpedite app, to interact with target application :param profileInfo: Parameters and settings for the profile session :type profileInfo: xpedite.profileInfo.ProfileInfo :param reportName: Name of the profile report :type reportName: str :param reportPath: Path to persist profile data for benchmarking :type reportPath: str :param dryRun: Flag to enable simulation of profiling target :type dryRun: bool :param heartbeatInterval: Heartbeat interval for profiler's tcp connection :type heartbeatInterval: int :param samplesFileSize: Max size of data files used to store samples :type samplesFileSize: int :param interactive: Flag to enable, an interactive profiling session (Default value = True) :type interactive: bool :param duration: Profile duration - The session is automatically terminated after elapse of duration seconds (Default value = None) :type duration: int :param cprofile: Handle to capture self profile Xpedite report generation code (Default value = None) :type cprofile: C{xpedite.selfProfile.CProfile} """ import time import select from xpedite.profiler.runtime import Runtime from xpedite.txn.classifier import DefaultClassifier runtime = Runtime( app=app, probes=profileInfo.probes, pmc=profileInfo.pmc, cpuSet=profileInfo.cpuSet, pollInterval=1, samplesFileSize=samplesFileSize, ) if not dryRun: begin = time.time() elapsed = 0 duration = int(duration) if duration is not None else None if interactive: LOGGER.info('press RETURN key to, end live profile and generate report ...') while True: timeout = min(heartbeatInterval, duration - elapsed) if duration is not None else heartbeatInterval eof = False if interactive: rlist, _, _ = select.select([sys.stdin], [], [], timeout) eof = sys.stdin in rlist else: time.sleep(timeout) elapsed = time.time() - begin LOGGER.debug('profile active - elapsed %d / %s seconds | EOF %s', int(elapsed), duration, eof) if eof or (duration and elapsed >= duration): break try: app.ping(keepAlive=True) except Exception: break classifier = profileInfo.classifier if profileInfo.classifier else DefaultClassifier() if cprofile: cprofile.enable() report = runtime.report(reportName=reportName, benchmarkPaths=profileInfo.benchmarkPaths , classifier=classifier, resultOrder=profileInfo.resultOrder, txnFilter=profileInfo.txnFilter) if reportPath: report.makeBenchmark(reportPath) return report