PQ6VRQEBZKSTOCA5PT4XK2YNAFETM6RRHKEQH2ZHU6OCDZODLPWQC function ProFi:start( param )if param == 'once' thenif self:shouldReturn() thenreturnelseself.should_run_once = trueendendself.has_started = trueself.has_finished = falseself:resetReports( self.reports )self:startHooks()self.startTime = getTime()
function ProFi:start(param)if param == 'once' thenif self:shouldReturn() thenreturnelseself.should_run_once = trueendendself.has_started = trueself.has_finished = falseself:resetReports(self.reports)self:startHooks()self.startTime = getTime()
function ProFi:checkMemory( interval, note )local time = getTime()local interval = interval or 0if self.lastCheckMemoryTime and time < self.lastCheckMemoryTime + interval thenreturnendself.lastCheckMemoryTime = timelocal memoryReport = {['time'] = time;['memory'] = collectgarbage('count');['note'] = note or '';}table.insert( self.memoryReports, memoryReport )self:setHighestMemoryReport( memoryReport )self:setLowestMemoryReport( memoryReport )
function ProFi:checkMemory(interval, note)local time = getTime()local interval = interval or 0if self.lastCheckMemoryTime and time < self.lastCheckMemoryTime + interval thenreturnendself.lastCheckMemoryTime = timelocal memoryReport = {['time'] = time,['memory'] = collectgarbage('count'),['note'] = note or '',}table.insert(self.memoryReports, memoryReport)self:setHighestMemoryReport(memoryReport)self:setLowestMemoryReport(memoryReport)
function ProFi:writeReport( filename )if #self.reports > 0 or #self.memoryReports > 0 thenfilename = filename or 'ProFi.txt'self:sortReportsWithSortMethod( self.reports, self.sortMethod )self:writeReportsToFilename( filename )print( string.format("[ProFi]\t Report written to %s", filename) )end
function ProFi:writeReport(filename)if #self.reports > 0 or #self.memoryReports > 0 thenfilename = filename or 'ProFi.txt'self:sortReportsWithSortMethod(self.reports, self.sortMethod)self:writeReportsToFilename(filename)print(string.format("[ProFi]\t Report written to %s", filename))end
self.reports = {}self.reportsByTitle = {}self.memoryReports = {}self.highestMemoryReport = nilself.lowestMemoryReport = nilself.has_started = falseself.has_finished = falseself.should_run_once = falseself.lastCheckMemoryTime = nilself.hookCount = self.hookCount or DEFAULT_DEBUG_HOOK_COUNTself.sortMethod = self.sortMethod or sortByDurationDescself.inspect = nil
self.reports = {}self.reportsByTitle = {}self.memoryReports = {}self.highestMemoryReport = nilself.lowestMemoryReport = nilself.has_started = falseself.has_finished = falseself.should_run_once = falseself.lastCheckMemoryTime = nilself.hookCount = self.hookCount or DEFAULT_DEBUG_HOOK_COUNTself.sortMethod = self.sortMethod or sortByDurationDescself.inspect = nil
function ProFi:setSortMethod( sortType )if sortType == 'duration' thenself.sortMethod = sortByDurationDescelseif sortType == 'count' thenself.sortMethod = sortByCallCountend
function ProFi:setSortMethod(sortType)if sortType == 'duration' thenself.sortMethod = sortByDurationDescelseif sortType == 'count' thenself.sortMethod = sortByCallCountend
function ProFi:setInspect( methodName, levels )if self.inspect thenself.inspect.methodName = methodNameself.inspect.levels = levels or 1elseself.inspect = {['methodName'] = methodName;['levels'] = levels or 1;}end
function ProFi:setInspect(methodName, levels)if self.inspect thenself.inspect.methodName = methodNameself.inspect.levels = levels or 1elseself.inspect = {['methodName'] = methodName,['levels'] = levels or 1,}end
function ProFi:getFuncReport( funcInfo )local title = self:getTitleFromFuncInfo( funcInfo )local funcReport = self.reportsByTitle[ title ]if not funcReport thenfuncReport = self:createFuncReport( funcInfo )self.reportsByTitle[ title ] = funcReporttable.insert( self.reports, funcReport )endreturn funcReport
function ProFi:getFuncReport(funcInfo)local title = self:getTitleFromFuncInfo(funcInfo)local funcReport = self.reportsByTitle[title]if not funcReport thenfuncReport = self:createFuncReport(funcInfo)self.reportsByTitle[title] = funcReporttable.insert(self.reports, funcReport)endreturn funcReport
function ProFi:getTitleFromFuncInfo( funcInfo )local name = funcInfo.name or 'anonymous'local source = funcInfo.short_src or 'C_FUNC'local linedefined = funcInfo.linedefined or 0linedefined = string.format( FORMAT_LINENUM, linedefined )return string.format(FORMAT_TITLE, source, name, linedefined)
function ProFi:getTitleFromFuncInfo(funcInfo)local name = funcInfo.name or 'anonymous'local source = funcInfo.short_src or 'C_FUNC'local linedefined = funcInfo.linedefined or 0linedefined = string.format(FORMAT_LINENUM, linedefined)return string.format(FORMAT_TITLE, source, name, linedefined)
function ProFi:createFuncReport( funcInfo )local name = funcInfo.name or 'anonymous'local source = funcInfo.source or 'C Func'local linedefined = funcInfo.linedefined or 0local funcReport = {['title'] = self:getTitleFromFuncInfo( funcInfo );['count'] = 0;['timer'] = 0;}return funcReport
function ProFi:createFuncReport(funcInfo)local name = funcInfo.name or 'anonymous'local source = funcInfo.source or 'C Func'local linedefined = funcInfo.linedefined or 0local funcReport = {['title'] = self:getTitleFromFuncInfo(funcInfo),['count'] = 0,['timer'] = 0,}return funcReport
function ProFi:writeReportsToFilename( filename )local file, err = io.open( filename, 'w' )assert( file, err )self:writeBannerToFile( file )if #self.reports > 0 thenself:writeProfilingReportsToFile( self.reports, file )endif #self.memoryReports > 0 thenself:writeMemoryReportsToFile( self.memoryReports, file )endfile:close()
function ProFi:writeReportsToFilename(filename)local file, err = io.open(filename, 'w')assert(file, err)self:writeBannerToFile(file)if #self.reports > 0 thenself:writeProfilingReportsToFile(self.reports, file)endif #self.memoryReports > 0 thenself:writeMemoryReportsToFile(self.memoryReports, file)endfile:close()
function ProFi:writeProfilingReportsToFile( reports, file )local totalTime = self.stopTime - self.startTimelocal totalTimeOutput = string.format(FORMAT_TOTALTIME_LINE, totalTime)file:write( totalTimeOutput )local header = string.format( FORMAT_HEADER_LINE, "FILE", "FUNCTION", "LINE", "TIME", "RELATIVE", "CALLED" )file:write( header )for i, funcReport in ipairs( reports ) dolocal timer = string.format(FORMAT_TIME, funcReport.timer)local count = string.format(FORMAT_COUNT, funcReport.count)local relTime = string.format(FORMAT_RELATIVE, (funcReport.timer / totalTime) * 100 )local outputLine = string.format(FORMAT_OUTPUT_LINE, funcReport.title, timer, relTime, count )file:write( outputLine )if funcReport.inspections thenself:writeInpsectionsToFile( funcReport.inspections, file )endend
function ProFi:writeProfilingReportsToFile(reports, file)local totalTime = self.stopTime - self.startTimelocal totalTimeOutput = string.format(FORMAT_TOTALTIME_LINE, totalTime)file:write(totalTimeOutput)local header = string.format(FORMAT_HEADER_LINE, "FILE", "FUNCTION", "LINE", "TIME", "RELATIVE", "CALLED")file:write(header)for i, funcReport in ipairs(reports) dolocal timer = string.format(FORMAT_TIME, funcReport.timer)local count = string.format(FORMAT_COUNT, funcReport.count)local relTime = string.format(FORMAT_RELATIVE, (funcReport.timer / totalTime) * 100)local outputLine = string.format(FORMAT_OUTPUT_LINE, funcReport.title, timer, relTime, count)file:write(outputLine)if funcReport.inspections thenself:writeInpsectionsToFile(funcReport.inspections, file)endend
function ProFi:writeMemoryReportsToFile( reports, file )file:write( FORMAT_MEMORY_HEADER1 )self:writeHighestMemoryReportToFile( file )self:writeLowestMemoryReportToFile( file )file:write( FORMAT_MEMORY_HEADER2 )for i, memoryReport in ipairs( reports ) dolocal outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_MEMORY_LINE )file:write( outputLine )end
function ProFi:writeMemoryReportsToFile(reports, file)file:write(FORMAT_MEMORY_HEADER1)self:writeHighestMemoryReportToFile(file)self:writeLowestMemoryReportToFile(file)file:write(FORMAT_MEMORY_HEADER2)for i, memoryReport in ipairs(reports) dolocal outputLine = self:formatMemoryReportWithFormatter(memoryReport, FORMAT_MEMORY_LINE)file:write(outputLine)end
function ProFi:writeHighestMemoryReportToFile( file )local memoryReport = self.highestMemoryReportlocal outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_HIGH_MEMORY_LINE )file:write( outputLine )
function ProFi:writeHighestMemoryReportToFile(file)local memoryReport = self.highestMemoryReportlocal outputLine = self:formatMemoryReportWithFormatter(memoryReport, FORMAT_HIGH_MEMORY_LINE)file:write(outputLine)
function ProFi:writeLowestMemoryReportToFile( file )local memoryReport = self.lowestMemoryReportlocal outputLine = self:formatMemoryReportWithFormatter( memoryReport, FORMAT_LOW_MEMORY_LINE )file:write( outputLine )
function ProFi:writeLowestMemoryReportToFile(file)local memoryReport = self.lowestMemoryReportlocal outputLine = self:formatMemoryReportWithFormatter(memoryReport, FORMAT_LOW_MEMORY_LINE)file:write(outputLine)
function ProFi:formatMemoryReportWithFormatter( memoryReport, formatter )local time = string.format(FORMAT_TIME, memoryReport.time)local kbytes = string.format(FORMAT_KBYTES, memoryReport.memory)local mbytes = string.format(FORMAT_MBYTES, memoryReport.memory/1024)local outputLine = string.format(formatter, time, kbytes, mbytes, memoryReport.note)return outputLine
function ProFi:formatMemoryReportWithFormatter(memoryReport, formatter)local time = string.format(FORMAT_TIME, memoryReport.time)local kbytes = string.format(FORMAT_KBYTES, memoryReport.memory)local mbytes = string.format(FORMAT_MBYTES, memoryReport.memory / 1024)local outputLine = string.format(formatter, time, kbytes, mbytes, memoryReport.note)return outputLine
function ProFi:writeInpsectionsToFile( inspections, file )local inspectionsList = self:sortInspectionsIntoList( inspections )file:write('\n==^ INSPECT ^======================================================================================================== COUNT ===\n')for i, inspection in ipairs( inspectionsList ) dolocal line = string.format(FORMAT_LINENUM, inspection.line)local title = string.format(FORMAT_TITLE, inspection.source, inspection.name, line)local count = string.format(FORMAT_COUNT, inspection.count)local outputLine = string.format(FORMAT_INSPECTION_LINE, title, count )file:write( outputLine )endfile:write('===============================================================================================================================\n\n')
function ProFi:writeInpsectionsToFile(inspections, file)local inspectionsList = self:sortInspectionsIntoList(inspections)file:write('\n==^ INSPECT ^======================================================================================================== COUNT ===\n')for i, inspection in ipairs(inspectionsList) dolocal line = string.format(FORMAT_LINENUM, inspection.line)local title = string.format(FORMAT_TITLE, inspection.source, inspection.name, line)local count = string.format(FORMAT_COUNT, inspection.count)local outputLine = string.format(FORMAT_INSPECTION_LINE, title, count)file:write(outputLine)endfile:write('===============================================================================================================================\n\n')
function ProFi:sortInspectionsIntoList( inspections )local inspectionsList = {}for k, inspection in pairs(inspections) doinspectionsList[#inspectionsList+1] = inspectionendtable.sort( inspectionsList, sortByCallCount )return inspectionsList
function ProFi:sortInspectionsIntoList(inspections)local inspectionsList = {}for k, inspection in pairs(inspections) doinspectionsList[#inspectionsList + 1] = inspectionendtable.sort(inspectionsList, sortByCallCount)return inspectionsList
function ProFi:resetReports( reports )for i, report in ipairs( reports ) doreport.timer = 0report.count = 0report.inspections = nilend
function ProFi:resetReports(reports)for i, report in ipairs(reports) doreport.timer = 0report.count = 0report.inspections = nilend
function ProFi:getInspectionsFromReport( funcReport )local inspections = funcReport.inspectionsif not inspections theninspections = {}funcReport.inspections = inspectionsendreturn inspections
function ProFi:getInspectionsFromReport(funcReport)local inspections = funcReport.inspectionsif not inspections theninspections = {}funcReport.inspections = inspectionsendreturn inspections
function ProFi:getInspectionWithKeyFromInspections( key, inspections )local inspection = inspections[key]if not inspection theninspection = {['count'] = 0;}inspections[key] = inspectionendreturn inspection
function ProFi:getInspectionWithKeyFromInspections(key, inspections)local inspection = inspections[key]if not inspection theninspection = {['count'] = 0,}inspections[key] = inspectionendreturn inspection
function ProFi:doInspection( inspect, funcReport )local inspections = self:getInspectionsFromReport( funcReport )local levels = 5 + inspect.levelslocal currentLevel = 5while currentLevel < levels dolocal funcInfo = debug.getinfo( currentLevel, 'nS' )if funcInfo thenlocal source = funcInfo.short_src or '[C]'local name = funcInfo.name or 'anonymous'local line = funcInfo.linedefinedlocal key = source..name..linelocal inspection = self:getInspectionWithKeyFromInspections( key, inspections )inspection.source = sourceinspection.name = nameinspection.line = lineinspection.count = inspection.count + 1currentLevel = currentLevel + 1elsebreakendend
function ProFi:doInspection(inspect, funcReport)local inspections = self:getInspectionsFromReport(funcReport)local levels = 5 + inspect.levelslocal currentLevel = 5while currentLevel < levels dolocal funcInfo = debug.getinfo(currentLevel, 'nS')if funcInfo thenlocal source = funcInfo.short_src or '[C]'local name = funcInfo.name or 'anonymous'local line = funcInfo.linedefinedlocal key = source .. name .. linelocal inspection = self:getInspectionWithKeyFromInspections(key, inspections)inspection.source = sourceinspection.name = nameinspection.line = lineinspection.count = inspection.count + 1currentLevel = currentLevel + 1elsebreakendend
function ProFi:onFunctionCall( funcInfo )local funcReport = ProFi:getFuncReport( funcInfo )funcReport.callTime = getTime()funcReport.count = funcReport.count + 1if self:shouldInspect( funcInfo ) thenself:doInspection( self.inspect, funcReport )end
function ProFi:onFunctionCall(funcInfo)local funcReport = ProFi:getFuncReport(funcInfo)funcReport.callTime = getTime()funcReport.count = funcReport.count + 1if self:shouldInspect(funcInfo) thenself:doInspection(self.inspect, funcReport)end
function ProFi:onFunctionReturn( funcInfo )local funcReport = ProFi:getFuncReport( funcInfo )if funcReport.callTime thenfuncReport.timer = funcReport.timer + (getTime() - funcReport.callTime)end
function ProFi:onFunctionReturn(funcInfo)local funcReport = ProFi:getFuncReport(funcInfo)if funcReport.callTime thenfuncReport.timer = funcReport.timer + (getTime() - funcReport.callTime)end
function ProFi:setHighestMemoryReport( memoryReport )if not self.highestMemoryReport thenself.highestMemoryReport = memoryReportelseif memoryReport.memory > self.highestMemoryReport.memory thenself.highestMemoryReport = memoryReportendend
function ProFi:setHighestMemoryReport(memoryReport)if not self.highestMemoryReport thenself.highestMemoryReport = memoryReportelseif memoryReport.memory > self.highestMemoryReport.memory thenself.highestMemoryReport = memoryReportendend
function ProFi:setLowestMemoryReport( memoryReport )if not self.lowestMemoryReport thenself.lowestMemoryReport = memoryReportelseif memoryReport.memory < self.lowestMemoryReport.memory thenself.lowestMemoryReport = memoryReportendend
function ProFi:setLowestMemoryReport(memoryReport)if not self.lowestMemoryReport thenself.lowestMemoryReport = memoryReportelseif memoryReport.memory < self.lowestMemoryReport.memory thenself.lowestMemoryReport = memoryReportendend
onDebugHook = function( hookType )local funcInfo = debug.getinfo( 2, 'nS' )if hookType == "call" thenProFi:onFunctionCall( funcInfo )elseif hookType == "return" thenProFi:onFunctionReturn( funcInfo )end
onDebugHook = function(hookType)local funcInfo = debug.getinfo(2, 'nS')if hookType == "call" thenProFi:onFunctionCall(funcInfo)elseif hookType == "return" thenProFi:onFunctionReturn(funcInfo)end