@@ -2114,173 +2114,6 @@ def parse_call(self):
21142114 return function
21152115
21162116
2117- class OprofileParser (LineParser ):
2118- """Parser for oprofile callgraph output.
2119-
2120- See also:
2121- - http://oprofile.sourceforge.net/doc/opreport.html#opreport-callgraph
2122- """
2123-
2124- _fields_re = {
2125- 'samples' : r'(\d+)' ,
2126- '%' : r'(\S+)' ,
2127- 'linenr info' : r'(?P<source>\(no location information\)|\S+:\d+)' ,
2128- 'image name' : r'(?P<image>\S+(?:\s\(tgid:[^)]*\))?)' ,
2129- 'app name' : r'(?P<application>\S+)' ,
2130- 'symbol name' : r'(?P<symbol>\(no symbols\)|.+?)' ,
2131- }
2132-
2133- def __init__ (self , infile ):
2134- LineParser .__init__ (self , infile )
2135- self .entries = {}
2136- self .entry_re = None
2137-
2138- def add_entry (self , callers , function , callees ):
2139- try :
2140- entry = self .entries [function .id ]
2141- except KeyError :
2142- self .entries [function .id ] = (callers , function , callees )
2143- else :
2144- callers_total , function_total , callees_total = entry
2145- self .update_subentries_dict (callers_total , callers )
2146- function_total .samples += function .samples
2147- self .update_subentries_dict (callees_total , callees )
2148-
2149- def update_subentries_dict (self , totals , partials ):
2150- for partial in partials .values ():
2151- try :
2152- total = totals [partial .id ]
2153- except KeyError :
2154- totals [partial .id ] = partial
2155- else :
2156- total .samples += partial .samples
2157-
2158- def parse (self ):
2159- # read lookahead
2160- self .readline ()
2161-
2162- self .parse_header ()
2163- while self .lookahead ():
2164- self .parse_entry ()
2165-
2166- profile = Profile ()
2167-
2168- reverse_call_samples = {}
2169-
2170- # populate the profile
2171- profile [SAMPLES ] = 0
2172- for _callers , _function , _callees in self .entries .values ():
2173- function = Function (_function .id , _function .name )
2174- function [SAMPLES ] = _function .samples
2175- profile .add_function (function )
2176- profile [SAMPLES ] += _function .samples
2177-
2178- if _function .application :
2179- function .process = os .path .basename (_function .application )
2180- if _function .image :
2181- function .module = os .path .basename (_function .image )
2182-
2183- total_callee_samples = 0
2184- for _callee in _callees .values ():
2185- total_callee_samples += _callee .samples
2186-
2187- for _callee in _callees .values ():
2188- if not _callee .self :
2189- call = Call (_callee .id )
2190- call [SAMPLES2 ] = _callee .samples
2191- function .add_call (call )
2192-
2193- # compute derived data
2194- profile .validate ()
2195- profile .find_cycles ()
2196- profile .ratio (TIME_RATIO , SAMPLES )
2197- profile .call_ratios (SAMPLES2 )
2198- profile .integrate (TOTAL_TIME_RATIO , TIME_RATIO )
2199-
2200- return profile
2201-
2202- def parse_header (self ):
2203- while not self .match_header ():
2204- self .consume ()
2205- line = self .lookahead ()
2206- fields = re .split (r'\s\s+' , line )
2207- entry_re = r'^\s*' + r'\s+' .join ([self ._fields_re [field ] for field in fields ]) + r'(?P<self>\s+\[self\])?$'
2208- self .entry_re = re .compile (entry_re )
2209- self .skip_separator ()
2210-
2211- def parse_entry (self ):
2212- callers = self .parse_subentries ()
2213- if self .match_primary ():
2214- function = self .parse_subentry ()
2215- if function is not None :
2216- callees = self .parse_subentries ()
2217- self .add_entry (callers , function , callees )
2218- self .skip_separator ()
2219-
2220- def parse_subentries (self ):
2221- subentries = {}
2222- while self .match_secondary ():
2223- subentry = self .parse_subentry ()
2224- subentries [subentry .id ] = subentry
2225- return subentries
2226-
2227- def parse_subentry (self ):
2228- entry = Struct ()
2229- line = self .consume ()
2230- mo = self .entry_re .match (line )
2231- if not mo :
2232- raise ParseError ('failed to parse' , line )
2233- fields = mo .groupdict ()
2234- entry .samples = int (mo .group (1 ))
2235- if 'source' in fields and fields ['source' ] != '(no location information)' :
2236- source = fields ['source' ]
2237- filename , lineno = source .split (':' )
2238- entry .filename = filename
2239- entry .lineno = int (lineno )
2240- else :
2241- source = ''
2242- entry .filename = None
2243- entry .lineno = None
2244- entry .image = fields .get ('image' , '' )
2245- entry .application = fields .get ('application' , '' )
2246- if 'symbol' in fields and fields ['symbol' ] != '(no symbols)' :
2247- entry .symbol = fields ['symbol' ]
2248- else :
2249- entry .symbol = ''
2250- if entry .symbol .startswith ('"' ) and entry .symbol .endswith ('"' ):
2251- entry .symbol = entry .symbol [1 :- 1 ]
2252- entry .id = ':' .join ((entry .application , entry .image , source , entry .symbol ))
2253- entry .self = fields .get ('self' , None ) != None
2254- if entry .self :
2255- entry .id += ':self'
2256- if entry .symbol :
2257- entry .name = entry .symbol
2258- else :
2259- entry .name = entry .image
2260- return entry
2261-
2262- def skip_separator (self ):
2263- while not self .match_separator ():
2264- self .consume ()
2265- self .consume ()
2266-
2267- def match_header (self ):
2268- line = self .lookahead ()
2269- return line .startswith ('samples' )
2270-
2271- def match_separator (self ):
2272- line = self .lookahead ()
2273- return line == '-' * len (line )
2274-
2275- def match_primary (self ):
2276- line = self .lookahead ()
2277- return not line [:1 ].isspace ()
2278-
2279- def match_secondary (self ):
2280- line = self .lookahead ()
2281- return line [:1 ].isspace ()
2282-
2283-
22842117class HProfParser (LineParser ):
22852118 """Parser for java hprof output
22862119
@@ -3035,7 +2868,6 @@ def _make_function(self, call):
30352868 "collapse" : CollapseParser ,
30362869 "hprof" : HProfParser ,
30372870 "json" : JsonParser ,
3038- "oprofile" : OprofileParser ,
30392871 "perf" : PerfParser ,
30402872 "prof" : GprofParser ,
30412873 "pstats" : PstatsParser ,
0 commit comments