Home | History | Annotate | Download | only in linux_perf
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 'use strict';
      6 
      7 /**
      8  * @fileoverview Parses vmscan events in the Linux event trace format.
      9  */
     10 base.require('tracing.importer.linux_perf.parser');
     11 base.exportTo('tracing.importer.linux_perf', function() {
     12 
     13   var Parser = tracing.importer.linux_perf.Parser;
     14 
     15   /**
     16    * Parses linux vmscan trace events.
     17    * @constructor
     18    */
     19   function MemReclaimParser(importer) {
     20     Parser.call(this, importer);
     21 
     22     importer.registerEventHandler('mm_vmscan_kswapd_wake',
     23         MemReclaimParser.prototype.kswapdWake.bind(this));
     24     importer.registerEventHandler('mm_vmscan_kswapd_sleep',
     25         MemReclaimParser.prototype.kswapdSleep.bind(this));
     26     importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',
     27         MemReclaimParser.prototype.reclaimBegin.bind(this));
     28     importer.registerEventHandler('mm_vmscan_direct_reclaim_end',
     29         MemReclaimParser.prototype.reclaimEnd.bind(this));
     30   }
     31 
     32   // Matches the mm_vmscan_kswapd_wake record
     33   //  mm_vmscan_kswapd_wake: nid=%d order=%d
     34   var kswapdWakeRE = /nid=(\d+) order=(\d+)/;
     35 
     36   // Matches the mm_vmscan_kswapd_sleep record
     37   //  mm_vmscan_kswapd_sleep: order=%d
     38   var kswapdSleepRE = /nid=(\d+)/;
     39 
     40   // Matches the mm_vmscan_direct_reclaim_begin record
     41   //  mm_vmscan_direct_reclaim_begin: order=%d may_writepage=%d gfp_flags=%s
     42   var reclaimBeginRE = /order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;
     43 
     44   // Matches the mm_vmscan_direct_reclaim_end record
     45   //  mm_vmscan_direct_reclaim_end: nr_reclaimed=%lu
     46   var reclaimEndRE = /nr_reclaimed=(\d+)/;
     47 
     48   MemReclaimParser.prototype = {
     49     __proto__: Parser.prototype,
     50 
     51     openAsyncSlice: function(ts, category, threadName, pid, key, name) {
     52       var kthread = this.importer.getOrCreateKernelThread(
     53           category + ':' + threadName, pid);
     54       var slice = new tracing.trace_model.AsyncSlice(
     55           category, name, tracing.getStringColorId(name), ts);
     56       slice.startThread = kthread.thread;
     57 
     58       if (!kthread.openAsyncSlices) {
     59         kthread.openAsyncSlices = { };
     60       }
     61       kthread.openAsyncSlices[key] = slice;
     62     },
     63 
     64     closeAsyncSlice: function(ts, category, threadName, pid, key, args) {
     65       var kthread = this.importer.getOrCreateKernelThread(
     66           category + ':' + threadName, pid);
     67       if (kthread.openAsyncSlices) {
     68         var slice = kthread.openAsyncSlices[key];
     69         if (slice) {
     70           slice.duration = ts - slice.start;
     71           slice.args = args;
     72           slice.endThread = kthread.thread;
     73           slice.subSlices = [
     74             new tracing.trace_model.Slice(category, slice.title,
     75                 slice.colorId, slice.start, slice.args, slice.duration)
     76           ];
     77           kthread.thread.asyncSliceGroup.push(slice);
     78           delete kthread.openAsyncSlices[key];
     79         }
     80       }
     81     },
     82 
     83     /**
     84      * Parses memreclaim events and sets up state in the importer.
     85      */
     86     kswapdWake: function(eventName, cpuNumber, pid, ts, eventBase) {
     87       var event = kswapdWakeRE.exec(eventBase.details);
     88       if (!event)
     89         return false;
     90 
     91       var nid = parseInt(event[1])
     92       var order = parseInt(event[2])
     93 
     94       var kthread = this.importer.getOrCreateKernelThread("kswapd: " + eventBase.threadName,
     95           pid, pid);
     96       if (kthread.openSliceTS) {
     97         if (order > kthread.order) {
     98           kthread.order = order;
     99         }
    100       } else {
    101         kthread.openSliceTS = ts;
    102         kthread.order = order;
    103       }
    104       return true;
    105     },
    106 
    107     kswapdSleep: function(eventName, cpuNumber, pid, ts, eventBase) {
    108       var kthread = this.importer.getOrCreateKernelThread("kswapd: " + eventBase.threadName,
    109           pid, pid);
    110       if (kthread.openSliceTS) {
    111         var slice = new tracing.trace_model.Slice('', eventBase.threadName,
    112             tracing.getStringColorId(eventBase.threadName),
    113             kthread.openSliceTS,
    114             {
    115                 order: kthread.order,
    116             },
    117             ts - kthread.openSliceTS);
    118 
    119         kthread.thread.sliceGroup.pushSlice(slice);
    120       }
    121       kthread.openSliceTS = undefined;
    122       kthread.order = undefined;
    123       return true;
    124     },
    125 
    126     reclaimBegin: function(eventName, cpuNumber, pid, ts, eventBase) {
    127       var event = reclaimBeginRE.exec(eventBase.details);
    128       if (!event)
    129         return false;
    130       
    131       var order = parseInt(event[1]);
    132       var gfp = event[2]
    133 
    134       var kthread = this.importer.getOrCreateKernelThread("direct reclaim: " + eventBase.threadName,
    135           pid, pid);
    136       kthread.openSliceTS = ts;
    137       kthread.order = order;
    138       kthread.gfp = gfp;
    139       return true;
    140     },
    141 
    142     reclaimEnd: function(eventName, cpuNumber, pid, ts, eventBase) {
    143       var event = reclaimEndRE.exec(eventBase.details);
    144       if (!event)
    145         return false;
    146       
    147       var nr_reclaimed = parseInt(event[1]);
    148 
    149       var kthread = this.importer.getOrCreateKernelThread("direct reclaim: " + eventBase.threadName,
    150           pid, pid);
    151       if (kthread.openSliceTS !== undefined) {
    152         var slice = new tracing.trace_model.Slice(
    153             "", "direct reclaim",
    154             tracing.getStringColorId(eventBase.threadName),
    155             kthread.openSliceTS,
    156             { 
    157                 order: kthread.order,
    158                 gfp: kthread.gfp,
    159                 nr_reclaimed: nr_reclaimed,
    160             },
    161             ts - kthread.openSliceTS);
    162         kthread.thread.sliceGroup.pushSlice(slice);
    163       }
    164       kthread.openSliceTS = undefined;
    165       kthread.order = undefined;
    166       kthread.gfp = undefined;
    167       return true;
    168     }
    169 
    170   };
    171 
    172   Parser.registerSubtype(MemReclaimParser);
    173 
    174   return {
    175     MemReclaimParser: MemReclaimParser
    176   };
    177 });
    178