/// <summary> /// Enable the PMC machine wide, for ETW capture. /// </summary> /// <param name="profileSourceInfos">Collection of PMC to be enabled.</param> public static void SetPreciseMachineCounters(IReadOnlyCollection <ProfileSourceInfo> profileSourceInfos) { if (profileSourceInfos == null) { throw new ArgumentNullException(nameof(profileSourceInfos)); } if (!Kernel32.IsWindows8OrGreater()) { throw new InvalidOperationException("System Tracing is only supported on Windows 8 and above."); } var profileSourceIDs = new List <int>(); var profileSourceIntervals = new List <int>(); foreach (var psi in profileSourceInfos) { if (AvailablePreciseMachineCounters.TryGetValue(psi.Name, out var profInfo)) { profileSourceIDs.Add(profInfo.ID); profileSourceIntervals.Add(Math.Min(profInfo.MaxInterval, Math.Max(profInfo.MinInterval, psi.Interval))); } } if (profileSourceIDs.Count > 0) { // // FIXME: This function changes the -pmcsources intervals machine wide. // Maybe we should undo/revert these changes! // TraceEventProfileSources.Set(profileSourceIDs.ToArray(), profileSourceIntervals.ToArray()); } }
private static void SetPreciseMachineCounters(IEnumerable <ProviderInfo> providers) { if (IsWindows8OrGreater) { var availableCpuCounters = TraceEventProfileSources.GetInfo(); var profileSourceIDs = new List <int>(); var profileSourceIntervals = new List <int>(); foreach (var cpuInfo in providers.OfType <CpuCounterInfo>()) { if (availableCpuCounters.TryGetValue(cpuInfo.CounterName, out var profInfo)) { profileSourceIDs.Add(profInfo.ID); profileSourceIntervals.Add(Math.Min(profInfo.MaxInterval, Math.Max(profInfo.MinInterval, cpuInfo.Interval))); } } if (profileSourceIDs.Count > 0) { // // FIXME: This function changes the -pmcsources intervals machine wide. // Maybe we should undo/revert these changes! // TraceEventProfileSources.Set(profileSourceIDs.ToArray(), profileSourceIntervals.ToArray()); } } }
public IEnumerable <ValidationError> Validate(ValidationParameters validationParameters) { if (TraceEventSession.IsElevated() != true) { yield return(new ValidationError(true, "Must be elevated (Admin) to use Hardware Counters to use ETW Kernel Session.")); } var availableCpuCounters = TraceEventProfileSources.GetInfo(); foreach (var benchmark in validationParameters.Benchmarks .Where(benchmark => !benchmark.Job.Diagnoser.HardwareCounters.IsNullOrEmpty())) { foreach (var hardwareCounter in benchmark.Job.Diagnoser.HardwareCounters) { if (!EtwTranslations.TryGetValue(hardwareCounter, out var counterName)) { yield return(new ValidationError(true, $"Counter {hardwareCounter} not recognized. Please make sure that you are using counter supported on Windows", benchmark)); } if (!availableCpuCounters.ContainsKey(counterName)) { yield return(new ValidationError(true, $"The counter {counterName} is not available. Please make sure you are Windows 8+ without Hyper-V", benchmark)); } } } }
private static PreciseMachineCounter FromCounter(HardwareCounter counter) { var profileSource = TraceEventProfileSources.GetInfo()[EtwTranslations[counter]]; // it can't fail, diagnoser validates that first return(new PreciseMachineCounter(profileSource.ID, profileSource.Name, counter, profileSource.MinInterval)); // we want the smallest interval to have best possible precision }
public static int GetProfileSourceInfoId(string key) { if (IsWindowsPlatform && TraceEventProfileSources.GetInfo().TryGetValue(key, out ProfileSourceInfo profileSourceInfo)) { return(profileSourceInfo.ID); } else { return(-1); } }
public GenericPerformanceMonitorCounterDiscoverer() { _performanceMonitorCounter = new T(); if (TraceEventProfileSources.GetInfo().TryGetValue(_performanceMonitorCounter.Name, out ProfileSourceInfo profileSourceInfo)) { _pmcId = profileSourceInfo.ID; } else { _pmcId = -1; } }
public BasePerformanceMonitorCounter(IPerformanceMonitorCounter pmc) : base(pmc.Name, pmc.DisplayName, pmc.Unit) { _interval = pmc.Interval; if (TraceEventProfileSources.GetInfo().TryGetValue(Id, out ProfileSourceInfo profileSourceInfo)) { _profileSourceInfoID = profileSourceInfo.ID; } else { _profileSourceInfoID = -1; } }
protected override PmcStats GetInitializedStats(Benchmark benchmark) { var stats = new PmcStats(benchmark.Job.Diagnoser.HardwareCounters); var counters = stats.Counters.Values; TraceEventProfileSources.Set( // it's a must have to get the events enabled!! counters.Select(counter => counter.ProfileSourceId).ToArray(), counters.Select(counter => counter.Interval).ToArray()); return(stats); }
protected override PmcStats GetInitializedStats(DiagnoserActionParameters parameters) { var stats = new PmcStats(parameters.Config.GetHardwareCounters().ToArray()); var counters = stats.Counters.Values; TraceEventProfileSources.Set( // it's a must have to get the events enabled!! counters.Select(counter => counter.ProfileSourceId).ToArray(), counters.Select(counter => counter.Interval).ToArray()); return(stats); }
public InstructionsRetiredMetricDiscoverer() { ProfileSourceInfo info; if (TraceEventProfileSources.GetInfo().TryGetValue(CounterName, out info)) { _profileSource = info.ID; } else { _profileSource = -1; } }
private static void PrintAvailableProfileSources() { var availableProfileSources = TraceEventProfileSources.GetInfo(); foreach (var kvp in availableProfileSources) { Debug.WriteLine(""); Debug.WriteLine($"Profile name: {kvp.Key}"); Debug.WriteLine($" ID : {kvp.Value.ID}"); Debug.WriteLine($" Interval : {kvp.Value.Interval}"); Debug.WriteLine($" MaxInterval : {kvp.Value.MaxInterval}"); Debug.WriteLine($" MinInterval : {kvp.Value.MinInterval}"); Debug.WriteLine(""); } }
public static IEnumerable <ValidationError> Validate(ValidationParameters validationParameters, bool mandatory) { if (!RuntimeInformation.IsWindows()) { yield return(new ValidationError(true, "Hardware Counters and EtwProfiler are supported only on Windows")); yield break; } if (!validationParameters.Config.GetHardwareCounters().Any() && mandatory) { yield return(new ValidationError(true, "No Hardware Counters defined, probably a bug")); yield break; } if (TraceEventSession.IsElevated() != true) { yield return(new ValidationError(true, "Must be elevated (Admin) to use ETW Kernel Session (required for Hardware Counters and EtwProfiler).")); } var availableCpuCounters = TraceEventProfileSources.GetInfo(); foreach (var hardwareCounter in validationParameters.Config.GetHardwareCounters()) { if (!EtwTranslations.TryGetValue(hardwareCounter, out var counterName)) { yield return(new ValidationError(true, $"Counter {hardwareCounter} not recognized. Please make sure that you are using counter available on your machine. You can get the list of available counters by running `tracelog.exe -profilesources Help`")); } if (!availableCpuCounters.ContainsKey(counterName)) { yield return(new ValidationError(true, $"The counter {counterName} is not available. Please make sure you are Windows 8+ without Hyper-V")); } } foreach (var benchmark in validationParameters.Benchmarks) { if (benchmark.Job.Infrastructure.HasValue(InfrastructureMode.ToolchainCharacteristic) && (benchmark.Job.Infrastructure.Toolchain is InProcessToolchain || benchmark.Job.Infrastructure.Toolchain is InProcessEmitToolchain)) { yield return(new ValidationError(true, "Hardware Counters are not supported for InProcessToolchain.", benchmark)); } } }
private void DoCpuCountersListClick(object sender, RoutedEventArgs e) { var cpuCounterSpecs = new List <string>(); var cpuCounters = TraceEventProfileSources.GetInfo(); foreach (var cpuCounter in cpuCounters.Values) { var defaultCount = Math.Max(100000, cpuCounter.MinInterval); if (cpuCounter.Name == "Timer") { defaultCount = 10000; } var cpuCounterSpec = cpuCounter.Name + ":" + defaultCount.ToString(); cpuCounterSpecs.Add(cpuCounterSpec); } CpuCountersListBox.ItemsSource = cpuCounterSpecs; CpuCountersPopup.IsOpen = true; }
protected override PmcStats GetInitializedStats(DiagnoserActionParameters parameters) { var stats = new PmcStats(parameters.Config.GetHardwareCounters().ToArray(), FromCounter); var counters = stats.Counters.Values; try { TraceEventProfileSources.Set( // it's a must have to get the events enabled!! counters.Select(counter => counter.ProfileSourceId).ToArray(), counters.Select(counter => counter.Interval).ToArray()); } catch (System.Runtime.InteropServices.COMException ex) when(ex.Message.StartsWith("The WMI data block or event notification has already been enabled")) { // previous run was interrupted by ctrl+c and never stopped } return(stats); }
private static void PrintAvailableProfileSources() { var availableProfileSources = TraceEventProfileSources.GetInfo(); var cpuCounterIds = new List <int>(); var cpuCounterIntervals = new List <int>(); var sb = new StringBuilder(); foreach (var kvp in availableProfileSources) { sb.AppendLine(); sb.AppendLine($"Profile name: {kvp.Key}"); sb.AppendLine($" ID : {kvp.Value.ID}"); sb.AppendLine($" Interval : {kvp.Value.Interval}"); sb.AppendLine($" MaxInterval : {kvp.Value.MaxInterval}"); sb.AppendLine($" MinInterval : {kvp.Value.MinInterval}"); sb.AppendLine(); } WriteDebugLine(sb.ToString()); }
static Helper() { AvailablePreciseMachineCounters = TraceEventProfileSources.GetInfo(); CanEnableKernelProvider = TraceEventSession.IsElevated() == true; }
internal static PreciseMachineCounter FromCounter(HardwareCounter counter, Func <ProfileSourceInfo, int> intervalSelector) { var profileSource = TraceEventProfileSources.GetInfo()[EtwTranslations[counter]]; // it can't fail, diagnoser validates that first return(new PreciseMachineCounter(profileSource.ID, profileSource.Name, counter, intervalSelector(profileSource))); }
internal static void Enable(IEnumerable <PreciseMachineCounter> counters) { TraceEventProfileSources.Set( // it's a must have to get the events enabled!! counters.Select(counter => counter.ProfileSourceId).ToArray(), counters.Select(counter => counter.Interval).ToArray()); }
public static string Start(string etlPath, IEnumerable <ProviderInfo> providerInfo, int bufferSizeMB = 64) { EnsureUnloadHandlerRegistered(); var userSessionName = "xunit.performance.logger." + Guid.NewGuid().ToString(); Sessions sessions = new Sessions(); sessions.UserFileName = Path.ChangeExtension(etlPath, ".user.etl"); sessions.KernelFileName = Path.ChangeExtension(etlPath, ".kernel.etl"); sessions.MergedFileName = etlPath; var mergedProviderInfo = ProviderInfo.Merge(providerInfo); try { sessions.UserSession = new TraceEventSession(userSessionName, sessions.UserFileName); sessions.UserSession.BufferSizeMB = bufferSizeMB; var availableCpuCounters = TraceEventProfileSources.GetInfo(); var cpuCounterIds = new List <int>(); var cpuCounterIntervals = new List <int>(); foreach (var cpuInfo in mergedProviderInfo.OfType <CpuCounterInfo>()) { ProfileSourceInfo profInfo; if (availableCpuCounters.TryGetValue(cpuInfo.CounterName, out profInfo)) { cpuCounterIds.Add(profInfo.ID); cpuCounterIntervals.Add(Math.Min(profInfo.MaxInterval, Math.Max(profInfo.MinInterval, cpuInfo.Interval))); } } if (cpuCounterIds.Count > 0) { TraceEventProfileSources.Set(cpuCounterIds.ToArray(), cpuCounterIntervals.ToArray()); } var kernelInfo = mergedProviderInfo.OfType <KernelProviderInfo>().FirstOrDefault(); if (kernelInfo != null && NeedSeparateKernelSession(kernelInfo.Keywords)) { sessions.KernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, sessions.KernelFileName); sessions.KernelSession.BufferSizeMB = bufferSizeMB; } else { sessions.KernelFileName = sessions.UserFileName; sessions.KernelSession = sessions.UserSession; } if (kernelInfo != null) { var kernelKeywords = (KernelTraceEventParser.Keywords)kernelInfo.Keywords; var kernelStackKeywords = (KernelTraceEventParser.Keywords)kernelInfo.StackKeywords; sessions.KernelSession.EnableKernelProvider(kernelKeywords, kernelStackKeywords); } foreach (var userInfo in mergedProviderInfo.OfType <UserProviderInfo>()) { sessions.UserSession.EnableProvider(userInfo.ProviderGuid, userInfo.Level, userInfo.Keywords); } s_sessions[userSessionName] = sessions; } catch { sessions.Close(); throw; } return(userSessionName); }