Supervise CPU/RAM/Disco como un profesional con Get‑Counter

¿Te fue útil?

Los problemas de rendimiento no se anuncian con cortesía. Aparecen como “la aplicación se siente lenta”, “RDP va con retraso”, “SQL está atascado” o mi favorito: “ayer iba bien”. Para cuando abres el Administrador de tareas, el pico ya se ha ido de la escena del crimen.

Get-Counter de PowerShell es tu cámara de vigilancia: siempre encendida, con marcas temporales, automatizable y útil como evidencia. Si aprendes a leer un puñado de contadores como un SRE lee gráficos, puedes separar la falta de CPU de la presión de memoria o la latencia de disco en minutos, no en horas de depuración basada en sensaciones.

Por qué Get‑Counter supera el clic y mirar

PerfMon está bien. El Administrador de tareas está bien. Pero “bien” no es lo que necesitas a las 02:13 cuando un servidor de archivos empieza a dar timeouts y tienes 15 minutos antes de que un VP encuentre tu número de teléfono.

Get-Counter gana porque es:

  • Automatizable: intervalos de muestreo repetibles, salida consistente, exportaciones sencillas.
  • Amigable para remoto: el mismo comando puede ejecutarse contra múltiples hosts.
  • Orientado a series temporales: puedes capturar un pico, no solo mirar un momento.
  • Composable: canalízalo, filtralo, agrégalo, prográmalo.

Además, no necesitas “recordar qué hiciste clic” durante un incidente. El propio comando es el registro.

Una regla práctica: deja de preguntar “¿está alta la CPU?” y comienza a preguntar “¿qué recurso es el reactivo limitante ahora?” CPU, memoria y disco son una pelea a tres bandas. Tu trabajo es identificar quién sostiene el cuchillo.

Broma #1: Si no estableces una línea base para tus contadores, cada gráfico es una “detección de anomalías” impulsada por pánico y café.

Datos e historia interesantes (que realmente ayudan)

  • Los contadores de rendimiento de Windows existen desde antes de PowerShell. Han estado presentes desde la era NT; PowerShell se volvió una forma cómoda de consultarlos sin la GUI.
  • PerfMon es solo un cliente. Los datos de los contadores vienen de proveedores (como PerfProc, PerfOS) e instrumentación dentro del SO y los controladores.
  • Las instancias pueden desaparecer. Los contadores de procesos usan instancias como chrome#3; cuando los procesos se reinician, los nombres de instancia pueden desplazarse, rompiendo automatizaciones ingenuas.
  • Algunos contadores “clásicos” engañan por omisión. La longitud de la cola de disco puede ser engañosa en pilas de almacenamiento modernas con caché y paralelismo; la latencia suele ser la verdad más fiable.
  • Los hipervisores cambiaron lo que significa “% CPU”. Ready time, stolen time y la planificación del host pueden causar lentitud incluso cuando la CPU del invitado parece moderada.
  • El tipo de contador importa. Algunos valores son tasas (por segundo), otros son contadores brutos, otros son fracciones; CookedValue es PowerShell haciendo la matemática por ti.
  • El intervalo de muestreo cambia la interpretación. Una muestra de 1 segundo captura picos; una de 30 segundos los oculta. Eso no es filosofía: es matemática.
  • Muchos contadores son calculados, no medidos. Por ejemplo, “% Processor Time” se deriva de deltas de tiempo de inactividad, no es un medidor mágico de CPU.
  • La consulta remota usa RPC/Infraestructura Perf. Puede bloquearse por políticas de firewall, endurecimiento de servicios o permisos incluso cuando WinRM funciona.

Un modelo mental práctico: CPU vs RAM vs Disco

Cuellos de botella de CPU: problemas rápidos, síntomas obvios, “soluciones” engañosas

Los problemas de CPU suelen aparecer como % Processor Time alto, largas colas de ejecución y respuesta lenta en todas partes. Pero la CPU también es donde la gente se queda atrapada: ven 80–90% de CPU y piden más núcleos inmediatamente. A veces eso es correcto. A menudo es un parche que cubre código malo, un escaneo antivirus agresivo, un formateador de logs descontrolado o un bucle busy-wait que debería dormir.

La virtualización también oculta pecados. Un invitado puede parecer “bien” mientras el host está sobresuscrito y tu VM espera ser planificada. Si solo mides dentro del invitado, puedes pasar por alto el problema real por completo.

Cuellos de botella de memoria: el desastre a cámara lenta

La presión de memoria es el tipo de problema que arruina el día lentamente y luego de repente. Windows intentará mantener las cosas funcionando recortando working sets y haciendo paging. Para cuando los usuarios se quejan, a menudo ya estás en la “cinta de muerte del paging”: el disco empieza a thrash, la CPU sube, y todo se vuelve inconsistente. Por eso el diagnóstico de memoria debe incluir tanto la memoria disponible como la actividad de paginación.

Cuellos de botella de disco: la latencia es la métrica reina

Los problemas de disco rara vez se tratan de techos de rendimiento; se tratan de latencia y latencia de cola. Un sistema de almacenamiento puede alcanzar MB/s impresionantes y aun así arruinar tu app si las lecturas tardan 50–200 ms durante ráfagas. Para la mayoría de cargas Windows, si puedes responder “¿cuál es la latencia de lectura/escritura ahora?” ya estás a medio camino de la solución.

Y sí, “disco” puede significar un SAN, un volumen en la nube, Storage Spaces, un caché de controlador RAID, un driver filtro antivirus o una tormenta de metadatos del sistema de archivos. Los contadores no nombrarán automáticamente al villano, pero te dirán si debes perseguir E/S, CPU o memoria primero.

Una cita que debería estar en cada runbook de on-call, porque te mantiene honesto:

“La esperanza no es una estrategia.” — General Gordon R. Sullivan

Usa contadores. No esperanza.

Tareas prácticas (comandos + salida + decisiones)

Abajo tienes tareas reales que puedes ejecutar durante incidentes o para establecer líneas base. Cada una incluye: el comando, qué significa la salida y la decisión que tomas a partir de ella.

Task 1: Listar contadores disponibles para CPU, memoria y disco

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter -ListSet Processor,Memory,PhysicalDisk | Select-Object -ExpandProperty Counter"
\\Processor(*)\\% Processor Time
\\Processor(*)\\% Privileged Time
\\Processor(*)\\% User Time
\\Processor(*)\\Interrupts/sec
\\Processor(*)\\% Idle Time
\\Memory\\Available MBytes
\\Memory\\Committed Bytes
\\Memory\\% Committed Bytes In Use
\\Memory\\Cache Faults/sec
\\Memory\\Pages/sec
\\PhysicalDisk(*)\\Avg. Disk sec/Read
\\PhysicalDisk(*)\\Avg. Disk sec/Write
\\PhysicalDisk(*)\\Disk Reads/sec
\\PhysicalDisk(*)\\Disk Writes/sec
\\PhysicalDisk(*)\\Current Disk Queue Length

Qué significa: Tu sistema expone estos contadores; los nombres varían según la versión del SO y los roles instalados. No puedes consultar lo que no está presente.

Decisión: Elige contadores según la pregunta que respondas (latencia, rendimiento, saturación), no por lo que te suena familiar.

Task 2: Instantánea rápida de CPU (global)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Processor(_Total)\% Processor Time' | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue"
Path                                   CookedValue
----                                   -----------
\\server\\processor(_total)\\% processor time   37.248

Qué significa: CookedValue es un porcentaje. Una sola muestra es una pista, no un veredicto.

Decisión: Si está alto, no actúes aún. Toma una serie temporal corta a continuación.

Task 3: Serie temporal de CPU (capturar picos)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 10 | Select-Object -ExpandProperty CounterSamples | Select-Object TimeStamp,CookedValue"
TimeStamp                CookedValue
---------                -----------
2/5/2026 2:13:01 AM      41.1
2/5/2026 2:13:02 AM      92.3
2/5/2026 2:13:03 AM      88.7
2/5/2026 2:13:04 AM      54.9
2/5/2026 2:13:05 AM      39.2
2/5/2026 2:13:06 AM      36.8
2/5/2026 2:13:07 AM      35.5
2/5/2026 2:13:08 AM      34.9
2/5/2026 2:13:09 AM      35.2
2/5/2026 2:13:10 AM      36.1

Qué significa: Tuviste un pico real (90%+) durante un par de segundos. Eso puede ser normal (GC, compactación, tareas programadas) o patológico.

Decisión: Si los picos se correlacionan con la afectación de usuarios, averigua si la CPU está realizando trabajo de usuario o de kernel a continuación.

Task 4: Tiempo de CPU de usuario vs privilegiado (presión del kernel)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Processor(_Total)\% User Time','\Processor(_Total)\% Privileged Time' -SampleInterval 1 -MaxSamples 5 | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue"
Path                                                CookedValue
----                                                -----------
\\server\\processor(_total)\\% user time             22.4
\\server\\processor(_total)\\% privileged time       18.7
\\server\\processor(_total)\\% user time             23.1
\\server\\processor(_total)\\% privileged time       41.2
\\server\\processor(_total)\\% user time             21.9
\\server\\processor(_total)\\% privileged time       39.5

Qué significa: Un pico en tiempo privilegiado sugiere trabajo en kernel: drivers, la pila de almacenamiento, drivers filtro antivirus, networking pesado, conmutación de contexto o tormentas de interrupciones.

Decisión: Si el tiempo privilegiado está alto, mira la latencia de disco y las interrupciones antes de culpar a “la aplicación”.

Task 5: Longitud de cola del procesador (¿esperan los hilos?)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\System\Processor Queue Length' -SampleInterval 1 -MaxSamples 10 | Select-Object -ExpandProperty CounterSamples | Select-Object TimeStamp,CookedValue"
TimeStamp                CookedValue
---------                -----------
2/5/2026 2:14:01 AM      0
2/5/2026 2:14:02 AM      2
2/5/2026 2:14:03 AM      8
2/5/2026 2:14:04 AM      9
2/5/2026 2:14:05 AM      7
2/5/2026 2:14:06 AM      1
2/5/2026 2:14:07 AM      0
2/5/2026 2:14:08 AM      0
2/5/2026 2:14:09 AM      1
2/5/2026 2:14:10 AM      0

Qué significa: Esto son hilos ejecutables esperando CPU. En un sistema multinúcleo, interprétalo respecto al número de cores. Los picos pueden ser normales; una cola sostenida sugiere contención de CPU.

Decisión: Si la longitud de cola se mantiene por encima de unas pocas por core durante intervalos sostenidos, necesitas reducir la demanda de CPU o añadir capacidad. Si solo pica brevemente, sigue la fuente del pico.

Task 6: Disponibilidad de memoria (la comprobación más simple: ¿estamos apretados?)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Memory\Available MBytes' -SampleInterval 2 -MaxSamples 5 | Select-Object -ExpandProperty CounterSamples | Select-Object TimeStamp,CookedValue"
TimeStamp                CookedValue
---------                -----------
2/5/2026 2:15:01 AM      612
2/5/2026 2:15:03 AM      590
2/5/2026 2:15:05 AM      571
2/5/2026 2:15:07 AM      548
2/5/2026 2:15:09 AM      530

Qué significa: La memoria disponible está en descenso. El umbral “malo” absoluto depende del rol. Controladores de dominio y servidores de archivos toleran menos memoria libre que servidores de base de datos que consumen mucha memoria.

Decisión: Si está baja y descendente, revisa los bytes comprometidos y la actividad de paginación antes de declarar “necesitamos más RAM”.

Task 7: Presión de commit (¿nos acercamos al límite de commit?)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Memory\% Committed Bytes In Use','\Memory\Committed Bytes' | Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue"
Path                                         CookedValue
----                                         -----------
\\server\\memory\\% committed bytes in use   91.6
\\server\\memory\\committed bytes            2.941943e+10

Qué significa: Un uso de commit cerca del 90% es una señal de alarma. El commit es memoria virtual que debe estar respaldada por RAM o archivo de paginación. Si el commit llega al 100%, las asignaciones fallan y los servicios se caen de formas creativas.

Decisión: Con uso sostenido de commit del 85–95%+, reduce uso de memoria, arregla fugas o aumenta RAM/pagefile. No esperes al 100%.

Task 8: Tasa de paginación (¿el sistema está thrashing?)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\Memory\Pages/sec' -SampleInterval 1 -MaxSamples 10 | Select-Object -ExpandProperty CounterSamples | Select-Object TimeStamp,CookedValue"
TimeStamp                CookedValue
---------                -----------
2/5/2026 2:16:01 AM      12
2/5/2026 2:16:02 AM      18
2/5/2026 2:16:03 AM      220
2/5/2026 2:16:04 AM      410
2/5/2026 2:16:05 AM      395
2/5/2026 2:16:06 AM      205
2/5/2026 2:16:07 AM      44
2/5/2026 2:16:08 AM      16
2/5/2026 2:16:09 AM      14
2/5/2026 2:16:10 AM      13

Qué significa: Una ráfaga de paginación puede ser normal. Paginación sostenida junto a poca memoria disponible y aumento de latencia de disco es la firma clásica de presión de memoria.

Decisión: Si la paginación es sostenida y la latencia de disco sube, trata la memoria como el cuello de botella primario incluso si “el disco está ocupado”. El disco es la víctima aquí.

Task 9: Latencia de disco por volumen (la foto clave)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(*)\Avg. Disk sec/Read','\PhysicalDisk(*)\Avg. Disk sec/Write' | Select-Object -ExpandProperty CounterSamples | Sort-Object CookedValue -Descending | Select-Object -First 8 Path,CookedValue"
Path                                                     CookedValue
----                                                     -----------
\\server\\physicaldisk(1 d:)\\avg. disk sec/write         0.187
\\server\\physicaldisk(1 d:)\\avg. disk sec/read          0.142
\\server\\physicaldisk(0 c:)\\avg. disk sec/write         0.021
\\server\\physicaldisk(0 c:)\\avg. disk sec/read          0.009

Qué significa: La latencia está en segundos. 0.187 seg son 187 ms de latencia de escritura, lo cual es malo para la mayoría de cargas transaccionales. Lecturas a 142 ms tampoco son buenas.

Decisión: Si un volumen específico muestra alta latencia, enfoca la investigación allí: qué carga lo está golpeando, qué cambió y si es capacidad, ruta o saturación del backend.

Task 10: Longitud de cola de disco (contexto, no veredicto)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(*)\Current Disk Queue Length' | Select-Object -ExpandProperty CounterSamples | Sort-Object CookedValue -Descending | Select-Object -First 6 Path,CookedValue"
Path                                                     CookedValue
----                                                     -----------
\\server\\physicaldisk(1 d:)\\current disk queue length   23
\\server\\physicaldisk(0 c:)\\current disk queue length   1

Qué significa: Peticiones esperando en disco. Una cola de 23 puede estar bien en un sistema de almacenamiento profundo y paralelo—o ser terrible en un disco SATA único. Sin latencia, la longitud de cola es media historia.

Decisión: Usa la longitud de cola para respaldar la conclusión sobre la latencia, no para sustituirla.

Task 11: Throughput de disco (¿estamos saturando ancho de banda?)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter '\PhysicalDisk(*)\Disk Read Bytes/sec','\PhysicalDisk(*)\Disk Write Bytes/sec' | Select-Object -ExpandProperty CounterSamples | Sort-Object CookedValue -Descending | Select-Object -First 10 Path,CookedValue"
Path                                                        CookedValue
----                                                        -----------
\\server\\physicaldisk(1 d:)\\disk write bytes/sec           8.941122e+07
\\server\\physicaldisk(1 d:)\\disk read bytes/sec            2.110294e+07
\\server\\physicaldisk(0 c:)\\disk write bytes/sec           1.240122e+06
\\server\\physicaldisk(0 c:)\\disk read bytes/sec            3.901220e+06

Qué significa: Bytes/sec. En D: estás haciendo ~89 MB/s de escrituras y ~21 MB/s de lecturas. Eso puede ser normal para un job de backup, terrible para una BD sensible a latencia, o ambas cosas.

Decisión: Si el throughput es alto y la latencia también, estás saturando algo. Si el throughput es bajo pero la latencia es alta, tienes contención, problemas en el backend o un patrón de I/O patológico.

Task 12: Identificar qué proceso consume CPU (principales culpables)

cr0x@server:~$ powershell -NoProfile -Command "Get-Process | Sort-Object CPU -Descending | Select-Object -First 8 Name,Id,CPU,WorkingSet64"
Name          Id   CPU WorkingSet64
----          --   --- ------------
w3wp        4120 812.3   1245184000
MsMpEng     2788 410.7    512245760
sqlservr    1556 209.1   8421191680
svchost     1020  88.5    210796544

Qué significa: Esto es tiempo de CPU acumulado desde el inicio del proceso, no CPU% instantáneo. Sigue siendo útil: si algo tiene tiempo de CPU absurdo en un uptime corto, es candidato.

Decisión: Si la CPU está alta ahora, correlaciona esto con los contadores de series temporales; si el principal culpable es un escaneo de seguridad, reprograma o ajusta exclusiones (con gobernanza).

Task 13: Comprobación remota de CPU en varios servidores

cr0x@server:~$ powershell -NoProfile -Command "$servers='app01','app02','db01'; Get-Counter '\Processor(_Total)\% Processor Time' -ComputerName $servers | Select-Object -ExpandProperty CounterSamples | Select-Object PSComputerName,TimeStamp,CookedValue"
PSComputerName TimeStamp                CookedValue
-------------- ---------                -----------
app01          2/5/2026 2:17:01 AM      18.2
app02          2/5/2026 2:17:01 AM      22.7
db01           2/5/2026 2:17:01 AM      79.4

Qué significa: Acabas de establecer el radio de alcance: la BD está caliente, las apps no. Así evitas depuración al azar.

Decisión: Enfócate en db01 a continuación: latencia de disco, comportamiento de caché de búfer, paginación y presión de consultas.

Task 14: Exportar una captura corta a CSV como evidencia

cr0x@server:~$ powershell -NoProfile -Command "$c='\Processor(_Total)\% Processor Time','\Memory\Available MBytes','\Memory\Pages/sec','\PhysicalDisk(_Total)\Avg. Disk sec/Read','\PhysicalDisk(_Total)\Avg. Disk sec/Write'; Get-Counter $c -SampleInterval 2 -MaxSamples 30 | Export-Counter -Path C:\temp\triage.blg"

Qué significa: Capturaste una ventana de 60 segundos en un archivo BLG. Eso es nativo de PerfMon y puede abrirse más tarde o analizarse.

Decisión: Durante incidentes, siempre captura evidencia antes de reiniciar cosas. “Reiniciamos y desapareció” no es una causa raíz.

Task 15: Parsear un BLG y convertir a CSV (compartible)

cr0x@server:~$ powershell -NoProfile -Command "Import-Counter C:\temp\triage.blg | Export-Counter -FileFormat CSV -Path C:\temp\triage.csv"

Qué significa: Ahora tienes un CSV que puedes abrir en Excel, ingerir en una base de series temporales o diferenciar contra una línea base.

Decisión: Usa el CSV para mostrar tendencias (latencia subiendo con paginación, CPU picando con tiempo privilegiado) y evitar debates de “esto se siente como”.

Task 16: Monitorizar una instancia de volumen específica de forma fiable (evitar la trampa de la instancia equivocada)

cr0x@server:~$ powershell -NoProfile -Command "Get-Counter -ListSet PhysicalDisk | Select-Object -ExpandProperty PathsWithInstances | Where-Object { $_ -like '*Avg. Disk sec/Read*' } | Select-Object -First 8"
\\PhysicalDisk(0 C:)\\Avg. Disk sec/Read
\\PhysicalDisk(1 D:)\\Avg. Disk sec/Read
\\PhysicalDisk(_Total)\\Avg. Disk sec/Read
\\PhysicalDisk(2 E:)\\Avg. Disk sec/Read

Qué significa: Estás enumerando rutas de instancia exactas. Eso te evita muestrear una instancia que no existe en otro servidor (o cuyos nombres cambiaron).

Decisión: Siempre descubre rutas de instancia programáticamente al escribir scripts que corran en flotas.

Guía rápida de diagnóstico

Esta es la secuencia “tengo cinco minutos”. No estás probando una tesis. Estás encontrando el cuello de botella lo suficientemente rápido para detener la hemorragia.

Primero: establece el alcance del síntoma

  1. ¿Un host o muchos? Muestrea CPU rápidamente a través de los servidores sospechosos (Task 13). Si solo una máquina está caliente, no te compliques innecesariamente.
  2. ¿Un volumen o varios? Revisa la latencia de disco por volumen (Task 9). Si solo D: sufre, no toques C:.

Segundo: identifica el recurso limitante

  1. ¿Saturación de CPU? Mira \Processor(_Total)\% Processor Time y \System\Processor Queue Length (Tasks 3 y 5). CPU alta sin cola puede seguir siendo “ocupada pero aguantando”. Cola alta significa hilos esperando.
  2. ¿Presión de memoria? Revisa \Memory\Available MBytes, \Memory\% Committed Bytes In Use y \Memory\Pages/sec (Tasks 6–8). Memoria disponible baja + commit alto + paginación sostenida es la firma.
  3. ¿Latencia de disco? Revisa \PhysicalDisk(*)\Avg. Disk sec/Read y Write (Task 9). Si la latencia es alta, todo lo que está encima se verá mal.

Tercero: decide mitigar o investigar

  • Si la CPU es el cuello de botella: encuentra procesos principales, revisa tiempo privilegiado (Tasks 4 y 12). Mitiga con limitación, reprogramación de jobs por lotes o escalado temporal. No reinicies servicios a ciegas a menos que haya una fuga o hilo desbocado.
  • Si la memoria es el cuello de botella: detén el crecimiento (proceso con fuga, caché descontrolada, servicio mal configurado). Mitiga reduciendo carga, reiniciando al culpable si es necesario y ajustando el pagefile. Si estás haciendo mucho paging, el disco parecerá culpable—ignora esa pista roja.
  • Si la latencia de disco es el cuello de botella: identifica el volumen y la carga. Mitiga pausando jobs pesados, moviendo rutas temporales, verificando salud del backend o haciendo failover si la arquitectura lo permite. Echar CPU a la latencia de almacenamiento es como gritarle a una barra de progreso.

Tres micro-historias corporativas desde el frente

Micro-historia #1: El incidente causado por una suposición errónea

Una empresa mediana tenía un servidor de archivos crítico de Windows que “se congelaba aleatoriamente” cada mañana de entre semana. La primera respuesta asumió lo evidente: “picos de CPU a las 9 AM, así que es CPU”. Presionaron por una VM más grande y más vCPU. La solicitud se aprobó porque sonaba razonable y a todos les gusta una historia de compra limpia.

Tras el cambio, el congelamiento siguió ocurriendo. La CPU parecía menor, pero la experiencia de usuario no mejoró. Eso debió ser la pista: bajar la utilización de CPU sin mejorar la latencia significa que la CPU no era el limitador.

El segundo respondededor hizo algo aburrido: capturó una traza de contadores de un minuto durante el evento. \PhysicalDisk(…)\Avg. Disk sec/Write pasó de milisegundos de un dígito a cientos de milisegundos. Al mismo tiempo, \Memory\Pages/sec estaba elevado y \Processor(_Total)\% Privileged Time picó. El subsistema de almacenamiento estaba haciendo timeouts bajo una carga de escritura intensa.

El culpable no era “el disco es lento” en abstracto. Era un job programado que volcaba millones de archivos pequeños en un solo directorio en un volumen alojado en almacenamiento compartido, justo cuando también se ejecutaban snapshots VSS. Agitación de metadatos, IO de snapshot y contención del backend: una tormenta perfecta de comportamientos mundanos de Windows.

La solución no fue más CPU. Fue reprogramar el job, distribuir la salida en varios directorios, ajustar el timing de snapshots y añadir un volumen separado para esa carga. El dinero ahorrado en CPU innecesaria pagó mejoras reales de almacenamiento más tarde.

Micro-historia #2: La optimización que salió mal

Un equipo de aplicación quería despliegues más rápidos. Ajustaron un servicio de Windows para cachear más datos en memoria, intentando reducir llamadas a la BD. Funcionó en staging. En producción también funcionó—hasta que el tráfico subió y la caché creció más allá del “objetivo suave”.

El uso de memoria subió lentamente. Nadie lo notó porque los servidores “tenían mucha RAM” y Windows no protestó ruidosamente. Pero \Memory\% Committed Bytes In Use fue subiendo. Entonces empezó el paging. La latencia de disco subió. El tiempo privilegiado de CPU subió. El sistema entró en la clásica cinta de paginación: todo técnicamente “estaba arriba”, pero los tiempos de respuesta eran terribles.

La primera solución intentada fue mover el pagefile a un volumen más rápido. Ayudó un poco, lo justo para enmascarar el problema y prolongar el incidente. Esa es la trampa: optimizar el paging es como instalar pasamanos más bonitos en unas escaleras a un sótano en el que no deberías vivir.

La corrección fue limitar la caché, añadir políticas de expulsión y separar objetos “calientes” de los “agradables de tener”. También añadieron una alerta simple basada en contadores: si el uso de commit se mantenía alto y la paginación superaba un umbral durante varios minutos, el equipo recibía página antes que los usuarios.

La lección: algunas “optimizaciones” de rendimiento son estrategias de consumo de recursos. Si no mides commit y paginación, puedes lanzar una bomba de tiempo detrás de una feature flag.

Micro-historia #3: La práctica aburrida pero correcta que salvó el día

Un entorno financiero ejecutaba jobs por lotes nocturnos: importaciones, generación de informes y ETL en servidores Windows conectados a almacenamiento compartido. Los jobs eran previsibles, pero el entorno tenía una cosa que a la mayoría les falta: líneas base. Cada semana, una tarea programada capturaba una traza corta de contadores durante las ventanas pico de batch y la archivaba.

Una noche, los informes empezaron a fallar en los plazos. El equipo de operaciones no discutió quién cambió qué. Abrieron las capturas semanales y compararon latencia y throughput de disco. La latencia subió en un solo volumen mientras el throughput se mantenía plano. Ese patrón gritaba “contención en el backend o problema en la ruta de almacenamiento”, no “aumentó la carga”.

Luego revisaron algunos servidores más. Mismo volumen, misma ventana temporal, misma firma de latencia. Eso estableció que no era un vecino ruidoso dentro de una VM. Era sistémico.

Los ingenieros de almacenamiento encontraron un evento de failover de ruta en el lado del SAN que no recuperó completamente las rutas óptimas, dejando tráfico en una ruta subóptima. Reparar la ruta restauró la latencia de inmediato y los jobs terminaron dentro de su ventana normal.

Esto no fue heroísmo. Fue recolección rutinaria de evidencia. La disciplina aburrida—trazas de línea base—convirtió una posible sala de guerra nocturna en una reparación de 30 minutos.

Broma #2: El sistema de monitorización más fiable es el que configuras antes de que tu jefe aprenda la palabra “latencia”.

Errores comunes (síntoma → causa raíz → solución)

1) “La CPU está al 40% pero el servidor está lento”

Síntoma: Los usuarios ven timeouts; la CPU parece moderada.

Causa raíz: Latencia de disco o presión de memoria causando que los hilos bloqueen en I/O; la CPU parece “libre” porque los hilos están esperando.

Solución: Revisa \PhysicalDisk(*)\Avg. Disk sec/Read/Write y \Memory\Pages/sec. Si la latencia es alta, arregla la ruta de I/O o la carga. Si la paginación es alta, soluciona la presión de memoria.

2) “La longitud de cola de disco está alta, por lo tanto el almacenamiento es el problema”

Síntoma: Picos en longitud de cola; alguien manda al equipo de almacenamiento.

Causa raíz: La longitud de cola depende del contexto; sube bajo I/O paralelo y caché normales. También puede subir durante paginación por presión de memoria.

Solución: Usa la latencia como indicador primario. Longitud de cola sin latencia alta no es incidente. Cola alta con latencia alta es accionable.

3) “Lo arreglamos añadiendo vCPUs”

Síntoma: % CPU bajó después de añadir cores; los usuarios siguen quejándose.

Causa raíz: La CPU no era el cuello de botella; solo cambiaste el denominador. O introdujiste problemas de scheduling/NUMA.

Solución: Valida con \System\Processor Queue Length y contadores de disco/memoria. Si la cola no estaba alta antes, la CPU no era el limitador. Revierte si complica la colocación NUMA.

4) “Available MBytes es bajo, nos quedamos sin memoria”

Síntoma: Memoria disponible baja; suenan alarmas; alguien pide RAM.

Causa raíz: Windows usa memoria agresivamente para caché; solo baja disponibilidad no prueba presión.

Solución: Confirma con % Committed Bytes In Use y Pages/sec. Disponible bajo + commit alto + paginación sostenida es presión. Disponible bajo + paginación baja puede estar bien.

5) “Paging es distinto de cero, así que es malo”

Síntoma: Pages/sec muestra actividad; cunde el pánico.

Causa raíz: Las ráfagas de paginación ocurren; el SO recorta y gestiona working sets. No es anormal que no sea cero; lo que no es normal es paginación sostenida alta.

Solución: Tréndalo. Toma 60–120 segundos de muestras y correlaciónalo con latencia y afectación de usuarios.

6) “La salida de Get-Counter es rara; los números parecen científicos”

Síntoma: Aparecen valores como 2.94e+10.

Causa raíz: PowerShell formatea números grandes en notación científica.

Solución: Formatea la salida explícitamente (por ejemplo, redondea/convierte unidades) al reportar a humanos. No cambies cómo recopilas; cambia cómo presentas.

7) “Los contadores difieren entre servidores, el script está roto”

Síntoma: Las consultas remotas fallan o devuelven instancias faltantes.

Causa raíz: Los nombres de instancia difieren (discos, NICs, procesos); roles/features cambian los conjuntos de contadores disponibles.

Solución: Descubre PathsWithInstances por host antes de muestrear. Evita codificar nombres de instancia cuando puedas consultar por patrón.

8) “Muestreamos cada 60 segundos y no vimos nada”

Síntoma: Los usuarios se quejan de picos; los contadores parecen calmos.

Causa raíz: Elegiste un intervalo de muestreo que promedia el problema.

Solución: Usa muestreo de 1–2 segundos durante el triage, luego amplia tras capturar la firma.

Listas de verificación / plan paso a paso

Checklist A: Construir una línea base (hazlo una vez, agradécetelo luego)

  1. Escoge 10–15 contadores para tu rol (web/app/DB/servidor de archivos). Conjunto mínimo:
    • \Processor(_Total)\% Processor Time
    • \System\Processor Queue Length
    • \Memory\Available MBytes
    • \Memory\% Committed Bytes In Use
    • \Memory\Pages/sec
    • \PhysicalDisk(*)\Avg. Disk sec/Read
    • \PhysicalDisk(*)\Avg. Disk sec/Write
  2. Captura durante 5–15 minutos en períodos conocidos de “actividad normal alta”, no a las 3 AM cuando no pasa nada.
  3. Almacena archivos BLG en una ubicación predecible con marcas temporales.
  4. Documenta qué es “normal”: rangos típicos de latencia, picos de CPU típicos y qué jobs se ejecutan cuándo.

Checklist B: Captura en incidente (kit mínimo de evidencia)

  1. Inicia una captura de 60–120 segundos con intervalos de 1–2 segundos para CPU/memoria/latencia de disco (Task 14, ajusta contadores según sea necesario).
  2. Registra qué experimentan los usuarios y cuándo (a nivel de minuto está bien).
  3. Comprueba si el problema es local al host o extendido en la flota (Task 13).
  4. Si debes reiniciar algo, hazlo después de tener al menos una traza.

Checklist C: Convierte el triage en monitorización (para dejar de revivir el mismo incidente)

  1. Crea una tarea programada que ejecute una captura corta de Get-Counter durante ventanas pico.
  2. Alerta sobre tendencias, no sobre puntos únicos:
    • latencia de disco sostenida alta
    • uso de commit sostenido alto
    • paginación sostenida con poca memoria disponible
    • longitud de cola de CPU sostenida
  3. Revisa semanalmente. No porque sea divertido. Porque sale más barato que las interrupciones.

Preguntas frecuentes

1) ¿Get‑Counter es lo bastante preciso para la respuesta a incidentes real?

Sí. Lee la misma infraestructura de contadores que usa PerfMon. El modo de fallo habitual no es la precisión; es la interpretación (contador equivocado, instancia equivocada, intervalo de muestreo equivocado).

2) ¿Debo usar CookedValue o RawValue?

Usa CookedValue para la mayor parte del trabajo operativo. RawValue es para cuando implementas tu propia matemática o validas tipos de contador. En triaje de producción buscas claridad.

3) ¿Qué intervalo de muestreo debo usar?

Durante triage: 1–2 segundos para 30–120 muestras. Para línea base: 5–15 segundos durante 10–30 minutos. Para tendencias a largo plazo: 30–60 segundos está bien, pero acepta que perderás micro-picos.

4) ¿Por qué falla Get‑Counter remoto cuando WinRM funciona?

Porque los contadores de rendimiento y WinRM usan tuberías distintas. Reglas de firewall, permisos, Remote Registry/dependencias de servicio o políticas endurecidas pueden bloquear la recolección de contadores aunque puedas PowerShell remoto.

5) ¿“Avg. Disk sec/Read” es lo mismo que latencia de disco?

En la práctica sí: es el tiempo de servicio promedio por lectura, en segundos, observado por el SO. Multiplica por 1000 para pensar en milisegundos. Rastrea lectura y escritura; fallan de manera diferente.

6) ¿Cuál es un valor “bueno” de latencia de disco?

Depende de la carga, pero como heurística SRE: milisegundos de un dígito es saludable para muchas cargas de servidor; decenas de milisegundos es preocupante; cientos es incidente. Compáralo siempre con tu línea base.

7) ¿Por qué la CPU parece baja cuando los usuarios hacen timeouts?

Porque esperar no consume CPU. Los hilos bloqueados en disco, red, locks o paginación no queman CPU. Por eso miras longitud de cola, paginación y latencia de I/O juntos.

8) ¿Puedo usar Get‑Counter como un agente de monitorización ligero?

Sí, con disciplina. Mantén el conjunto de contadores pequeño, el muestreo sensato y las salidas estructuradas (BLG/CSV). No polles cientos de contadores cada segundo en boxes de producción y luego te sorprendas cuando añades overhead.

9) ¿Cómo evito el problema de “nombre de instancia equivocado” para discos y procesos?

Enumera instancias primero con PathsWithInstances, luego muestrea las rutas exactas devueltas. Para procesos, prefiere métricas ligadas a nombres de servicio o IDs cuando sea posible, porque los nombres de instancia pueden cambiar.

Conclusión: siguientes pasos que sí puedes hacer

  1. Escoge tus contadores clave (CPU total + cola, memoria disponible + commit + paginación, latencia de disco lectura/escritura por volumen).
  2. Ejecuta una captura de 2 minutos en la próxima queja en vez de mirar el Administrador de tareas. Guárdala como BLG. Evidencia primero, opiniones después.
  3. Establece una línea base de una ventana “normal y ocupada” esta semana. Sin línea base, adivinas con confianza.
  4. Convierte una lección de incidente en una alerta: latencia de disco sostenida, presión de commit sostenida o cola de CPU sostenida. Elige la que coincida con tu último outage.
  5. Escribe tus umbrales como heurísticas, no como leyes. Tu entorno te enseñará qué se ve “malo” realmente.

Si haces solo una cosa: empieza a medir rutinariamente la latencia de disco y la presión de commit. Esas dos métricas detectan una cantidad asombrosa de tickets de “servidor lento” antes de que se conviertan en outages.

← Anterior
DNSSEC NSEC3: mitos — cuándo ayuda y cuándo perjudica el rendimiento
Siguiente →
Bucle OOBE / «Algo salió mal»: Soluciones rápidas para desastres de configuración

Deja un comentario