summaryrefslogtreecommitdiffstats
path: root/Tools/PerfSummary/LogParser.cs
diff options
context:
space:
mode:
authorKonstantin <const@const.me>2023-01-20 15:25:02 +0100
committerKonstantin <const@const.me>2023-01-20 15:25:02 +0100
commit5483755f6332dc0f00174a9f7869f44073f4359d (patch)
tree7caafd1d3185ec0ced82afa3996ae537a5759bd9 /Tools/PerfSummary/LogParser.cs
parenta052894a31128ef62e53ae34efd3485c2bbd8569 (diff)
A tool to summarize performance data into one table
Diffstat (limited to 'Tools/PerfSummary/LogParser.cs')
-rw-r--r--Tools/PerfSummary/LogParser.cs207
1 files changed, 207 insertions, 0 deletions
diff --git a/Tools/PerfSummary/LogParser.cs b/Tools/PerfSummary/LogParser.cs
new file mode 100644
index 0000000..c89d695
--- /dev/null
+++ b/Tools/PerfSummary/LogParser.cs
@@ -0,0 +1,207 @@
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace PerfSummary
+{
+ enum eInputClip: byte
+ {
+ jfk,
+ columbia,
+ }
+ enum eWhisperModel: byte
+ {
+ medium,
+ large
+ }
+
+ struct LogName
+ {
+ public readonly eInputClip clip;
+ public readonly eWhisperModel model;
+ public readonly string gpu;
+
+ public override string ToString() => $"{clip}-{model}-{gpu}";
+
+ public static LogName? tryParse( string path )
+ {
+ string? ext = Path.GetExtension( path );
+ if( ext == null || !ext.Equals( ".txt", StringComparison.InvariantCultureIgnoreCase ) )
+ return null;
+
+ string name = Path.GetFileNameWithoutExtension( path );
+ string[] fields = name.Split( '-' );
+ if( fields.Length != 3 )
+ return null;
+
+ return new LogName( fields );
+ }
+
+ LogName( string[] fields )
+ {
+ clip = Enum.Parse<eInputClip>( fields[ 0 ] );
+ model = Enum.Parse<eWhisperModel>( fields[ 1 ] );
+ gpu = fields[ 2 ];
+ }
+ }
+
+ record class LogData
+ {
+ public LogName name { get; init; }
+ // The numbers are seconds
+ public double runComplete { get; init; }
+ public double encode { get; init; }
+ public double decode { get; init; }
+ // The numbers are megabytes
+ public double ram { get; init; }
+ public double vram { get; init; }
+ }
+
+ static class LogParser
+ {
+ public static IEnumerable<LogData> parse( string folder )
+ {
+ foreach( string path in Directory.EnumerateFiles( folder, "*.txt" ) )
+ {
+ LogName? name = LogName.tryParse( path );
+ if( name == null )
+ continue;
+ yield return parseFile( name.Value, path );
+ }
+ }
+
+ enum eSection: byte
+ {
+ CPU, GPU, Shaders, Memory
+ }
+ static readonly (string, eSection)[] sectionMarkers = new (string, eSection)[]
+ {
+ ("CPU Tasks", eSection.CPU),
+ ("GPU Tasks", eSection.GPU),
+ ("Compute Shaders", eSection.Shaders),
+ ("Memory Usage", eSection.Memory),
+ };
+
+ static bool tryParseSection( ref eSection? section, string line )
+ {
+ foreach( (string marker, eSection s) in sectionMarkers )
+ {
+ if( line.Contains( marker ) )
+ {
+ section = s;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool tryParseTime( ref double? val, string key, string line )
+ {
+ if( !line.StartsWith( key ) )
+ return false;
+ if( !char.IsWhiteSpace( line[ key.Length ] ) )
+ return false;
+
+ line = line.Substring( key.Length ).TrimStart();
+ int comma = line.IndexOf( ',' );
+ if( comma > 0 )
+ line = line.Substring( 0, comma );
+ string[] fields = line.Split( ' ', StringSplitOptions.RemoveEmptyEntries );
+ if( fields.Length != 2 )
+ throw new ArgumentException();
+
+ double v = double.Parse( fields[ 0 ], CultureInfo.InvariantCulture );
+ switch( fields[ 1 ] )
+ {
+ case "seconds":
+ val = v;
+ return true;
+ case "milliseconds":
+ val = v / 1E3;
+ return true;
+ case "microseconds":
+ val = v / 1E6;
+ return true;
+ }
+ throw new ArgumentException();
+ }
+
+ static readonly Regex reMemory = new Regex( @"^Total\s+([0-9\.]+)\s+(\S+)\s+RAM, ([0-9\.]+)\s+(\S+)\s+VRAM$" );
+
+ static double parseMemory( Match m, int iv )
+ {
+ double v = double.Parse( m.Groups[ iv ].Value, CultureInfo.InvariantCulture );
+ string u = m.Groups[ iv + 1 ].Value;
+ switch( u )
+ {
+ case "bytes":
+ return v / ( 1 << 20 );
+ case "KB":
+ return v / ( 1 << 10 );
+ case "MB":
+ return v;
+ case "GB":
+ return v * ( 1 << 10 );
+ }
+ throw new ArgumentException();
+ }
+
+ static bool tryParseMemory( ref double? ram, ref double? vram, string line )
+ {
+ Match m = reMemory.Match( line );
+ if( !m.Success )
+ return false;
+ ram = parseMemory( m, 1 );
+ vram = parseMemory( m, 3 );
+ return true;
+ }
+
+ static LogData parseFile( in LogName name, string path )
+ {
+ using var reader = File.OpenText( path );
+ double? runComplete = null;
+ double? encode = null;
+ double? decode = null;
+ double? ram = null;
+ double? vram = null;
+ eSection? section = null;
+
+ while( true )
+ {
+ string? line = reader.ReadLine();
+ if( line == null )
+ break;
+ if( string.IsNullOrEmpty( line ) )
+ continue;
+ if( tryParseSection( ref section, line ) )
+ continue;
+
+ switch( section )
+ {
+ case eSection.CPU:
+ tryParseTime( ref runComplete, "RunComplete", line );
+ break;
+ case eSection.GPU:
+ tryParseTime( ref encode, "Encode", line );
+ tryParseTime( ref decode, "Decode", line );
+ break;
+ case eSection.Memory:
+ tryParseMemory( ref ram, ref vram, line );
+ break;
+ }
+ }
+
+ if( null == runComplete || null == encode || null == decode || null == ram || null == vram )
+ throw new ArgumentException();
+
+ return new LogData()
+ {
+ name = name,
+ runComplete = runComplete.Value,
+ encode = encode.Value,
+ decode = decode.Value,
+ ram = ram.Value,
+ vram = vram.Value,
+ };
+ }
+ }
+} \ No newline at end of file