You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
This summary type sums up multiple CsvStat averages and emits the total as a SummaryTableMetric named metricName (if specified). - Budget colors can optionally be applied to individual stats and/or the total via colourThresholds and colourThresholdsTotal nodes - If emitStatMetrics is enabled, each stat will emit a SummaryTableMetric, named metricName/strippedStatName (with the same value as the existing CsvStatAverage element if it exists) - Budget coloring is applied to existing CsvStatAverage elements. - The budget for a given stat is assumed to be the first element of its colourThresholds. This value is displayed in the report - A totalStatName attribute can be specified if a total stat already exists. If so, an "other" value will be output to the detailed summary table with the unaccounted value - If the showTotal attribute is set to false (default: true), the total won't be shown in the detailed report Other changes: - Always read all CSV stat averages, regardless of whether -readAllStats is specified. -readAllStats is only now used to determine whether to show CSV stat averages in a summary table Example: <summary type="statBudgets" metricName="GTGameplay" title="Gamethread - Gameplay Budgets" hideStatPrefix="Exclusive/GameThread/" emitStatMetrics="1"> <colourThresholdsTotal>3,4,5,6</colourThresholdsTotal> <colourThresholds stat="Exclusive/GameThread/Buildings">1,2,3,4</colourThresholds> <stats>Exclusive/GameThread/Buildings,Exclusive/GameThread/Camera,Exclusive/GameThread/Curie,Exclusive/GameThread/Network*,Exclusive/GameThread/PlayerController*,Exclusive/GameThread/WorldTickMisc,Exclusive/GameThread/FlushLatentActions,Exclusive/GameThread/Tickables,Exclusive/GameThread/SyncBodies,Exclusive/GameThread/CharPhys*,Exclusive/GameThread/Character*,Exclusive/GameThread/FortPawnTickSubsystem,Exclusive/GameThread/SignificanceManager,exclusive/gamethread/vehicle*,Exclusive/GameThread/AbilityTasks,Exclusive/GameThread/Actor*,Exclusive/GameThread/HandleRPC,Exclusive/GameThread/RepNotifies,Exclusive/GameThread/TickActors,Exclusive/GameThread/Pickups,Exclusive/GameThread/ProjectileMovement,Exclusive/GameThread/TimelineComponent,Exclusive/GameThread/TimerManager,Exclusive/GameThread/FortTrainManager</stats> </summary> [FYI] andrew.ladenberger, michael.short [CL 30329557 by ben woodhouse in ue5-main branch]
248 lines
8.5 KiB
C#
248 lines
8.5 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
using CSVStats;
|
|
using PerfReportTool;
|
|
using System.Reflection;
|
|
using System.Drawing;
|
|
|
|
namespace PerfSummaries
|
|
{
|
|
class SummaryFactory
|
|
{
|
|
public static void Init()
|
|
{
|
|
summaryNameLookup = new Dictionary<string, Type>();
|
|
Assembly assembly = typeof(SummaryFactory).GetTypeInfo().Assembly;
|
|
foreach (Type type in assembly.GetTypes())
|
|
{
|
|
if (type.IsSubclassOf(typeof(Summary)))
|
|
{
|
|
Summary instance = (Summary)Activator.CreateInstance(type);
|
|
summaryNameLookup.Add(instance.GetName(), type);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Summary Create(string summaryTypeName, XElement summaryXmlElement, XmlVariableMappings vars, string baseXmlDirectory)
|
|
{
|
|
if ( summaryNameLookup.TryGetValue(summaryTypeName, out System.Type summaryType ) )
|
|
{
|
|
object[] constructArgs = new object[3] { summaryXmlElement, vars, baseXmlDirectory };
|
|
return (Summary)Activator.CreateInstance(summaryType, constructArgs);
|
|
}
|
|
throw new Exception("Summary type " + summaryType + " not found!");
|
|
}
|
|
|
|
static Dictionary<string, System.Type> summaryNameLookup = null;
|
|
};
|
|
|
|
abstract class Summary
|
|
{
|
|
|
|
public class CaptureRange
|
|
{
|
|
public string name;
|
|
public string startEvent;
|
|
public string endEvent;
|
|
public bool includeFirstFrame;
|
|
public bool includeLastFrame;
|
|
public CaptureRange(string inName, string start, string end)
|
|
{
|
|
name = inName;
|
|
startEvent = start;
|
|
endEvent = end;
|
|
includeFirstFrame = false;
|
|
includeLastFrame = false;
|
|
}
|
|
}
|
|
public class CaptureData
|
|
{
|
|
public int startIndex;
|
|
public int endIndex;
|
|
public List<float> Frames;
|
|
public CaptureData(int start, int end, List<float> inFrames)
|
|
{
|
|
startIndex = start;
|
|
endIndex = end;
|
|
Frames = inFrames;
|
|
}
|
|
}
|
|
|
|
public Summary()
|
|
{
|
|
stats = new List<string>();
|
|
captures = new List<CaptureRange>();
|
|
StatThresholds = new Dictionary<string, ColourThresholdList>();
|
|
|
|
}
|
|
public virtual void WriteSummaryData(System.IO.StreamWriter htmlFile, CsvStats csvStats, CsvStats csvStatsUnstripped, bool bWriteSummaryCsv, SummaryTableRowData rowData, string htmlFileName)
|
|
{ }
|
|
|
|
public virtual void PostInit(ReportTypeInfo reportTypeInfo, CsvStats csvStats)
|
|
{
|
|
// Resolve wildcards and remove duplicates
|
|
stats = csvStats.GetStatNamesMatchingStringList(stats.ToArray());
|
|
}
|
|
|
|
public abstract string GetName();
|
|
|
|
public void ReadStatsFromXML(XElement element, XmlVariableMappings vars)
|
|
{
|
|
useUnstrippedCsvStats = element.GetSafeAttribute<bool>(vars, "useUnstrippedCsvStats", false);
|
|
XElement statsElement = element.Element("stats");
|
|
if (statsElement != null)
|
|
{
|
|
stats = statsElement.GetValue(vars).Split(',').ToList();
|
|
}
|
|
foreach (XElement child in element.Elements())
|
|
{
|
|
if (child.Name == "capture")
|
|
{
|
|
string captureName = child.GetRequiredAttribute<string>(vars, "name");
|
|
string captureStart = child.GetRequiredAttribute<string>(vars, "startEvent");
|
|
string captureEnd = child.GetRequiredAttribute<string>(vars, "endEvent");
|
|
bool incFirstFrame = child.GetSafeAttribute<bool>(vars, "includeFirstFrame", true);
|
|
bool incLastFrame = child.GetSafeAttribute<bool>(vars, "includeLastFrame", true);
|
|
CaptureRange newRange = new CaptureRange(captureName, captureStart, captureEnd);
|
|
newRange.includeFirstFrame = incFirstFrame;
|
|
newRange.includeLastFrame = incLastFrame;
|
|
captures.Add(newRange);
|
|
}
|
|
else if (child.Name == "colourThresholds")
|
|
{
|
|
if (child.Attribute("stat") == null)
|
|
{
|
|
continue;
|
|
}
|
|
string statName = child.GetRequiredAttribute<string>(vars, "stat");
|
|
string hitchThresholdsStr = child.GetValue(vars);
|
|
if (hitchThresholdsStr == "")
|
|
{
|
|
continue;
|
|
}
|
|
string[] hitchThresholdsStrList = hitchThresholdsStr.Split(',');
|
|
ColourThresholdList HitchThresholds = new ColourThresholdList();
|
|
for (int i = 0; i < hitchThresholdsStrList.Length; i++)
|
|
{
|
|
string hitchThresholdStr = hitchThresholdsStrList[i];
|
|
string hitchThresholdNumStr = hitchThresholdStr;
|
|
Colour thresholdColour = null;
|
|
|
|
int openBracketIndex = hitchThresholdStr.IndexOf('(');
|
|
if (openBracketIndex != -1 )
|
|
{
|
|
hitchThresholdNumStr = hitchThresholdStr.Substring(0, openBracketIndex);
|
|
int closeBracketIndex = hitchThresholdStr.IndexOf(')');
|
|
if (closeBracketIndex > openBracketIndex)
|
|
{
|
|
string colourString = hitchThresholdStr.Substring(openBracketIndex+1, closeBracketIndex - openBracketIndex-1);
|
|
thresholdColour = new Colour(colourString);
|
|
}
|
|
}
|
|
double thresholdValue = Convert.ToDouble(hitchThresholdNumStr, System.Globalization.CultureInfo.InvariantCulture);
|
|
|
|
HitchThresholds.Add(new ThresholdInfo(thresholdValue, thresholdColour));
|
|
}
|
|
if (HitchThresholds.Count == 4)
|
|
{
|
|
StatThresholds.Add(statName, HitchThresholds);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public CaptureData GetFramesForCapture(CaptureRange inCapture, List<float> FrameTimes, List<CsvEvent> EventsCaptured)
|
|
{
|
|
List<float> ReturnFrames = new List<float>();
|
|
int startFrame = -1;
|
|
int endFrame = FrameTimes.Count;
|
|
for (int i = 0; i < EventsCaptured.Count; i++)
|
|
{
|
|
if (startFrame < 0 && EventsCaptured[i].Name.ToLower().Contains(inCapture.startEvent.ToLower()))
|
|
{
|
|
startFrame = EventsCaptured[i].Frame;
|
|
if (!inCapture.includeFirstFrame)
|
|
{
|
|
startFrame++;
|
|
}
|
|
}
|
|
else if (endFrame >= FrameTimes.Count && EventsCaptured[i].Name.ToLower().Contains(inCapture.endEvent.ToLower()))
|
|
{
|
|
endFrame = EventsCaptured[i].Frame;
|
|
if (!inCapture.includeLastFrame)
|
|
{
|
|
endFrame--;
|
|
}
|
|
}
|
|
}
|
|
if (startFrame == -1 || endFrame == FrameTimes.Count || endFrame < startFrame)
|
|
{
|
|
return null;
|
|
}
|
|
ReturnFrames = FrameTimes.GetRange(startFrame, (endFrame - startFrame));
|
|
CaptureData CaptureToUse = new CaptureData(startFrame, endFrame, ReturnFrames);
|
|
return CaptureToUse;
|
|
}
|
|
|
|
public string[] GetUniqueStatNames()
|
|
{
|
|
HashSet<string> uniqueStats = new HashSet<string>();
|
|
foreach (string stat in stats)
|
|
{
|
|
if (!uniqueStats.Contains(stat))
|
|
{
|
|
uniqueStats.Add(stat);
|
|
}
|
|
}
|
|
return uniqueStats.ToArray();
|
|
}
|
|
|
|
protected ColourThresholdList ReadColourThresholdListXML(XElement colourThresholdEl, XmlVariableMappings vars)
|
|
{
|
|
return ColourThresholdList.ReadColourThresholdListXML(colourThresholdEl, vars);
|
|
}
|
|
|
|
protected double [] ReadColourThresholdsXML(XElement colourThresholdEl, XmlVariableMappings vars)
|
|
{
|
|
return ColourThresholdList.ReadColourThresholdsXML(colourThresholdEl, vars);
|
|
}
|
|
|
|
public string GetStatThresholdColour(string StatToUse, double value)
|
|
{
|
|
ColourThresholdList Thresholds = GetStatColourThresholdList(StatToUse);
|
|
if (Thresholds != null)
|
|
{
|
|
return Thresholds.GetColourForValue(value);
|
|
}
|
|
return "'#ffffff'";
|
|
}
|
|
|
|
public ColourThresholdList GetStatColourThresholdList(string StatToUse)
|
|
{
|
|
if (StatThresholds.ContainsKey(StatToUse))
|
|
{
|
|
return StatThresholds[StatToUse];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public List<CaptureRange> captures;
|
|
public List<string> stats;
|
|
public Dictionary<string, ColourThresholdList> StatThresholds;
|
|
public bool useUnstrippedCsvStats;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|