Repository: microsoft/garnet
File: libs/server/Metrics/Latency/GarnetLatencyMetricsSession.cs (C#)

Code before:
using System.Runtime.CompilerServices;
using Garnet.common;

namespace Garnet.server
{
    /// <summary>
    /// Latency metrics emitted from RespServerSession
    /// </summary>
    internal sealed class GarnetLatencyMetricsSession
    {
        readonly GarnetServerMonitor monitor;
        static readonly LatencyMetricsType[] defaultLatencyTypes = Enum.GetValues<LatencyMetricsType>();
        int Version => (int)(monitor.monitor_iterations % 2);
        public int PriorVersion => 1 - Version;
        public LatencyMetricsEntrySession[] metrics;

        public GarnetLatencyMetricsSession(GarnetServerMonitor monitor)
        {
            this.monitor = monitor;
            Init();
        }

        public void Return()
        {
            foreach (var cmd in defaultLatencyTypes)
            {
                metrics[(int)cmd].latency[0].Return();
                metrics[(int)cmd].latency[1].Return();
            }
            metrics = null;
        }

        private void Init()
        {
            metrics = new LatencyMetricsEntrySession[defaultLatencyTypes.Length];
            foreach (var cmd in defaultLatencyTypes)
                metrics[(int)cmd] = new LatencyMetricsEntrySession();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Start(LatencyMetricsType cmd)
        {
            int idx = (int)cmd;
            metrics[idx].Start();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void StopAndSwitch(LatencyMetricsType oldCmd, LatencyMetricsType newCmd)
        {
            int old_idx = (int)oldCmd;
            int new_idx = (int)newCmd;

Review comment (performance):
Better to have a Return method within LatencyMetricsEntrySession that this method can invoke to maintain the abstraction? That way, invoking Return will become obvious to any future users of LatencyMetricsEntrySession.

Code after:
using System.Runtime.CompilerServices;
using Garnet.common;

namespace Garnet.server
{
    /// <summary>
    /// Latency metrics emitted from RespServerSession
    /// </summary>
    internal sealed class GarnetLatencyMetricsSession
    {
        readonly GarnetServerMonitor monitor;
        static readonly LatencyMetricsType[] defaultLatencyTypes = Enum.GetValues<LatencyMetricsType>();
        int Version => (int)(monitor.monitor_iterations % 2);
        public int PriorVersion => 1 - Version;
        public LatencyMetricsEntrySession[] metrics;

        public GarnetLatencyMetricsSession(GarnetServerMonitor monitor)
        {
            this.monitor = monitor;
            Init();
        }

        public void Return()
        {
            foreach (var cmd in defaultLatencyTypes)
            {
                metrics[(int)cmd].Return();
            }
            metrics = null;
        }

        private void Init()
        {
            metrics = new LatencyMetricsEntrySession[defaultLatencyTypes.Length];
            foreach (var cmd in defaultLatencyTypes)
                metrics[(int)cmd] = new LatencyMetricsEntrySession();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Start(LatencyMetricsType cmd)
        {
            int idx = (int)cmd;
            metrics[idx].Start();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void StopAndSwitch(LatencyMetricsType oldCmd, LatencyMetricsType newCmd)
        {
            int old_idx = (int)oldCmd;
            int new_idx = (int)newCmd;
            metrics[new_idx].startTimestamp = metrics[old_idx].startTimestamp;