// 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); } } } }