#!/usr/bin/env python
#
#  Copyright 2009 University Of Southern California
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing,
#  software distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

"""Parses the output of pprof and produces summary memory statistics."""

__author__ = "Gideon Juve <juve@usc.edu>"
__all__ = []
__version__ = "1.0"

import sys, os, re
from stats import Variable
from analysis import Analysis, sorteditems

class Event:
	def __init__(self,op,time,rec):
		self.op = op
		self.time = time
		self.rec = rec

class Executable:
	def __init__(self,xform,name):
		self.xform = xform
		self.name = name
		self.vmpeak = Variable()
		self.rsspeak = Variable()

class Transformation:
	def __init__(self,name):
		self.name = name
		self.vmpeak = Variable()
		self.rsspeak = Variable()

class MemAnalysis(Analysis):
	def __init__(self):
		self.exes = {}
		self.xforms = {}
		self.file_re = re.compile("\.err(\.[0-9]{3})?$")

	def print_stats(self):
		print ",,vmpeak,,,,,,rsspeak"
		print "transformation,executable,count,min,max,avg,stddev,sum,count,min,max,avg,stddev,sum"
		for exe in sorteditems(self.exes):
			print "%s,%s,%s,%s" % (exe.xform,exe.name,exe.vmpeak,exe.rsspeak)

		print "\n"

		print ",vmpeak,,,,,,rsspeak"
		print "transformation,count,min,max,avg,stddev,sum,count,min,max,avg,stddev,sum"
		for xform in sorteditems(self.xforms):
			print "%s,%s,%s" % (xform.name,xform.vmpeak,xform.rsspeak)

	def is_datafile(self, file):
		return self.file_re.search(file) is not None

	def process_datafile(self, file):
		f = open(file, 'r')
		line = f.readline()
		while line:
			if 'xform' in line:
				self.process_invocation(f)
			line = f.readline()
		f.close()

	def process_invocation(self, file):
		events = {}

		# Read lines
		line = file.readline()
		while line:
			# Skip lines
			if 'xform' in line:
				file.seek(len(line) * -1, os.SEEK_CUR)
				break
			if 'WARNING' in line:
				line = file.readline()
				continue
			if 'PTRACE_' in line:
				line = file.readline()
				continue

			#xform pid ppid exe lstart lstop tstart tstop vmpeak rsspeak utime stime wtime cutime cstime
			tok = line.split(' ')
			if len(tok) != 15:
				continue

			xfn = tok[0]
			exn = os.path.basename(tok[3])
			start = int(tok[4])
			stop = int(tok[5])
			vmpeak = float(tok[8])/1024
			rsspeak = float(tok[9])/1024

			if xfn in events:
				tline = events[xfn]
			else:
				tline = []
				events[xfn] = tline

			if xfn in self.xforms:
				xform = self.xforms[xfn]
			else:
				xform = Transformation(xfn)
				self.xforms[xfn] = xform

			id = xfn+"$"+exn
			if id in self.exes:
				exe = self.exes[id]
			else:
				exe = Executable(xfn,exn)
				self.exes[id] = exe

			tline.append(Event('add',start,(vmpeak,rsspeak)))
			tline.append(Event('sub',stop,(vmpeak,rsspeak)))
		
			exe.vmpeak.update(vmpeak)
			exe.rsspeak.update(rsspeak)

			line = file.readline()

		# Process events for each xform
		for xfn in events:
			tline = events[xfn]
			tline.sort(lambda x,y: x.time - y.time)
			vmpeak = 0
			rsspeak = 0
			maxpeak = 0
			maxhwm = 0
			for event in tline:
				if event.op == 'add':
					vmpeak = vmpeak + event.rec[0]
					rsspeak = rsspeak + event.rec[1]
				elif event.op == 'sub':
					vmpeak = vmpeak - event.rec[0]
					rsspeak = rsspeak - event.rec[1]
				maxpeak = max(maxpeak, vmpeak)
				maxhwm = max(maxhwm, rsspeak)
			xform = self.xforms[xfn]
			xform.vmpeak.update(maxpeak)
			xform.rsspeak.update(maxhwm)


if __name__ == '__main__':
	MemAnalysis().analyze()
