public static string ToNamespace(this ProfilerResult profilerResult) { #region Argument exception if (profilerResult == null) { throw new ArgumentNullException("profilerResult"); } #endregion return("{0}".FormatWith(ProfilerResult.Namespace)); }
public static DataTable ToCachesReadTable(this ProfilerResult profilerResult) { var cachesRead = new DataTable("CachesRead", "Common"); #region Columns cachesRead.Columns.Add("CacheType", typeof(string)); cachesRead.Columns.Add("CacheSubType", typeof(string)); #endregion if (profilerResult.ExecuteForPrepare) { return(cachesRead); } #region Calculation var getDataFromCache = profilerResult.Values .Where((e) => e.EventClass == TraceEventClass.GetDataFromCache); var measureGroupCache = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromMeasureGroupCache) .Select((e) => new { CacheType = "Measure Group Cache", CacheSubType = e.TextData }); var persistedCache = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromPersistedCache) .Select((e) => new { CacheType = "Persisted Cache", CacheSubType = e.TextData }); var flatCache = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromFlatCache) .Select((e) => new { CacheType = "Flat Cache", CacheSubType = e.TextData }); var calculationCacheGlobalScope = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromCalculationCache && e.TextData.Equals("Global Scope", StringComparison.InvariantCultureIgnoreCase)) .Select((e) => new { CacheType = "Calculation Cache - Global Scope", CacheSubType = e.TextData }); var calculationCacheSessionScope = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromCalculationCache && e.TextData.Equals("Session Scope", StringComparison.InvariantCultureIgnoreCase)) .Select((e) => new { CacheType = "Calculation Cache - Session Scope", CacheSubType = e.TextData }); var calculationCacheQueryScope = getDataFromCache .Where((e) => e.EventSubclass == TraceEventSubclass.GetDataFromCalculationCache && e.TextData.Equals("Query Scope", StringComparison.InvariantCultureIgnoreCase)) .Select((e) => new { CacheType = "Calculation Cache - Query Scope", CacheSubType = e.TextData }); #endregion #region Insert rows var caches = measureGroupCache .Concat(persistedCache) .Concat(flatCache) .Concat(calculationCacheGlobalScope) .Concat(calculationCacheSessionScope) .Concat(calculationCacheQueryScope); foreach (var item in caches) { cachesRead.Rows.Add(item.CacheType, item.CacheSubType); } #endregion return(cachesRead); }
public static DataTable ToAggregationsReadTable(this ProfilerResult profilerResult) { var aggregationsRead = new DataTable("AggregationsRead", "Common"); #region Columns aggregationsRead.Columns.Add("CubeID", typeof(string)); aggregationsRead.Columns.Add("MeasureGroupID", typeof(string)); aggregationsRead.Columns.Add("PartitionID", typeof(string)); aggregationsRead.Columns.Add("AggregationID", typeof(string)); aggregationsRead.Columns.Add("AggregationName", typeof(string)); aggregationsRead.Columns.Add("AggregationHit", typeof(int)); aggregationsRead.Columns.Add("AggregationDuration", typeof(TimeSpan)); aggregationsRead.Columns.Add("AggregationDurationRatio", typeof(double)); #endregion if (profilerResult.ExecuteForPrepare) { return(aggregationsRead); } #region Calculation var progressReportEndQueryAggregationEvents = profilerResult.Values.FilterProgressReportEndQueryAggregationEvents().ToList(); var durationTotal = progressReportEndQueryAggregationEvents.Sum((e) => e.Duration); var progressReportEndQueryAggregation = progressReportEndQueryAggregationEvents.GroupBy((e) => e.ObjectID) .Select((g) => { var fe = g.First(); var values = fe.ObjectPath.Split('.'); return(new { CubeID = values[2], MeasureGroupID = values[3], PartitionID = values[4], AggregationID = values[5], AggregationName = fe.ObjectName, AggregationHit = g.Count(), AggregationDuration = g.Sum((e) => e.Duration), AggregationDurationRatio = durationTotal == 0L ? 0D : ((double)(g.Sum((e) => e.Duration) * 100D) / (double)durationTotal) }); }); #endregion #region Insert rows foreach (var item in progressReportEndQueryAggregation) { aggregationsRead.Rows.Add( item.CubeID, item.MeasureGroupID, item.PartitionID, item.AggregationID, item.AggregationName, item.AggregationHit, TimeSpan.FromMilliseconds(item.AggregationDuration), Math.Round(item.AggregationDurationRatio, 2) ); } #endregion return(aggregationsRead); }
public static DataTable ToEnginePerformanceTable(this ProfilerResult profilerResult) { var enginePerformance = new DataTable("EnginePerformance", "Common"); #region Columns enginePerformance.Columns.Add("QueryDuration", typeof(TimeSpan)); enginePerformance.Columns.Add("FormulaEngineDuration", typeof(TimeSpan)); enginePerformance.Columns.Add("StorageEngineDuration", typeof(TimeSpan)); enginePerformance.Columns.Add("QuerySubcubeExecutionsCacheData", typeof(int)); enginePerformance.Columns.Add("QuerySubcubeExecutionsNonCacheData", typeof(int)); enginePerformance.Columns.Add("CachesRead", typeof(int)); enginePerformance.Columns.Add("PartitionsRead", typeof(int)); enginePerformance.Columns.Add("PartitionsHit", typeof(int)); enginePerformance.Columns.Add("PartitionsDuration", typeof(TimeSpan)); enginePerformance.Columns.Add("AggregationsRead", typeof(int)); enginePerformance.Columns.Add("AggregationsHit", typeof(int)); enginePerformance.Columns.Add("AggregationsDuration", typeof(TimeSpan)); enginePerformance.Columns.Add("ResourceUsageReads", typeof(int)); enginePerformance.Columns.Add("ResourceUsageReadKB", typeof(long)); enginePerformance.Columns.Add("ResourceUsageWrites", typeof(int)); enginePerformance.Columns.Add("ResourceUsageWriteKB", typeof(long)); enginePerformance.Columns.Add("ResourceUsageCpuTimeMS", typeof(long)); enginePerformance.Columns.Add("ResourceUsageRowsScanned", typeof(int)); enginePerformance.Columns.Add("ResourceUsageRowsReturned", typeof(int)); #endregion if (profilerResult.ExecuteForPrepare) { return(enginePerformance); } #region Calculation #region QueryEnd events var queryEndEvents = profilerResult.Values.Where((e) => e.EventClass == TraceEventClass.QueryEnd); if (queryEndEvents.Count() != 1) { throw new ApplicationException("Invalid QueryEnd events count [{0}]".FormatWith(queryEndEvents.Count())); } #endregion var queryDuration = queryEndEvents.Single().Duration; #region QuerySubCube events var querySubCubeEvents = profilerResult.Values.Where((e) => e.EventClass == TraceEventClass.QuerySubcube); #endregion var storageEngineDuration = querySubCubeEvents.Sum((e) => e.Duration); if (storageEngineDuration > queryDuration) { storageEngineDuration = queryDuration; } var formulaEngineDuration = queryDuration - storageEngineDuration; var querySubcubeExecutionsCacheData = querySubCubeEvents.Count((e) => e.EventSubclass == TraceEventSubclass.CacheData); var querySubcubeExecutionsNonCacheData = querySubCubeEvents.Count((e) => e.EventSubclass == TraceEventSubclass.NonCacheData); #region ProgressReportEnd events var progressReportEndQueryPartitionEvents = profilerResult.Values.FilterProgressReportEndQueryPartitionEvents(); var progressReportEndQueryAggregationEvents = profilerResult.Values.FilterProgressReportEndQueryAggregationEvents(); #endregion var partitionsRead = progressReportEndQueryPartitionEvents.GroupBy((e) => e.ObjectID).Count(); var partitionsDuration = progressReportEndQueryPartitionEvents.Sum((e) => e.Duration); var partitionsHit = progressReportEndQueryPartitionEvents.Count(); var aggregationsRead = progressReportEndQueryAggregationEvents.GroupBy((e) => e.ObjectID).Count(); var aggregationsDuration = progressReportEndQueryAggregationEvents.Sum((e) => e.Duration); var aggregationsHit = progressReportEndQueryAggregationEvents.Count(); #region GetDataFromCache events var getDataFromCacheEvents = profilerResult.Values.Where((e) => e.EventClass == TraceEventClass.GetDataFromCache); #endregion var cachesRead = getDataFromCacheEvents.Count(); #region ResourceUsage events var resourceUsageEvents = profilerResult.Values.Where((e) => e.EventClass == TraceEventClass.ResourceUsage); if (resourceUsageEvents.Count() != 1) { throw new ApplicationException("Invalid ResourceUsage events count"); } #endregion var resourceUsage = resourceUsageEvents.Select((e) => { if (e.TextData == null) { throw new ApplicationException("Invalid ResourceUsage.TextData [null]"); } var values = e.TextData.Split('\n') .Select((v) => v.Split(',').Last().Trim()) .ToArray(); if (values.Length != 8) { throw new ApplicationException("Invalid ResourceUsage.TextData [{0}]".FormatWith(values.Length)); } return(new { ResourceUsageReads = int.Parse(values[0]), ResourceUsageReadKB = long.Parse(values[1]), ResourceUsageWrites = int.Parse(values[2]), ResourceUsageWriteKB = long.Parse(values[3]), ResourceUsageCpuTimeMS = long.Parse(values[4]), ResourceUsageRowsScanned = int.Parse(values[5]), ResourceUsageRowsReturned = int.Parse(values[6]), }); }) .Single(); #endregion #region Insert row enginePerformance.Rows.Add( TimeSpan.FromMilliseconds(queryDuration), TimeSpan.FromMilliseconds(formulaEngineDuration), TimeSpan.FromMilliseconds(storageEngineDuration), querySubcubeExecutionsCacheData, querySubcubeExecutionsNonCacheData, cachesRead, partitionsRead, partitionsHit, TimeSpan.FromMilliseconds(partitionsDuration), aggregationsRead, aggregationsHit, TimeSpan.FromMilliseconds(aggregationsDuration), resourceUsage.ResourceUsageReads, resourceUsage.ResourceUsageReadKB, resourceUsage.ResourceUsageWrites, resourceUsage.ResourceUsageWriteKB, resourceUsage.ResourceUsageCpuTimeMS, resourceUsage.ResourceUsageRowsScanned, resourceUsage.ResourceUsageRowsReturned ); #endregion return(enginePerformance); }
public static Task <ProfilerResult> StartAsync(ProcedureContext procedureContext, CollectorsSynchronizer collectorsSynchronizer, CancellationToken cancellationToken) { #region Argument exceptions if (procedureContext == null) { throw new ArgumentNullException("procedureContext"); } if (collectorsSynchronizer == null) { throw new ArgumentNullException("collectorsSynchronizer"); } if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } #endregion var started = new ManualResetEvent(false); var faulted = new ManualResetEvent(false); var traceTask = new Task <ProfilerResult>(() => { #region task var profilerResult = ProfilerResult.Create(procedureContext, collectorsSynchronizer); using (var server = new Server()) { server.Connect(procedureContext.ConnectionString); var trace = server.Traces.Find(ProfilerCollector.TraceId); if (trace == null) { throw new ApplicationException("Trace not found [{0}]".FormatWith(ProfilerCollector.TraceName)); } var onTraceEventException = default(Exception); #if ASQASSAS13 || ASQASSAS14 var clientActivityID = procedureContext.ClientActivityID.ToString("D"); #endif trace.OnEvent += (s, e) => { #region OnEvent try { #if ASQASSAS11 || ASQASSAS12 var found = e.ConnectionID == procedureContext.CurrentConnectionID; #else var found = clientActivityID.Equals(e[TraceColumn.ActivityID], StringComparison.OrdinalIgnoreCase); #endif if (found) { profilerResult.Add(e); } } catch (Exception ex) { if (onTraceEventException == null) { onTraceEventException = ex; } profilerResult.CollectCompleted.Set(); } #endregion }; trace.Start(); while (!trace.IsStarted) { Thread.Sleep(50); } started.Set(); cancellationToken.WaitHandle.WaitOne(Timeout.Infinite); WaitHandle.WaitAny(new [] { profilerResult.CollectCompleted, procedureContext.CancellationToken.WaitHandle }); if (onTraceEventException != null) { throw onTraceEventException; } if (procedureContext.ExecutionMode == ProcedureExecutionMode.Batch && !procedureContext.IsCancellationRequested) { profilerResult.FlushBatch(completion: true); } trace.Stop(); } return(profilerResult); #endregion }, cancellationToken, TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning); traceTask.ContinueWith((previousTask) => faulted.Set(), TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnFaulted); traceTask.ContinueWith((previousTask) => collectorsSynchronizer.CompleteAdding(), TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.ExecuteSynchronously); traceTask.Start(); WaitHandle.WaitAny(new [] { started, faulted }); return(traceTask); }