Ir para o conteúdo

Benchmark Notes — C# (Cross.Runtime.Bench.Csharp)

Correções Aplicadas

1. Warmup Insuficiente (CRÍTICO — Problema 1)

Sintoma: Todas as execuções apresentavam hasDrift: SuddenIncrease com magnitude +25% a +80%. Amostras finais sistematicamente mais lentas que as iniciais.

Causa raiz: O WarmupManager.ExecuteAdaptiveWarmup() podia declarar estabilidade após apenas 10-25 iterações, quando o JIT Tiered Compilation do .NET ainda não havia compilado Tier 1 (optimized). Background JIT ativo durante a medição causava drift.

Correção (WarmupManager.cs): - Adicionada constante MinWarmupBeforeStabilityCheck = 50 - A verificação de CV% só ocorre após 50 iterações mínimas - Isso garante que o JIT Tier 1 do .NET já compilou hot paths antes de verificar estabilidade - Compatível com o mesmo piso aplicado em Java e Node.js

2. CPU% Inválida (CRÍTICO — Problema 2)

Sintoma: cpu_cpuPercent retornava valores absurdos: 15.000% a 30.000%.

Causa raiz: O cálculo (cpuTotalDelta / wallClockMs) * 100 acumulava tempo CPU de múltiplas threads sem normalizar pelo número de cores. Em uma máquina de 16 cores, um benchmark single-thread reportava ~1600%.

Correção (BenchmarkRunner.cs e CpuMetricsCollector.cs): - Fórmula corrigida: cpuPercent = (userTimeMs + systemTimeMs) / (wallClockMs * ProcessorCount) * 100 - Produz 0-100% (single-core equivalent) - Max clamping alterado de ProcessorCount * 100 para 100.0 - Mesma fórmula aplicada em: - BenchmarkRunner.cs (cálculo principal) - CpuMetricsCollector.TakeSample() (coleta periódica) - CpuMetricsCollector.GetCpuUsagePercent() já estava correto

Como o Warmup Está Implementado

O warmup segue o padrão adaptativo (default) ou fixo:

Warmup Adaptativo (default)

  1. Executa a ação repetidamente com timer de alta precisão
  2. Após 50 iterações mínimas (MinWarmupBeforeStabilityCheck), inicia verificação
  3. A cada 5 iterações, calcula CV% das últimas N medições (janela = CvStabilityWindow)
  4. Se CV% < TargetCoefficientOfVariation (default 5%) por N verificações consecutivas → Para
  5. Caso contrário, continua até WarmupTimeSeconds (3s) ou WarmupIterations (100)

Warmup Fixo (AdaptiveWarmup = false)

  • Executa exatamente WarmupIterations vezes sem verificação de estabilidade

Configurações por Preset

Preset WarmupIterations WarmupTimeSeconds Target CV%
Default 100 3.0s 5%
Fast 10 1.0s N/A (fixo)
HighPrecision 200 10.0s 2%

Como CPU% É Calculada

cpuPercent = (cpuUserDelta + cpuSystemDelta) / (wallClockMs × ProcessorCount) × 100

Onde: - cpuUserDelta = Process.UserProcessorTime (delta ms) - cpuSystemDelta = Process.PrivilegedProcessorTime (delta ms) - wallClockMs = Stopwatch.GetTimestamp() delta convertido para ms - ProcessorCount = Environment.ProcessorCount - Resultado: 0-100% (normalizado para single-core equivalent)

Como as Estatísticas São Agregadas

  1. Coleta: N medições via Stopwatch.GetTimestamp() (nanosegundos)
  2. Filtragem de Outliers: IQR (default), MAD, ZScore, ou Grubbs
  3. Algoritmo de Welford: Cálculo numericamente estável de média e variância
  4. Variância amostral: Bessel correction (N-1 divisor)
  5. IC 95%: t-Student com df = N-1 (não z-score)
  6. Detecção de Anomalias: Mann-Kendall test para drift, análise de GC e CPU

Métricas Exportadas

  • Mean, Median, StdDev, Min, Max (ns e ms)
  • CV% (Coefficient of Variation)
  • IC 95% (Confidence Interval)
  • Throughput (ops/sec)
  • Outliers removidos + método