зеркало из https://github.com/microsoft/BPerf.git
This commit is contained in:
Родитель
39ca5dcf4d
Коммит
6ef9e375c2
|
@ -3,90 +3,12 @@
|
|||
|
||||
namespace Microsoft.BPerf.StackAggregation
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.BPerf.ModuleInformation.Abstractions;
|
||||
using Microsoft.BPerf.SymbolicInformation.Interfaces;
|
||||
using Microsoft.Diagnostics.Symbols;
|
||||
using Microsoft.Diagnostics.Tracing.Stacks;
|
||||
|
||||
public sealed class GenericStackSource : StackSource
|
||||
public abstract class GenericStackSource : StackSource
|
||||
{
|
||||
private readonly List<StackInfo> stacks;
|
||||
|
||||
private readonly List<Frame> frames;
|
||||
|
||||
private readonly List<string> pseudoFrames;
|
||||
|
||||
private readonly int pseudoFramesStartOffset;
|
||||
|
||||
private readonly List<StackSourceSample> samples;
|
||||
|
||||
private readonly IInstructionPointerToSymbolicNameProvider eipToNameProvider;
|
||||
|
||||
private readonly Action<Action<StackSourceSample>> indirectCallback;
|
||||
|
||||
public GenericStackSource(IStackSamplesProvider samplesProvider, IInstructionPointerToSymbolicNameProvider eipToNameProvider, Action<Action<StackSourceSample>> indirectCallback)
|
||||
{
|
||||
this.stacks = samplesProvider.Stacks;
|
||||
this.frames = samplesProvider.Frames;
|
||||
this.pseudoFrames = samplesProvider.PseudoFrames;
|
||||
this.pseudoFramesStartOffset = samplesProvider.PseudoFramesStartOffset;
|
||||
this.samples = samplesProvider.Samples;
|
||||
this.SampleTimeRelativeMSecLimit = samplesProvider.MaxTimeRelativeMSec;
|
||||
|
||||
this.eipToNameProvider = eipToNameProvider;
|
||||
this.indirectCallback = indirectCallback;
|
||||
}
|
||||
|
||||
public override int CallStackIndexLimit => this.stacks.Count;
|
||||
|
||||
public override int CallFrameIndexLimit => this.frames.Count + (int)StackSourceFrameIndex.Start;
|
||||
|
||||
public override int SampleIndexLimit => this.samples.Count;
|
||||
|
||||
public override double SampleTimeRelativeMSecLimit { get; }
|
||||
|
||||
public override void ForEach(Action<StackSourceSample> callback)
|
||||
{
|
||||
StackInformationAbstractionsEventSource.Logger.BeginForEachSample();
|
||||
|
||||
this.indirectCallback(callback);
|
||||
|
||||
StackInformationAbstractionsEventSource.Logger.EndForEachSample();
|
||||
}
|
||||
|
||||
public override StackSourceCallStackIndex GetCallerIndex(StackSourceCallStackIndex callStackIndex)
|
||||
{
|
||||
return (StackSourceCallStackIndex)this.stacks[(int)callStackIndex].CallerID;
|
||||
}
|
||||
|
||||
public override StackSourceFrameIndex GetFrameIndex(StackSourceCallStackIndex callStackIndex)
|
||||
{
|
||||
return (StackSourceFrameIndex)this.stacks[(int)callStackIndex].FrameID;
|
||||
}
|
||||
|
||||
public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
|
||||
{
|
||||
var frame = this.frames[(int)frameIndex];
|
||||
|
||||
if ((int)frameIndex < this.pseudoFramesStartOffset)
|
||||
{
|
||||
return this.eipToNameProvider.GetSymbolicName(frame.ProcessId, frame.InstructionPointer);
|
||||
}
|
||||
|
||||
return this.pseudoFrames[(int)frame.ProcessId];
|
||||
}
|
||||
|
||||
public override StackSourceSample GetSampleByIndex(StackSourceSampleIndex sampleIndex)
|
||||
{
|
||||
return this.samples[(int)sampleIndex];
|
||||
}
|
||||
|
||||
public ValueTask<SourceLocation> GetSourceLocation(StackSourceFrameIndex frameIndex)
|
||||
{
|
||||
var frame = this.frames[(int)frameIndex];
|
||||
return this.eipToNameProvider.GetSourceLocation(frame.ProcessId, frame.InstructionPointer);
|
||||
}
|
||||
public abstract ValueTask<SourceLocation> GetSourceLocation(StackSourceFrameIndex frameIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
@ -8,11 +8,11 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.BPerf.ModuleInformation.Abstractions\Microsoft.BPerf.ModuleInformation.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.BPerf.SymbolicInformation.Interfaces\Microsoft.BPerf.SymbolicInformation.Interfaces.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Diagnostics.Tracing.Stacks\Microsoft.Diagnostics.Tracing.Stacks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.26" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\SourceLink.targets" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
@ -13,6 +13,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.26" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\SourceLink.targets" />
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.BPerf.StackInformation.Etw
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.BPerf.StackAggregation;
|
||||
using Microsoft.Diagnostics.Symbols;
|
||||
using Microsoft.Diagnostics.Tracing.Stacks;
|
||||
|
||||
internal sealed class SourceAwareStackSource : GenericStackSource
|
||||
{
|
||||
private readonly StackSource inner;
|
||||
|
||||
public SourceAwareStackSource(StackSource inner)
|
||||
{
|
||||
this.inner = inner;
|
||||
}
|
||||
|
||||
public override StackSource BaseStackSource => this.inner.BaseStackSource;
|
||||
|
||||
public override int CallStackIndexLimit => this.inner.CallStackIndexLimit;
|
||||
|
||||
public override int CallFrameIndexLimit => this.inner.CallFrameIndexLimit;
|
||||
|
||||
public override bool SamplesImmutable => this.inner.SamplesImmutable;
|
||||
|
||||
public override int SampleIndexLimit => this.inner.SampleIndexLimit;
|
||||
|
||||
public override double SampleTimeRelativeMSecLimit => this.inner.SampleTimeRelativeMSecLimit;
|
||||
|
||||
public override int ScenarioCount => this.inner.ScenarioCount;
|
||||
|
||||
public override float? SamplingRate => this.inner.SamplingRate;
|
||||
|
||||
public override bool IsGraphSource => this.inner.IsGraphSource;
|
||||
|
||||
public override bool OnlyManagedCodeStacks => this.inner.OnlyManagedCodeStacks;
|
||||
|
||||
public override void ParallelForEach(Action<StackSourceSample> callback, int desiredParallelism = 0)
|
||||
{
|
||||
this.inner.ParallelForEach(callback, desiredParallelism);
|
||||
}
|
||||
|
||||
public override void GetReferences(StackSourceSampleIndex nodeIndex, RefDirection direction, Action<StackSourceSampleIndex> callback)
|
||||
{
|
||||
this.inner.GetReferences(nodeIndex, direction, callback);
|
||||
}
|
||||
|
||||
public override int GetNumberOfFoldedFrames(StackSourceCallStackIndex callStackIndex)
|
||||
{
|
||||
return this.inner.GetNumberOfFoldedFrames(callStackIndex);
|
||||
}
|
||||
|
||||
public override StackSourceSample GetSampleByIndex(StackSourceSampleIndex sampleIndex)
|
||||
{
|
||||
return this.inner.GetSampleByIndex(sampleIndex);
|
||||
}
|
||||
|
||||
public override StackSourceCallStackIndex GetCallerIndex(StackSourceCallStackIndex callStackIndex)
|
||||
{
|
||||
return this.inner.GetCallerIndex(callStackIndex);
|
||||
}
|
||||
|
||||
public override StackSourceFrameIndex GetFrameIndex(StackSourceCallStackIndex callStackIndex)
|
||||
{
|
||||
return this.inner.GetFrameIndex(callStackIndex);
|
||||
}
|
||||
|
||||
public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
|
||||
{
|
||||
return this.inner.GetFrameName(frameIndex, verboseName);
|
||||
}
|
||||
|
||||
public override void ForEach(Action<StackSourceSample> callback)
|
||||
{
|
||||
this.inner.ForEach(callback);
|
||||
}
|
||||
|
||||
public override ValueTask<SourceLocation> GetSourceLocation(StackSourceFrameIndex frameIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.BPerf.StackInformation.Etw
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.BPerf.StackAggregation;
|
||||
using Microsoft.Diagnostics.Tracing.Etlx;
|
||||
using Microsoft.Diagnostics.Tracing.Stacks;
|
||||
|
||||
public sealed class TraceLogEtwDeserializer
|
||||
{
|
||||
public TraceLogEtwDeserializer(string etlFileName)
|
||||
{
|
||||
var traceLog = new TraceLog(TraceLog.CreateFromEventTraceLogFile(etlFileName));
|
||||
this.StackSource = new SourceAwareStackSource(new TraceEventStackSource(traceLog.Events));
|
||||
this.EventStats = new Dictionary<int, TraceEventCounts>(traceLog.Stats.Count);
|
||||
this.TraceProcesses = traceLog.Processes;
|
||||
|
||||
int i = 0;
|
||||
foreach (var eventStat in traceLog.Stats)
|
||||
{
|
||||
this.EventStats.Add(i, eventStat);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<int, TraceEventCounts> EventStats { get; }
|
||||
|
||||
public TraceProcesses TraceProcesses { get; }
|
||||
|
||||
public GenericStackSource StackSource { get; }
|
||||
}
|
||||
}
|
|
@ -5,20 +5,14 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using global::Diagnostics.Tracing.StackSources;
|
||||
using Microsoft.BPerf.ModuleInformation.Abstractions;
|
||||
using Microsoft.BPerf.StackAggregation;
|
||||
using Microsoft.BPerf.StackInformation.Etw;
|
||||
using Microsoft.BPerf.SymbolicInformation.ProgramDatabase;
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
using Microsoft.Diagnostics.Tracing.Stacks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public sealed class CallTreeData : ICallTreeData
|
||||
{
|
||||
|
@ -32,11 +26,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private readonly object lockobj = new object();
|
||||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerInformationProvider;
|
||||
|
||||
private readonly EtwDeserializer deserializer;
|
||||
private readonly GenericStackSource stackSource;
|
||||
|
||||
private readonly StackViewerModel model;
|
||||
|
||||
|
@ -44,11 +34,9 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private CallTree callTree;
|
||||
|
||||
public CallTreeData(ISymbolServerArtifactRetriever symbolServerArtifactRetriever, ISourceServerAuthorizationInformationProvider sourceServerInformationProvider, EtwDeserializer deserializer, StackViewerModel model)
|
||||
public CallTreeData(GenericStackSource stackSource, StackViewerModel model)
|
||||
{
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.sourceServerInformationProvider = sourceServerInformationProvider;
|
||||
this.deserializer = deserializer;
|
||||
this.stackSource = stackSource;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
@ -63,21 +51,19 @@ namespace Microsoft.BPerf.StackViewer
|
|||
CallTreeDataEventSource.Log.NodeCacheHit(name);
|
||||
return new TreeNode(this.nodeNameCache[name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var node in this.callTree.ByID)
|
||||
{
|
||||
if (node.Name == name)
|
||||
{
|
||||
this.nodeNameCache.Add(name, node);
|
||||
CallTreeDataEventSource.Log.NodeCacheMisss(name);
|
||||
return new TreeNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
CallTreeDataEventSource.Log.NodeCacheNotFound(name);
|
||||
return null;
|
||||
foreach (var node in this.callTree.ByID)
|
||||
{
|
||||
if (node.Name == name)
|
||||
{
|
||||
this.nodeNameCache.Add(name, node);
|
||||
CallTreeDataEventSource.Log.NodeCacheMisss(name);
|
||||
return new TreeNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
CallTreeDataEventSource.Log.NodeCacheNotFound(name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,52 +199,32 @@ namespace Microsoft.BPerf.StackViewer
|
|||
if (sourceLocation != null)
|
||||
{
|
||||
var buildTimePath = sourceLocation.SourceFile.BuildTimeFilePath;
|
||||
var srcSrvString = sourceLocation.SourceFile.SrcSrvString;
|
||||
var srcSrvString = sourceLocation.SourceFile.GetSourceFile();
|
||||
|
||||
// TODO: src srv stream needs more support, also talk to VS folks and see how they do SourceLink
|
||||
if (srcSrvString != null)
|
||||
var lines = File.ReadAllLines(sourceLocation.SourceFile.GetSourceFile());
|
||||
|
||||
var list = new List<LineInformation>();
|
||||
|
||||
int i = 1;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var doc = JObject.Parse(srcSrvString)["documents"].ToObject<Dictionary<string, string>>().First();
|
||||
string urlPath = doc.Value.Replace("*", buildTimePath.Replace(doc.Key.Replace("*", string.Empty), string.Empty));
|
||||
|
||||
var client = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false })
|
||||
var li = new LineInformation
|
||||
{
|
||||
BaseAddress = new Uri(urlPath)
|
||||
Line = line,
|
||||
LineNumber = i++
|
||||
};
|
||||
|
||||
var authorizationHeader = this.sourceServerInformationProvider.GetAuthorizationHeaderValue(urlPath);
|
||||
if (!string.IsNullOrEmpty(authorizationHeader))
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
|
||||
}
|
||||
|
||||
var result = await client.GetStringAsync(urlPath);
|
||||
|
||||
var lines = result.Split('\n');
|
||||
|
||||
var list = new List<LineInformation>();
|
||||
|
||||
int i = 1;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var li = new LineInformation
|
||||
{
|
||||
Line = line,
|
||||
LineNumber = i++
|
||||
};
|
||||
|
||||
list.Add(li);
|
||||
}
|
||||
|
||||
var si = new SourceInformation
|
||||
{
|
||||
BuildTimeFilePath = buildTimePath,
|
||||
Lines = list,
|
||||
Summary = new List<LineInformation> { new LineInformation { LineNumber = sourceLocation.LineNumber, Metric = retVal[index] } }
|
||||
};
|
||||
|
||||
return si;
|
||||
list.Add(li);
|
||||
}
|
||||
|
||||
var si = new SourceInformation
|
||||
{
|
||||
BuildTimeFilePath = buildTimePath,
|
||||
Lines = list,
|
||||
Summary = new List<LineInformation> { new LineInformation { LineNumber = sourceLocation.LineNumber, Metric = retVal[index] } }
|
||||
};
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
return null; // TODO: need to implement the local case i.e. this is the build machine
|
||||
|
@ -283,38 +249,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
return;
|
||||
}
|
||||
|
||||
var pid = uint.Parse(this.model.Pid);
|
||||
var symbolProvider = new TracePdbSymbolReaderProvider(this.symbolServerArtifactRetriever);
|
||||
|
||||
if (this.deserializer.ImageLoadMap.TryGetValue(pid, out var images))
|
||||
{
|
||||
int total = 0;
|
||||
int count = 0;
|
||||
foreach (var image in images)
|
||||
{
|
||||
count++;
|
||||
total += image.InstructionPointers.Count;
|
||||
}
|
||||
|
||||
var pdbLookupImageList = new List<ImageInfo>(count);
|
||||
var ftotal = (float)total;
|
||||
foreach (var image in images)
|
||||
{
|
||||
if ((image.InstructionPointers.Count / ftotal) * 100 >= 1.0)
|
||||
{
|
||||
pdbLookupImageList.Add(image);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var image in pdbLookupImageList)
|
||||
{
|
||||
if (this.deserializer.ImageToDebugInfoMap.TryGetValue(new ProcessImageId(pid, image.Begin), out var dbgId))
|
||||
{
|
||||
await symbolProvider.GetSymbolReader(image.FilePath, dbgId.Signature, dbgId.Age, dbgId.Filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var filterParams = new FilterParams
|
||||
{
|
||||
StartTimeRelativeMSec = this.model.Start,
|
||||
|
@ -327,34 +261,10 @@ namespace Microsoft.BPerf.StackViewer
|
|||
Name = "NoName"
|
||||
};
|
||||
|
||||
var stackType = int.Parse(this.model.StackType);
|
||||
if (!this.deserializer.EventStacks.TryGetValue(stackType, out var stackEventType))
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
var instructionPointerDecoder = new InstructionPointerToSymbolicNameProvider(this.deserializer, symbolProvider);
|
||||
var stackSource = new GenericStackSource(
|
||||
this.deserializer,
|
||||
instructionPointerDecoder,
|
||||
callback =>
|
||||
{
|
||||
var sampleSource = this.deserializer;
|
||||
var samples = stackEventType.SampleIndices;
|
||||
foreach (var s in samples)
|
||||
{
|
||||
var sample = sampleSource.Samples[s];
|
||||
if (sample.Scenario == pid)
|
||||
{
|
||||
callback(sampleSource.Samples[s]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var ss = new FilterStackSource(filterParams, stackSource, ScalingPolicyKind.TimeMetric);
|
||||
var ss = new FilterStackSource(filterParams, this.stackSource, ScalingPolicyKind.TimeMetric);
|
||||
|
||||
double startTimeRelativeMsec = double.TryParse(filterParams.StartTimeRelativeMSec, out startTimeRelativeMsec) ? Math.Max(startTimeRelativeMsec, 0.0) : 0.0;
|
||||
double endTimeRelativeMsec = double.TryParse(filterParams.EndTimeRelativeMSec, out endTimeRelativeMsec) ? Math.Min(endTimeRelativeMsec, ss.SampleTimeRelativeMSecLimit) : ss.SampleTimeRelativeMSecLimit;
|
||||
double endTimeRelativeMsec = double.TryParse(filterParams.EndTimeRelativeMSec, out endTimeRelativeMsec) ? Math.Min(endTimeRelativeMsec, this.stackSource.SampleTimeRelativeMSecLimit) : this.stackSource.SampleTimeRelativeMSecLimit;
|
||||
|
||||
this.callTree = new CallTree(ScalingPolicyKind.TimeMetric);
|
||||
this.callTree.TimeHistogramController = new TimeHistogramController(this.callTree, startTimeRelativeMsec, endTimeRelativeMsec);
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.BPerf.StackInformation.Abstractions;
|
||||
using Microsoft.BPerf.StackInformation.Etw;
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
|
||||
public sealed class DeserializedData : IDeserializedData
|
||||
{
|
||||
|
@ -20,10 +19,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private readonly FileLocationType locationType;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider;
|
||||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly string tempDownloadLocation;
|
||||
|
||||
private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
||||
|
@ -36,14 +31,12 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private int initialized;
|
||||
|
||||
private EtwDeserializer deserializer;
|
||||
private TraceLogEtwDeserializer deserializer;
|
||||
|
||||
public DeserializedData(string uri, FileLocationType locationType, ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, string tempDownloadLocation)
|
||||
public DeserializedData(string uri, FileLocationType locationType, string tempDownloadLocation)
|
||||
{
|
||||
this.uri = uri;
|
||||
this.locationType = locationType;
|
||||
this.sourceServerAuthorizationInformationProvider = sourceServerAuthorizationInformationProvider;
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.tempDownloadLocation = tempDownloadLocation;
|
||||
}
|
||||
|
||||
|
@ -61,7 +54,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
if (!this.callTreeDataCache.TryGetValue(model, out var value))
|
||||
{
|
||||
value = new CallTreeData(this.symbolServerArtifactRetriever, this.sourceServerAuthorizationInformationProvider, this.deserializer, model);
|
||||
value = new CallTreeData(this.deserializer.StackSource, model);
|
||||
this.callTreeDataCache.Add(model, value);
|
||||
}
|
||||
|
||||
|
@ -116,24 +109,16 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
var filePath = this.locationType == FileLocationType.Url ? await this.DownloadFile(this.uri) : this.uri;
|
||||
|
||||
this.deserializer = new EtwDeserializer(filePath);
|
||||
this.deserializer = new TraceLogEtwDeserializer(filePath);
|
||||
|
||||
foreach (var pair in this.deserializer.EventStacks)
|
||||
foreach (var pair in this.deserializer.EventStats)
|
||||
{
|
||||
this.stackEventTypes.Add(new StackEventTypeInfo(pair.Key, pair.Value.EventName, pair.Value.SampleIndices.Count));
|
||||
this.stackEventTypes.Add(new StackEventTypeInfo(pair.Key, pair.Value.EventName, pair.Value.Count, pair.Value.StackCount));
|
||||
}
|
||||
|
||||
foreach (var pair in this.deserializer.ImageLoadMap.OrderBy(t => t.Value.Sum(y => y.InstructionPointers.Count)).Reverse())
|
||||
foreach (var pair in this.deserializer.TraceProcesses.OrderByDescending(t => t.CPUMSec))
|
||||
{
|
||||
long total = 0;
|
||||
foreach (var image in pair.Value)
|
||||
{
|
||||
total += image.InstructionPointers.Count;
|
||||
}
|
||||
|
||||
this.processList.Add(this.deserializer.ProcessIdToNameMap.TryGetValue(pair.Key, out var processName)
|
||||
? new ProcessInfo(processName, pair.Key, total)
|
||||
: new ProcessInfo($"Process {pair.Key}", pair.Key, total));
|
||||
this.processList.Add(new ProcessInfo(pair.Name + $"({pair.ProcessID})", (int)pair.ProcessIndex, pair.CPUMSec));
|
||||
}
|
||||
|
||||
this.initialized = 1;
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
using System;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
@ -13,19 +12,13 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
private readonly CallTreeDataCache cache;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider;
|
||||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly ICacheExpirationTimeProvider cacheExpirationTimeProvider;
|
||||
|
||||
private readonly IOptions<StackViewerSettings> stackViewerSettings;
|
||||
|
||||
public DeserializedDataCache(CallTreeDataCache cache, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider, ICacheExpirationTimeProvider cacheExpirationTimeProvider, IOptions<StackViewerSettings> stackViewerSettings)
|
||||
public DeserializedDataCache(CallTreeDataCache cache, ICacheExpirationTimeProvider cacheExpirationTimeProvider, IOptions<StackViewerSettings> stackViewerSettings)
|
||||
{
|
||||
this.cache = cache;
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.sourceServerAuthorizationInformationProvider = sourceServerAuthorizationInformationProvider;
|
||||
this.cacheExpirationTimeProvider = cacheExpirationTimeProvider;
|
||||
this.stackViewerSettings = stackViewerSettings;
|
||||
}
|
||||
|
@ -42,7 +35,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
if (!this.cache.TryGetValue(model.Filename, out IDeserializedData data))
|
||||
{
|
||||
var cacheEntryOptions = new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.NeverRemove).RegisterPostEvictionCallback(callback: EvictionCallback, state: this).SetSlidingExpiration(this.cacheExpirationTimeProvider.Expiration);
|
||||
data = new DeserializedData(model.Filename, model.LocationType, this.sourceServerAuthorizationInformationProvider, this.symbolServerArtifactRetriever, this.stackViewerSettings.Value.TemporaryDataFileDownloadLocation);
|
||||
data = new DeserializedData(model.Filename, model.LocationType, this.stackViewerSettings.Value.TemporaryDataFileDownloadLocation);
|
||||
this.cache.Set(model.Filename, data, cacheEntryOptions);
|
||||
CacheMonitorEventSource.Logger.CacheEntryAdded(Environment.MachineName, model.Filename);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<ProjectReference Include="..\Microsoft.BPerf.SymbolicInformation.Interfaces\Microsoft.BPerf.SymbolicInformation.Interfaces.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.BPerf.SymbolicInformation.ProgramDatabase\Microsoft.BPerf.SymbolicInformation.ProgramDatabase.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.BPerf.SymbolServer.Interfaces\Microsoft.BPerf.SymbolServer.Interfaces.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Diagnostics.Tracing.Stacks\Microsoft.Diagnostics.Tracing.Stacks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
namespace Microsoft.BPerf.StackViewer
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
public class ProcessListViewModel : StackViewerModel
|
||||
|
|
|
@ -5,17 +5,17 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
public sealed class ProcessInfo
|
||||
{
|
||||
public ProcessInfo(string processName, uint pid, long samplesCount)
|
||||
public ProcessInfo(string processName, int pid, float cpumsec)
|
||||
{
|
||||
this.Name = processName;
|
||||
this.Id = pid;
|
||||
this.SamplesCount = samplesCount;
|
||||
this.CPUMSec = cpumsec;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public uint Id { get; }
|
||||
public int Id { get; }
|
||||
|
||||
public long SamplesCount { get; }
|
||||
public float CPUMSec { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
public sealed class StackEventTypeInfo
|
||||
{
|
||||
public StackEventTypeInfo(int eventId, string eventName, int eventCount)
|
||||
public StackEventTypeInfo(int eventId, string eventName, int eventCount, int stackEventCount)
|
||||
{
|
||||
this.EventId = eventId;
|
||||
this.EventName = eventName;
|
||||
this.EventCount = eventCount;
|
||||
this.StackEventCount = stackEventCount;
|
||||
}
|
||||
|
||||
public int EventId { get; }
|
||||
|
@ -17,5 +18,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
public string EventName { get; }
|
||||
|
||||
public int EventCount { get; }
|
||||
|
||||
public int StackEventCount { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
@foreach (var process in this.Model.ProcessList)
|
||||
{
|
||||
<tr>
|
||||
<td><a href="/ui/stackviewer/summary?filename=@this.Model.Filename&stacktype=@this.Model.StackType&pid=@process.Id">@process.Name (@process.Id)</a></td>
|
||||
<td>@process.SamplesCount</td>
|
||||
<td><a href="/ui/stackviewer/summary?filename=@this.Model.Filename&stacktype=@this.Model.StackType&pid=@process.Id">@process.Name</a></td>
|
||||
<td>@process.CPUMSec</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
|
Загрузка…
Ссылка в новой задаче