示例#1
0
        /// <summary>
        /// Resets all frame statistics. Run exactly once per frame.
        /// </summary>
        public void NewFrame()
        {
            // Reset the counters we keep track of
            for (int i = 0; i < ActiveCounters.Length; ++i)
            {
                if (ActiveCounters[i])
                {
                    long count = FrameStatistics.COUNTERS[i];
                    var  type  = (StatisticsCounterType)i;

                    if (!globalStatistics.TryGetValue(type, out var global))
                    {
                        globalStatistics[type] = global = GlobalStatistics.Get <long>(threadName, type.ToString());
                    }

                    global.Value = count;
                    currentFrame.Counts[type]    = count;
                    currentFrame.FramesPerSecond = Clock.FramesPerSecond;

                    FrameStatistics.COUNTERS[i] = 0;
                }
            }

            if (PendingFrames.Count < max_pending_frames - 1)
            {
                PendingFrames.Enqueue(currentFrame);
                currentFrame = FramesPool.Get();
            }

            currentFrame.Clear();

            if (HandleGC)
            {
                for (int i = 0; i < lastAmountGarbageCollects.Length; ++i)
                {
                    int amountCollections = GC.CollectionCount(i);

                    if (lastAmountGarbageCollects[i] != amountCollections)
                    {
                        lastAmountGarbageCollects[i] = amountCollections;
                        currentFrame.GarbageCollections.Add(i);
                    }
                }
            }

            double dampRate = Math.Max(Clock.ElapsedFrameTime, 0) / 1000;

            averageFrameTime = Interpolation.Damp(averageFrameTime, Clock.ElapsedFrameTime, 0.01, dampRate);

            //check for dropped (stutter) frames
            traceCollector?.NewFrame(Clock.ElapsedFrameTime, Math.Max(10, Math.Max(1000 / Clock.MaximumUpdateHz, averageFrameTime) * 4));

            consumeStopwatchElapsedTime();
        }
示例#2
0
        public static void NewFrame()
        {
            if (Active != active)
            {
                active = Active;

                lastReport            = 0;
                framesSinceLastReport = 0;

                GlobalStatistics.Clear(group_name);
                collected_times.Clear();
            }

            if (!active)
            {
                return;
            }

            //reset frame totals
            current_collection_type_stack.Clear();
            consumeStopwatchElapsedTime();

            if (framesSinceLastReport > 0 && clock.CurrentTime - lastReport > 1000)
            {
                GlobalStatistics.Clear(group_name);

                int i = 0;

                foreach (var t in collected_times.OrderByDescending(t => t.Value.TotalMilliseconds).Take(5))
                {
                    string runCount = t.Value.Count / framesSinceLastReport > 1 ? $" ({t.Value.Count / framesSinceLastReport} instances)" : string.Empty;

                    GlobalStatistics.Get <string>(group_name, $"{++i}. {t.Key.Name}{runCount}").Value =
                        $"{t.Value.TotalMilliseconds / framesSinceLastReport:N1}ms";
                }

                collected_times.Clear();
                framesSinceLastReport = 0;
                lastReport            = clock.CurrentTime;
            }

            framesSinceLastReport++;
        }
        protected override void OnEventWritten(EventWrittenEventArgs data)
        {
            switch ((EventType)data.EventId)
            {
            case EventType.GCStart_V1 when data.Payload != null:
                // https://docs.microsoft.com/en-us/dotnet/framework/performance/garbage-collection-etw-events#gcstart_v1_event
                GlobalStatistics.Get <int>(statistics_grouping, $"Collections Gen{data.Payload[1]}").Value++;
                break;

            case EventType.GCHeapStats_V1 when data.Payload != null:
                // https://docs.microsoft.com/en-us/dotnet/framework/performance/garbage-collection-etw-events#gcheapstats_v1_event
                for (int i = 0; i <= 6; i += 2)
                {
                    addStatistic <ulong>($"Size Gen{i / 2}", data.Payload[i]);
                }

                addStatistic <ulong>("Finalization queue length", data.Payload[9]);
                addStatistic <uint>("Pinned objects", data.Payload[10]);
                break;
            }
        }
 private void addStatistic <T>(string name, object data)
 => GlobalStatistics.Get <T>(statistics_grouping, name).Value = (T)data;
        protected override void OnEventWritten(EventWrittenEventArgs data)
        {
            switch (data.EventSource.Name)
            {
            case source_arraypool:

                switch ((ArrayPoolEventType)data.EventId)
                {
                case ArrayPoolEventType.BufferAllocated:
                    statAllocated.Value++;
                    break;

                case ArrayPoolEventType.BufferRented:
                    statRented.Value++;
                    statInflight.Value++;
                    break;

                case ArrayPoolEventType.BufferReturned:
                    statReturned.Value++;

                    // the listener may have been started while buffers were already rented.
                    if (statInflight.Value > 0)
                    {
                        statInflight.Value--;
                    }
                    break;
                }

                break;

            case source_runtime:
                switch ((GCEventType)data.EventId)
                {
                case GCEventType.GCStart_V1 when data.Payload != null:
                    // https://docs.microsoft.com/en-us/dotnet/framework/performance/garbage-collection-etw-events#gcstart_v1_event
                    GlobalStatistics.Get <int>(gc_statistics_grouping, $"Collections Gen{data.Payload[1]}").Value++;
                    break;

                case GCEventType.GCHeapStats_V1 when data.Payload != null:
                    // https://docs.microsoft.com/en-us/dotnet/framework/performance/garbage-collection-etw-events#gcheapstats_v1_event
                    for (int i = 0; i <= 6; i += 2)
                    {
                        addStatistic <ulong>($"Size Gen{i / 2}", data.Payload[i]);
                    }

                    addStatistic <ulong>("Finalization queue length", data.Payload[9]);
                    addStatistic <uint>("Pinned objects", data.Payload[10]);
                    break;

                case GCEventType.GCAllocationTick_V2 when data.Payload != null:
                    string name = (string)data.Payload[5];
                    if (string.IsNullOrEmpty(name))
                    {
                        break;
                    }

                    var allocType = Type.GetType(name, false, false);
                    if (allocType == null)
                    {
                        break;
                    }

                    var finalizeMethod = allocType.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance);
                    Debug.Assert(finalizeMethod != null);         // All objects have this.

                    if (finalizeMethod.DeclaringType != typeof(object))
                    {
                        Logger.Log($"Allocated finalizable object: {name}", LoggingTarget.Performance);
                    }

                    break;

                case GCEventType.FinalizeObject when data.Payload != null:
                    if (data.Payload[0] == null)
                    {
                        break;
                    }

                    var type = getTypeFromHandle((IntPtr)data.Payload[0]);
                    if (type == null)
                    {
                        break;
                    }

                    Logger.Log($"Finalizing object: {type.ReadableName()}", LoggingTarget.Performance);

                    break;
                }

                break;
            }
        }