Skip to content

Commit

Permalink
Adding lazy initialization for CPU Core threads.
Browse files Browse the repository at this point in the history
Fixing a bug with incorrect presentation of the sampling data in Source Code control.
  • Loading branch information
bombomby committed Apr 19, 2019
1 parent 67a8811 commit 3ba5d4a
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 58 deletions.
26 changes: 18 additions & 8 deletions gui/Data/EventBoard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,12 @@ public override void CollectDescriptionFilter(HashSet<Object> filter)
public override void Add(SamplingNode node)
{
base.Add(node);
Self += node.Sampled;
SelfPercent += node.SelfPercent;

if (!node.ExcludeFromSelf)
{
Self += node.Sampled;
SelfPercent += node.SelfPercent;
}

if (!node.ExcludeFromTotal)
{
Expand All @@ -157,14 +161,13 @@ public Board(TNode node)
AddRange(items.Values);
}

void Add(Dictionary<Object, TItem> items, TNode node)
void AddInternal(Dictionary<Object, TItem> items, TNode node)
{
TDescription description = node.Description;
if (description != null)
if (node.Description != null)
{
TItem item;

Object key = description.GetSharedKey();
Object key = node.Description.GetSharedKey();

if (!items.TryGetValue(key, out item))
{
Expand All @@ -174,9 +177,16 @@ void Add(Dictionary<Object, TItem> items, TNode node)

item.Add(node);
}
}

void Add(Dictionary<Object, TItem> items, TNode node)
{
if (node.ShadowNodes != null)
node.ShadowNodes.ForEach(shadow => AddInternal(items, shadow as TNode));
else
AddInternal(items, node);

foreach (TNode child in node.Children)
Add(items, child);
node.Children?.ForEach(child => Add(items, child as TNode));
}
}
}
20 changes: 17 additions & 3 deletions gui/Data/EventTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public abstract class BaseTreeNode : INotifyPropertyChanged
private bool isSelected;
private Visibility visible;

public BaseTreeNode Parent { get; private set; }
public BaseTreeNode Parent { get; set; }
public BaseTreeNode RootParent { get; private set; }
public List<BaseTreeNode> Children { get; private set; }

Expand All @@ -27,6 +27,7 @@ public abstract class BaseTreeNode : INotifyPropertyChanged
public abstract String ToolTipName { get; }

public virtual List<Tag> Tags { get { return null; } set { } }
public virtual List<BaseTreeNode> ShadowNodes { get { return null; } }

public event PropertyChangedEventHandler PropertyChanged;
private void Raise(string propertyName)
Expand All @@ -45,7 +46,19 @@ public double Ratio
}

public double TotalPercent { get { return RootParent != null ? (100.0 * Duration / RootParent.Duration) : 100.0; } }
public double SelfPercent { get { return RootParent != null ? (100.0 * SelfDuration / RootParent.Duration) : (SelfDuration / Duration); } }
public double SelfPercent
{
get
{
if (RootParent != null)
return (100.0 * SelfDuration / RootParent.Duration);

if (Duration > 0.0)
return SelfDuration / Duration;

return 0.0;
}
}

public abstract String Path { get; }

Expand Down Expand Up @@ -177,7 +190,8 @@ public abstract class TreeNode<TDescription> : BaseTreeNode
public override String Name { get { return Description.Name; } }
public override String ToolTipName { get { return String.Format("{0}\n{1}", Description.FullName, Description.Path); } }

public bool ExcludeFromTotal { get; private set; }
public bool ExcludeFromTotal { get; set; } = false;
public bool ExcludeFromSelf { get; set; } = false;

public TreeNode(TreeNode<TDescription> root, TDescription desc, double duration)
: base(root, duration)
Expand Down
86 changes: 52 additions & 34 deletions gui/Data/FrameCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Profiler.Data

public class ThreadData
{
public ThreadDescription Description { get; set; }
public List<EventFrame> Events { get; set; }
public List<Callstack> Callstacks { get; set; }
public List<SysCallEntry> SysCalls { get; set; }
Expand All @@ -21,8 +22,9 @@ public class ThreadData
public TagsPack TagsPack { get; set; }
public bool IsDirty { get; set; }

public ThreadData()
public ThreadData(ThreadDescription desc)
{
Description = desc;
Events = new List<EventFrame>();
}

Expand Down Expand Up @@ -97,13 +99,16 @@ public class FrameGroup
public EventDescriptionBoard Board { get; set; }
public ISamplingBoard SamplingBoard { get; set; }
public List<ThreadData> Threads { get; set; }
public List<ThreadData> Cores { get; set; }
public List<ThreadData> Fibers { get; set; }
public ThreadData MainThread { get { return Threads[Board.MainThreadIndex]; } }
public SummaryPack Summary { get; set; }
public SynchronizationMap Synchronization { get; set; }

public List<DataResponse> Responses { get; set; }

public bool IsCoreDataGenerated { get; set; }

public List<ThreadData> GetThreads(ThreadDescription.Source origin)
{
List<ThreadData> threads = new List<ThreadData>();
Expand All @@ -125,7 +130,7 @@ public FrameGroup(EventDescriptionBoard board)

Threads = new List<ThreadData>(board.Threads.Count);
foreach (ThreadDescription desc in board.Threads)
Threads.Add(new ThreadData());
Threads.Add(new ThreadData(desc));

Fibers = new List<ThreadData>();
Responses = new List<DataResponse>();
Expand All @@ -143,7 +148,7 @@ public void AddFrame(EventFrame frame)
{
while (threadIndex >= Threads.Count)
{
Threads.Add(new ThreadData());
Threads.Add(new ThreadData(Board.Threads[threadIndex]));
}
Threads[threadIndex].Events.Add(frame);
}
Expand All @@ -154,53 +159,66 @@ public void AddFrame(EventFrame frame)
{
while (fiberIndex >= Fibers.Count)
{
Fibers.Add(new ThreadData());
Fibers.Add(new ThreadData(null));
}
Fibers[fiberIndex].Events.Add(frame);
}
}
}

private void GenerateDummyCoreThreads()
{
if (Cores == null)
{
Cores = new List<ThreadData>(Board.CPUCoreCount);

foreach (KeyValuePair<UInt64, Synchronization> pair in Synchronization.SyncMap)
{
foreach (SyncInterval interval in pair.Value)
{
while (Cores.Count <= interval.Core)
{
ThreadDescription desc = new ThreadDescription() { Name = String.Format("CPU Core {0:00}", Cores.Count), ThreadID = UInt64.MaxValue, Origin = ThreadDescription.Source.Core };
Cores.Add(AddThread(desc));
}
}
}
}
}

void GenerateCoreThreads()
public void GenerateRealCoreThreads()
{
List<KeyValuePair<ThreadDescription, ThreadData>> cores = new List<KeyValuePair<ThreadDescription, ThreadData>>(Board.CPUCoreCount);

foreach (KeyValuePair<UInt64, Synchronization> pair in Synchronization.SyncMap)
if (Cores != null && !IsCoreDataGenerated)
{
ThreadDescription threadDesc = null;
Board.ThreadDescriptions.TryGetValue(pair.Key, out threadDesc);

if (threadDesc != null && threadDesc.IsIdle)
continue;
foreach (KeyValuePair<UInt64, Synchronization> pair in Synchronization.SyncMap)
{
ThreadDescription threadDesc = null;
Board.ThreadDescriptions.TryGetValue(pair.Key, out threadDesc);

EventDescription eventDesc = new EventDescription(threadDesc != null ? String.Format("{0}:0x{1:X}", threadDesc.FullName, threadDesc.ThreadID) : pair.Key.ToString("X"));
if (threadDesc != null && threadDesc.ProcessID != Board.ProcessID)
eventDesc.Color = Colors.SlateGray;
if (threadDesc != null && threadDesc.IsIdle)
continue;

foreach (SyncInterval interval in pair.Value)
{
byte core = interval.Core;
EventDescription eventDesc = new EventDescription(threadDesc != null ? String.Format("{0}:0x{1:X}", threadDesc.FullName, threadDesc.ThreadID) : pair.Key.ToString("X"));
if (threadDesc != null && threadDesc.ProcessID != Board.ProcessID)
eventDesc.Color = Colors.SlateGray;

while (cores.Count <= core)
{
ThreadDescription desc = new ThreadDescription() { Name = String.Format("CPU Core {0:00}", cores.Count), ThreadID = UInt64.MaxValue, Origin = ThreadDescription.Source.Core };
cores.Add(new KeyValuePair<ThreadDescription, ThreadData>(desc, AddThread(desc)));
}
foreach (SyncInterval interval in pair.Value)
{
byte core = interval.Core;

Entry entry = new Entry(eventDesc, interval.Start, interval.Finish);
Entry entry = new Entry(eventDesc, interval.Start, interval.Finish);

EventFrame frame = new EventFrame(new FrameHeader(interval, cores[interval.Core].Key.ThreadIndex), new List<Entry>() { entry }, this);
entry.Frame = frame;
EventFrame frame = new EventFrame(new FrameHeader(interval, Cores[interval.Core].Description.ThreadIndex), new List<Entry>() { entry }, this);
entry.Frame = frame;

cores[interval.Core].Value.Events.Add(frame);
Cores[interval.Core].Events.Add(frame);
}
}
}

cores.ForEach(core => core.Value.Events.Sort());
Cores.ForEach(core => core.Events.Sort());
IsCoreDataGenerated = true;
}
}


private void GenerateMiscThreads()
{
Expand Down Expand Up @@ -255,7 +273,7 @@ public void AddSynchronization(SynchronizationMap syncMap)
}
}

GenerateCoreThreads();
GenerateDummyCoreThreads();
GenerateMiscThreads();
}

Expand All @@ -268,7 +286,7 @@ public void AddFiberSynchronization(FiberSynchronization fiberSync)
int index = fiberSync.FiberIndex;
while (index >= Fibers.Count)
{
Fibers.Add(new ThreadData());
Fibers.Add(new ThreadData(null));
}
Fibers[index].FiberSync = fiberSync;

Expand Down Expand Up @@ -404,7 +422,7 @@ public ThreadData AddThread(ThreadDescription desc)
desc.ThreadIndex = index;
if (desc.ThreadID != UInt64.MaxValue)
Board.ThreadID2ThreadIndex.Add(desc.ThreadID, index);
ThreadData threadData = new ThreadData();
ThreadData threadData = new ThreadData(desc);
Threads.Add(threadData);
Board.Threads.Add(desc);
return threadData;
Expand Down
13 changes: 9 additions & 4 deletions gui/Data/SamplingFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ public class SamplingNode : TreeNode<SamplingDescription>
public UInt64 Address { get; private set; }
public override String Name { get { return Description.Name; } }

private List<BaseTreeNode> shadowNodes = new List<BaseTreeNode>();
public override List<BaseTreeNode> ShadowNodes { get { return shadowNodes; } }

// Participated in sampling process
public uint Passed { get; private set; }

Expand All @@ -231,7 +234,7 @@ public uint Sampled

//public SamplingNode Parent { get; private set; }

SamplingNode(SamplingNode root, SamplingDescription desc, UInt64 address, UInt32 passed)
SamplingNode(SamplingNode root, SamplingDescription desc, UInt32 passed)
: base(root, desc, passed)
{
Passed = passed;
Expand All @@ -247,7 +250,7 @@ public static SamplingNode Create(BinaryReader reader, SamplingDescriptionBoard

UInt32 passed = reader.ReadUInt32();

SamplingNode node = new SamplingNode(root, desc, address, passed);
SamplingNode node = new SamplingNode(root, desc, passed);

UInt32 childrenCount = reader.ReadUInt32();
for (UInt32 i = 0; i < childrenCount; ++i)
Expand All @@ -274,13 +277,15 @@ void AppendMerge(Callstack callstack, int index, SamplingNode root)
{
if (IsSimilar(node.Description, desc))
{
node.shadowNodes.Add(new SamplingNode(rootNode, desc, 1) { Parent = this, ChildrenDuration = index == callstack.Count - 1 ? 0 : 1 });
++node.Passed;
node.AppendMerge(callstack, index + 1, rootNode);
return;
}
}

SamplingNode child = new SamplingNode(rootNode, desc, desc.Address, 1);
SamplingNode child = new SamplingNode(rootNode, desc, 1);
child.shadowNodes.Add(new SamplingNode(rootNode, desc, 1) { Parent = child, ChildrenDuration = index == callstack.Count - 1 ? 0 : 1 });
AddChild(child);
child.AppendMerge(callstack, index + 1, rootNode);
}
Expand All @@ -302,7 +307,7 @@ void Update()

public static SamplingNode Create(List<Callstack> callstacks)
{
SamplingNode node = new SamplingNode(null, null, 0, (uint)callstacks.Count);
SamplingNode node = new SamplingNode(null, null, (uint)callstacks.Count);
callstacks.ForEach(c => node.AppendMerge(c, 0, node));
node.Update();
node.Sort();
Expand Down
Loading

0 comments on commit 3ba5d4a

Please sign in to comment.