public override void ApplyFilter(DirectXCanvas canvas, ThreadScroll scroll, HashSet <EventDescription> descriptions) { Filter = EventFilter.Create(EventData, descriptions); if (Filter != null) { DynamicMesh builder = canvas.CreateMesh(); foreach (EventFrame frame in EventData.Events) { Interval interval = scroll.TimeToUnit(frame.Header); builder.AddRect(new Rect(interval.Left, 0.0, interval.Width, 1.0), FilterFrameColor); } foreach (Entry entry in Filter.Entries) { Interval interval = scroll.TimeToUnit(entry); builder.AddRect(new Rect(interval.Left, 0.0, interval.Width, 1.0), FilterEntryColor); } SharpDX.Utilities.Dispose(ref FilterMesh); FilterMesh = builder.Freeze(canvas.RenderDevice); //if (FilterMesh != null) // FilterMesh.UseAlpha = true; } else { SharpDX.Utilities.Dispose(ref FilterMesh); } }
public override void Export(Point point, ThreadScroll scroll) { EventNode node = null; EventFrame frame = null; int level = FindNode(point, scroll, out frame, out node); if (EventNodeSelected != null) { ITick tick = scroll.PixelToTime(point.X); if (frame == null) { frame = FindFrame(tick); } if (frame != null) { EventNodeSelected(this, frame, node); } if (node != null) { var option = new ArchiveOption { Mode = ArchiveMode.Save, Sources = new List <IArchiveSource> { new NodeArchiveSource(node) }, ArchiveType = ArchiveSourceType.Node }; ArchiveFactory.Instance().Archive(ref option); } } }
public override void Render(DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box) { Matrix world = GetWorldMatrix(scroll); if (layer == DirectXCanvas.Layer.Background) { ChartMeshes?.ForEach(mesh => { mesh.WorldTransform = world; canvas.Draw(mesh); }); } }
public override void OnMouseMove(Point point, ThreadScroll scroll) { EventNode node = null; EventFrame frame = null; int level = FindNode(point, scroll, out frame, out node); if (level != -1) { Interval interval = scroll.TimeToPixel(node.Entry); Rect rect = new Rect(interval.Left, Offset + level * RenderParams.BaseHeight + RenderParams.BaseMargin, interval.Width, RenderParams.BaseHeight - RenderParams.BaseMargin); EventNodeHover?.Invoke(point, rect, this, node); } else { EventNodeHover?.Invoke(point, new Rect(), this, null); } }
public int FindNode(Point point, ThreadScroll scroll, out EventFrame eventFrame, out EventNode eventNode) { ITick tick = scroll.PixelToTime(point.X); int index = Data.Utils.BinarySearchExactIndex(EventData.Events, tick.Start); EventFrame resultFrame = null; EventNode resultNode = null; int resultLevel = -1; if (index >= 0) { EventFrame frame = EventData.Events[index]; int desiredLevel = (int)(point.Y / RenderParams.BaseHeight); GetTree(frame).ForEachChild((node, level) => { if (level > desiredLevel || resultFrame != null) { return(false); } if (level == desiredLevel) { EventNode evNode = (node as EventNode); if (evNode.Entry.Intersect(tick.Start)) { resultFrame = frame; resultNode = evNode; resultLevel = level; return(false); } } return(true); }); } eventFrame = resultFrame; eventNode = resultNode; return(resultLevel); }
public override void BuildMesh(DirectXCanvas canvas, ThreadScroll scroll) { if (Timestamps.Count < 2) { return; } DirectX.ComplexDynamicMesh builder = new ComplexDynamicMesh(canvas, DIPSpltCount); List <Color[]> entryColors = new List <Color[]>(); foreach (Entry entry in Entries) { Color color = entry.Fill; Color gradColor = DirectX.Utils.MultiplyColor(color, GradientColorShade); //entryColors.Add(new Color[] { leftColor, rightColor, rightColor, leftColor }); entryColors.Add(new Color[] { color, color, gradColor, gradColor }); } double left = scroll.TimeToUnit(Timestamps[0]); for (int i = 0; i < Timestamps.Count - 1; ++i) { double right = scroll.TimeToUnit(Timestamps[i + 1]); double bottom = 0.0; for (int entryIndex = 0; entryIndex < Entries.Count; ++entryIndex) { double val = Entries[entryIndex].Values[i]; double height = val / MaxValue; if (height > 0.0) { builder.AddRect(new Rect(left, 1.0 - bottom - height, right - left, height), entryColors[entryIndex]); bottom += height; } } left = right; } ChartMeshes = builder.Freeze(canvas.RenderDevice); }
public override void OnMouseClick(Point point, ThreadScroll scroll) { EventNode node = null; EventFrame frame = null; int level = FindNode(point, scroll, out frame, out node); if (EventNodeSelected != null) { ITick tick = scroll.PixelToTime(point.X); if (frame == null) { frame = FindFrame(tick); } if (frame != null) { EventNodeSelected(this, frame, node); } } }
void BuildMeshNode(DirectX.ComplexDynamicMesh builder, ThreadScroll scroll, EventNode node, int level) { if (level == MaxDepth) { return; } Interval interval = scroll.TimeToUnit(node.Entry); double y = (double)level / MaxDepth; double h = 1.0 / MaxDepth; Color nodeColor = node.Description.ForceColor; Color nodeGradColor = DirectX.Utils.MultiplyColor(nodeColor, NodeGradientShade); builder.AddRect(new Rect(interval.Left, y, interval.Width, h), new Color[] { nodeColor, nodeGradColor, nodeGradColor, nodeColor }); foreach (EventNode child in node.Children) { BuildMeshNode(builder, scroll, child, level + 1); } }
public override void Render(DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box) { if (layer == DirectXCanvas.Layer.Foreground) { Matrix world = GetWorldMatrix(scroll, false); //Matrix world = new Matrix(scroll.Zoom, 0.0, 0.0, 1.0, -scroll.ViewUnit.Left * scroll.Zoom, 0.0); if (BackgroundMeshTris != null) { BackgroundMeshTris.WorldTransform = world; canvas.Draw(BackgroundMeshTris); } if (BackgroundMeshLines != null) { BackgroundMeshLines.WorldTransform = world; canvas.Draw(BackgroundMeshLines); } double yOffset = Offset + (Height - RenderParams.BaseHeight) * 0.5; FrameList focusThread = Group.FocusThread; if (focusThread != null) { Data.Utils.ForEachInsideInterval(focusThread.Events, scroll.ViewTime, (frame, index) => { Interval interval = scroll.TimeToPixel(frame); String text = String.Format(System.Globalization.CultureInfo.InvariantCulture, "Frame {0} ({1:0.0}ms)", (uint)index, frame.Duration); // 2 times to emulate "bold" for (int i = 0; i < 2; ++i) { canvas.Text.Draw(new Point(interval.Left, yOffset), text, TextColor, TextAlignment.Center, interval.Width); } }); } } }
public override void BuildMesh(DirectX.DirectXCanvas canvas, ThreadScroll scroll) { DirectX.DynamicMesh builder = canvas.CreateMesh(); builder.Geometry = DirectX.Mesh.GeometryType.Lines; double headerHeight = 1.0; //(Height - RenderParams.BaseMargin) / scroll.Height; // Adding Tickers if (EnableTickers) { for (double tick = Math.Ceiling(scroll.TimeSlice.StartMS); tick < Math.Ceiling(scroll.TimeSlice.FinishMS); tick += 1.0) { double longX = scroll.TimeToUnit(new Tick { Start = Durable.MsToTick(tick) }); builder.AddLine(new Point(longX, headerHeight * 3.0 / 6.0), new Point(longX, headerHeight), TickColor); double medX = scroll.TimeToUnit(new Tick { Start = Durable.MsToTick(tick + 0.5) }); builder.AddLine(new Point(medX, headerHeight * 4.0 / 6.0), new Point(medX, headerHeight), TickColor); for (double miniTick = 0.1; miniTick < 1.0; miniTick += 0.1) { double miniX = scroll.TimeToUnit(new Tick { Start = Durable.MsToTick(tick + miniTick) }); builder.AddLine(new Point(miniX, headerHeight * 5.0 / 6.0), new Point(miniX, headerHeight), TickColor); } } } BackgroundMeshLines = builder.Freeze(canvas.RenderDevice); DirectX.DynamicMesh builderHeader = canvas.CreateMesh(); builderHeader.AddRect(new Rect(0.0, 0.0, 1.0, headerHeight), new Color[] { GradientTop, GradientTop, GradientBottom, GradientBottom }); BackgroundMeshTris = builderHeader.Freeze(canvas.RenderDevice); }
public override void OnMouseMove(Point point, ThreadScroll scroll) { ITick tick = scroll.PixelToTime(point.X); int index = Data.Utils.BinarySearchClosestIndex(Timestamps, tick.Start); if (0 <= index && index + 1 < Timestamps.Count) { double leftPx = scroll.TimeToPixel(Timestamps[index]); double rightPx = scroll.TimeToPixel(Timestamps[index + 1]); Rect rect = new Rect(leftPx, Offset + RenderParams.BaseMargin, rightPx - leftPx, Height - RenderParams.BaseMargin); List <double> values = new List <double>(); for (int entryIndex = 0; entryIndex < Entries.Count; ++entryIndex) { values.Add(Entries[entryIndex].Values[index]); } StringBuilder builder = new StringBuilder(); builder.AppendFormat("NumCores [{0}]: ", values.Sum()); for (int i = 0; i < values.Count; ++i) { if (i != 0) { builder.Append("+"); } builder.Append(values[i]); //builder.AppendFormat("{0}({1})", values[i], entries[i].Name); } ChartHover?.Invoke(point, rect, builder.ToString()); } else { ChartHover?.Invoke(point, new Rect(), null); } }
public override void ApplyFilter(DirectXCanvas canvas, ThreadScroll scroll, HashSet <EventDescription> descriptions) { throw new NotImplementedException(); }
public override void Export(Point point, ThreadScroll scroll) { }
public override void BuildMesh(DirectX.DirectXCanvas canvas, ThreadScroll scroll) { SetBusy(true); UpdateDepth(); // Build Mesh DirectX.ComplexDynamicMesh builder = new ComplexDynamicMesh(canvas, DIPSplitCount); DirectX.ComplexDynamicMesh syncBuilder = new ComplexDynamicMesh(canvas, DIPSplitCount); DirectX.ComplexDynamicMesh syncWorkBuilder = new ComplexDynamicMesh(canvas, DIPSplitCount); if (EventData.Sync != null && EventData.Sync != null) { SyncReason stallReason = SyncReason.SyncReasonCount; long stallFrom = 0; int frameSyncIndex = 0; for (int i = 0; i < EventData.Sync.Count; i++) { SyncInterval sync = EventData.Sync[i]; Interval workInterval = scroll.TimeToUnit(sync); //draw work int coreColorIndex = (int)sync.Core; coreColorIndex = coreColorIndex % WorkColors.Length; Color WorkColor = WorkColors[coreColorIndex]; syncWorkBuilder.AddRect(new Rect(workInterval.Left, 0, workInterval.Right - workInterval.Left, SyncLineHeight / Height), WorkColor); if (i == 0) { stallReason = sync.Reason; stallFrom = sync.Finish; continue; } long workStart = sync.Start; long workFinish = sync.Finish; while (frameSyncIndex < EventData.Events.Count && EventData.Events[frameSyncIndex].Finish < stallFrom) { ++frameSyncIndex; } //Ignoring all the waiting outside marked work to simplify the view if (frameSyncIndex < EventData.Events.Count && EventData.Events[frameSyncIndex].Start <= workStart) { Durable syncDurable = new Durable(stallFrom, workStart); Interval syncInterval = scroll.TimeToUnit(syncDurable); double syncWidth = syncInterval.Right - syncInterval.Left; if (syncWidth > 0) { // draw sleep Color waitColor = IsUserInitiatedSync(stallReason) ? SynchronizationColorUser : SynchronizationColor; syncBuilder.AddRect(new Rect(syncInterval.Left, 0, syncWidth, SyncLineHeight / Height), waitColor); } } stallFrom = workFinish; stallReason = sync.Reason; } } foreach (EventFrame frame in EventData.Events) { Durable interval = Group.Board.TimeSlice; EventTree tree = GetTree(frame); foreach (EventNode node in tree.Children) { BuildMeshNode(builder, scroll, node, 0); } } Blocks = builder.Freeze(canvas.RenderDevice); SyncMesh = syncBuilder.Freeze(canvas.RenderDevice); SyncWorkMesh = syncWorkBuilder.Freeze(canvas.RenderDevice); CallstackMeshPolys = canvas.CreateMesh(); CallstackMeshPolys.Projection = Mesh.ProjectionType.Pixel; CallstackMeshLines = canvas.CreateMesh(); CallstackMeshLines.Geometry = Mesh.GeometryType.Lines; CallstackMeshLines.Projection = Mesh.ProjectionType.Pixel; SetBusy(false); }
public override void OnMouseClick(Point point, ThreadScroll scroll) { }
public override void ApplyFilter(DirectXCanvas canvas, ThreadScroll scroll, HashSet <EventDescription> descriptions) { }
public override void Render(DirectX.DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box) { if (!IsVisible) { return; } Matrix world = GetWorldMatrix(scroll); if (layer == DirectXCanvas.Layer.Background) { Draw(canvas, Blocks, world); if (FilterMesh != null) { FilterMesh.WorldTransform = world; canvas.Draw(FilterMesh); } if (scroll.SyncDraw == ThreadScroll.SyncDrawType.Wait) { Draw(canvas, SyncMesh, world); } if (SyncWorkMesh != null && scroll.SyncDraw == ThreadScroll.SyncDrawType.Work) { Draw(canvas, SyncWorkMesh, world); } Data.Utils.ForEachInsideInterval(EventData.Events, scroll.ViewTime, frame => { GetTree(frame).ForEachChild((node, level) => { Entry entry = (node as EventNode).Entry; Interval intervalPx = scroll.TimeToPixel(entry); if (intervalPx.Width < TextDrawThreshold || intervalPx.Right < 0.0 || level >= MaxDepth) { return(false); } if (intervalPx.Left < 0.0) { intervalPx.Width += intervalPx.Left; intervalPx.Left = 0.0; } double lum = Data.Utils.GetLuminance(entry.Description.ForceColor); Color color = lum < Data.Utils.LuminanceThreshold ? Colors.White : Colors.Black; canvas.Text.Draw(new Point(intervalPx.Left + TextDrawOffset, Offset + level * RenderParams.BaseHeight), entry.Description.Name, color, TextAlignment.Left, intervalPx.Width - TextDrawOffset); return(true); }); }); } if (layer == DirectXCanvas.Layer.Foreground) { if (CallstackMeshPolys != null && CallstackMeshLines != null && (scroll.DrawCallstacks != 0 || scroll.DrawDataTags)) { double width = CallstackMarkerRadius; double height = CallstackMarkerRadius; double offset = Offset + RenderParams.BaseHeight * 0.5; if (scroll.DrawCallstacks != 0) { Data.Utils.ForEachInsideInterval(EventData.Callstacks, scroll.ViewTime, callstack => { if ((callstack.Reason & scroll.DrawCallstacks) != 0) { double center = scroll.TimeToPixel(callstack); Point[] points = new Point[] { new Point(center - width, offset), new Point(center, offset - height), new Point(center + width, offset), new Point(center, offset + height) }; Color fillColor = (callstack.Reason == CallStackReason.AutoSample) ? CallstackColor : SystemCallstackColor; Color strokeColor = Colors.Black; CallstackMeshPolys.AddRect(points, fillColor); CallstackMeshLines.AddRect(points, strokeColor); } }); } if (scroll.DrawDataTags && EventData.TagsPack != null) { Data.Utils.ForEachInsideInterval(EventData.TagsPack.Tags, scroll.ViewTime, tag => { double center = scroll.TimeToPixel(tag); Point[] points = new Point[] { new Point(center - width, Offset), new Point(center + width, Offset), new Point(center, offset) }; CallstackMeshPolys.AddTri(points, CallstackColor); CallstackMeshLines.AddTri(points, Colors.Black); }); } CallstackMeshPolys.Update(canvas.RenderDevice); CallstackMeshLines.Update(canvas.RenderDevice); canvas.Draw(CallstackMeshPolys); canvas.Draw(CallstackMeshLines); } } }
public abstract void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext);
public Matrix GetWorldMatrix(ThreadScroll scroll, bool useMargin = true) { return(new Matrix(scroll.Zoom, 0.0, 0.0, (Height - (useMargin ? 2.0 * RenderParams.BaseMargin : 0.0)) / scroll.Height, -(scroll.ViewUnit.Left * scroll.Zoom), (Offset + (useMargin ? 1.0 * RenderParams.BaseMargin : 0.0)) / scroll.Height)); }
public override void Export(Point point, ThreadScroll scroll) { //throw new NotImplementedException(); }
public abstract void Render(DirectX.DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box);
public abstract void ApplyFilter(DirectX.DirectXCanvas canvas, ThreadScroll scroll, HashSet <EventDescription> descriptions);
public abstract void OnMouseClick(Point point, ThreadScroll scroll);
public override void OnMouseClick(Point point, ThreadScroll scroll) { //throw new NotImplementedException(); }
public override void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext) { }
public override void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext) { //throw new NotImplementedException(); }
public abstract void BuildMesh(DirectX.DirectXCanvas canvas, ThreadScroll scroll);
public abstract void Export(Point point, ThreadScroll scroll);
public override void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext) { EventNode node = null; EventFrame frame = null; ITick tick = scroll.PixelToTime(point.X); if (FindNode(point, scroll, out frame, out node) != -1) { dataContext.Add(node); } // show current sync info if (EventData.Sync != null && EventData.Sync != null) { int index = Data.Utils.BinarySearchClosestIndex(EventData.Sync, tick.Start); if (index != -1) { bool insideWaitInterval = false; WaitInterval interval = new WaitInterval() { Start = EventData.Sync[index].Finish, Reason = EventData.Sync[index].Reason }; if (index + 1 < EventData.Sync.Count) { if (EventData.Sync[index].Finish < tick.Start && tick.Start < EventData.Sync[index + 1].Start) { UInt64 threadId = EventData.Sync[index].NewThreadId; ThreadDescription threadDesc = null; Group.Board.ThreadDescriptions.TryGetValue(threadId, out threadDesc); interval.newThreadDesc = threadDesc; interval.newThreadId = threadId; interval.Finish = EventData.Sync[index + 1].Start; dataContext.Add(interval); insideWaitInterval = true; } } if (!insideWaitInterval) { interval.Reason = SyncReason.SyncReasonActive; interval.Start = EventData.Sync[index].Start; interval.Finish = EventData.Sync[index].Finish; interval.core = (byte)EventData.Sync[index].Core; dataContext.Add(interval); } } } if (node != null) { // build all intervals inside selected node int from = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Start); int to = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Finish); if (from >= 0 && to >= from) { IntPair[] waitInfo = new IntPair[(int)SyncReason.SyncReasonCount]; for (int index = from; index <= to; ++index) { SyncReason reason = frame.Synchronization[index].Reason; int reasonIndex = (int)reason; long idleStart = frame.Synchronization[index].Finish; long idleFinish = (index + 1 < frame.Synchronization.Count) ? frame.Synchronization[index + 1].Start : frame.Finish; if (idleStart > node.Entry.Finish) { continue; } long idleStartClamped = Math.Max(idleStart, node.Entry.Start); long idleFinishClamped = Math.Min(idleFinish, node.Entry.Finish); long durationInTicks = idleFinishClamped - idleStartClamped; waitInfo[reasonIndex].duration += durationInTicks; waitInfo[reasonIndex].count++; } NodeWaitIntervalList intervals = new NodeWaitIntervalList(); for (int i = 0; i < waitInfo.Length; i++) { if (waitInfo[i].count > 0) { NodeWaitInterval interval = new NodeWaitInterval() { Start = 0, Finish = waitInfo[i].duration, Reason = (SyncReason)i, NodeInterval = node.Entry, Count = waitInfo[i].count }; intervals.Add(interval); } } intervals.Sort((a, b) => { return(Comparer <long> .Default.Compare(b.Finish, a.Finish)); }); if (intervals.Count > 0) { dataContext.Add(intervals); } } } // FindNode if (EventData.Callstacks != null && scroll.DrawCallstacks != 0) { int startIndex = Data.Utils.BinarySearchClosestIndex(EventData.Callstacks, tick.Start); for (int i = startIndex; (i <= startIndex + 1) && (i < EventData.Callstacks.Count) && (i != -1); ++i) { double pixelPos = scroll.TimeToPixel(EventData.Callstacks[i]); if (Math.Abs(pixelPos - point.X) < CallstackMarkerRadius * 1.2 && (EventData.Callstacks[i].Reason & scroll.DrawCallstacks) != 0) { dataContext.Add(EventData.Callstacks[i]); break; } } } }