// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EpicGames.Core;
namespace UnrealBuildTool
{
///
/// Types of timing data events.
///
public enum TimingDataType
{
///
/// No type assigned.
///
None,
///
/// This event represents an aggregate of summary events.
///
Aggregate,
///
/// This event represents a summary of related include, class, and function events, usually
/// summarizing a single compilation unit or part of a compilation unit.
///
Summary,
///
/// Timing related to compiling include files.
///
Include,
///
/// Timing related to compiling classes.
///
Class,
///
/// Timing related to compiling functions.
///
Function,
}
///
/// Class used to capture timing data from events like those generated by MSVC when timing data
/// is being generated.
///
[Serializable]
public class TimingData : IBinarySerializable
{
///
/// Constructs a new instance of .
///
public TimingData(string Name, TimingDataType Type)
{
this.Name = Name;
this.Type = Type;
}
///
/// Constructs a new instance of using data from a .
///
/// The to get the data from.
public TimingData(BinaryReader Reader)
{
Name = Reader.ReadString();
Type = (TimingDataType)Reader.ReadByte();
Count = Reader.ReadInt32();
ExclusiveDuration = Reader.ReadDouble();
int ChildCount = Reader.ReadInt32();
for (int i = 0; i < ChildCount; ++i)
{
TimingData NewChild = new TimingData(Reader);
Children.Add(NewChild.Name, NewChild);
}
}
///
/// The name of the event being represented, such as a file or category name.
///
public string Name { get; set; }
///
/// The type of timing data this event represents.
///
public TimingDataType Type { get; set; }
///
/// Gets the number of times this event was encountered.
///
public int Count { get; set; } = 1;
///
/// Gets the amount of time, in milliseconds, that the event took to complete disregarding its sub-events.
///
public double ExclusiveDuration { get; set; } = 0.0;
///
/// Gets the amount of time, in milliseconds, that the event took including its sub-events.
///
public double InclusiveDuration => ExclusiveDuration + Children.Sum(c => c.Value.InclusiveDuration);
///
/// If this event is a sub-event, the parent is the event it is the sub-event to.
///
public TimingData? Parent { get; set; }
///
/// Any sub-events of this event.
///
public Dictionary Children { get; set; } = new Dictionary();
///
/// Adds a sub-event (child) to this event if it doesn't exist, or increase the duration by the
/// duration of the provided event.
///
/// The sub-event to add to this event.
public void AddChild(TimingData ChildData)
{
TimingData? MatchingData;
if (Children.TryGetValue(ChildData.Name, out MatchingData))
{
MatchingData.ExclusiveDuration += ChildData.ExclusiveDuration;
foreach (TimingData ChildChildData in ChildData.Children.Values)
{
MatchingData.AddChild(ChildChildData);
}
}
else
{
Children.Add(ChildData.Name, ChildData);
}
}
///
/// Creates a deep clone of this event.
///
/// A deep clone of this event.
public TimingData Clone()
{
TimingData ClonedTimingData = new TimingData(Name, Type)
{
ExclusiveDuration = ExclusiveDuration,
};
foreach (KeyValuePair Child in Children)
{
ClonedTimingData.Children.Add(Child.Key, Child.Value.Clone());
}
return ClonedTimingData;
}
///
/// Writes a binary representation of this event and its sub-events.
///
/// The to write the binary representation to.
public void Write(BinaryWriter Writer)
{
Writer.Write(Name);
Writer.Write((byte)Type);
Writer.Write(Count);
Writer.Write(ExclusiveDuration);
Writer.Write(Children.Count);
foreach (TimingData Child in Children.Values)
{
Writer.Write(Child);
}
}
}
}