Volver al blog
·8 min de lectura·productdevbook

Por qué los procesos auxiliares confunden a los monitores de ancho de banda en macOS

Los procesos auxiliares dividen una sola app visible en una docena de filas de red. Por qué pasa esto en macOS y cómo leer más allá del ruido.

  • macOS
  • Bandwidth
  • Network monitoring
  • Deep dive

Abres el Monitor de Actividad una tarde tranquila, ordenas por bytes de red, y la cima de tu lista se ve así: Google Chrome Helper (Renderer), Google Chrome Helper (GPU), Google Chrome Helper, Slack Helper, Slack Helper (Renderer), Slack Helper (GPU). No hay fila para "Chrome" o "Slack", solo un confeti de auxiliares, cada uno tirando unos cientos de kilobytes por segundo. ¿Qué app está realmente hablando? Esa confusión es toda la razón por la que la atribución del ancho de banda de los procesos auxiliares en Mac es la parte más difícil de construir un monitor de red en macOS.

Este artículo explica por qué las apps lanzan auxiliares en primer lugar, por qué el kernel reporta su uso de red por separado, y qué significa "agrupar" cuando una herramienta intenta darte un número limpio por app.

Por qué las apps lanzan procesos auxiliares

Las apps modernas de macOS casi nunca corren como un solo proceso. Hay tres grandes razones.

Sandboxing y separación de privilegios

El App Sandbox de Apple es un límite por proceso. Un renderer que parsea HTML no confiable o ejecuta JavaScript corre con un conjunto de derechos distinto al del padre que tiene tu permiso de micrófono. Si el renderer es comprometido por una página maliciosa, el radio de explosión se detiene en ese proceso: no puede empezar de pronto a grabar audio o leer tu carpeta Documentos. Por esto Chrome y Safari ambos vienen con procesos separados para cada pestaña o sitio, y por qué Slack, Discord y Notion (todas apps Electron) siguen el mismo patrón.

Aislamiento de fallos

Si una pestaña en Chrome se queda sin memoria o cae en un bug del motor JavaScript, no quieres que cada pestaña en el navegador muera con ella. Los procesos auxiliares significan que una sola página mala muestra la pantalla "Aw, Snap" para esa pestaña y nada más. La misma lógica aplica a Slack renderizando un canal, o Discord renderizando una llamada de voz.

Arquitectura de Electron y Chromium

Si la app está construida sobre Electron —Slack, Discord, VS Code, Notion, Linear, Figma desktop, 1Password 8, Microsoft Teams, Postman— hereda el modelo multi-proceso de Chromium en bloque. Hay un proceso "principal", un proceso "GPU", un proceso "Network Service" (a menudo llamado Utility) y un proceso renderer por ventana del navegador o vista significativa. El renderer nunca abre un socket él mismo. Habla al servicio de red por IPC, y el servicio de red hace el handshake TCP real.

Ese último detalle importa más de lo que parece.

Por qué la atribución del ancho de banda de los procesos auxiliares en Mac es difícil

El kernel de macOS atribuye los bytes a cualquier PID que llamó a socket(2) y luego connect(2)/sendto(2)/recvfrom(2). Esa es la respuesta correcta para el kernel: no tiene idea de qué significa "Slack" como producto. Solo sabe que el PID 4711 abrió un socket a 34.117.x.x:443.

Así que cuando le preguntas a nettop o lsof -i o la API cruda proc_pidinfo "¿quién usó bytes de red?", recibes una lista plana de PIDs. Cada PID tiene un nombre de proceso (el nombre del ejecutable en disco), y ese nombre casi siempre es algo como:

  • Google Chrome Helper
  • Google Chrome Helper (GPU)
  • Google Chrome Helper (Renderer)
  • Google Chrome Helper (Plugin)
  • Slack Helper
  • Slack Helper (Renderer)
  • Slack Helper (GPU)
  • com.docker.backend

Un monitor ingenuo —uno que solo vuelca la vista del kernel a la pantalla— te muestra exactamente eso. Ves siete filas de Chrome que tienes que sumar mentalmente para responder "¿cuánto usó Chrome esta hora?". Peor, los renderers son de corta vida. Cierra una pestaña, el renderer muere. Abre una nueva, aparece un nuevo renderer con un nuevo PID. Suma a lo largo de una hora y la respuesta está fragmentada entre docenas de PIDs muertos. Ese es el reto principal de la atribución del ancho de banda de los procesos auxiliares en Mac: las unidades que el kernel expone no coinciden con las unidades en las que un humano quiere pensar.

Qué significa "agrupar"

Agrupar es el acto de mirar un proceso auxiliar —por su ruta de bundle, PID padre, o ambos— y atribuir sus bytes a la app visible al usuario a la que pertenece. Bien hecho, dejas de ver once filas de Chrome y empiezas a ver una fila llamada "Google Chrome" con la suma.

Hay unas cuantas maneras de hacerlo, y cada una tiene compromisos.

Por ruta de bundle

Cada auxiliar vive dentro del bundle de la app padre. Para Chrome, esa ruta es algo como:

/Applications/Google Chrome.app/Contents/Frameworks/
  Google Chrome Framework.framework/Versions/.../Helpers/
  Google Chrome Helper.app/Contents/MacOS/Google Chrome Helper

Si la ruta del ejecutable de un proceso contiene otro bundle .app más arriba en el árbol, el bundle externo es casi seguro el padre. Esta es la señal de agrupación más fiable porque sobrevive a través de cambios de PID: abre una nueva pestaña de Chrome, la ruta del nuevo renderer sigue estando bajo Google Chrome.app.

Por PID padre

Puedes subir por el árbol de procesos hasta llegar a un padre que viva en /Applications o cuyo identificador de bundle coincida con una aplicación "real". Esto funciona pero es más frágil: launchd reasigna padre a procesos huérfanos, y algunos auxiliares se lanzan por servicios XPC en lugar de directamente por el padre.

Por prefijo de identificador de bundle

El bundle ID de Slack es com.tinyspeck.slackmacgap. El bundle ID del auxiliar es com.tinyspeck.slackmacgap.helper o com.tinyspeck.slackmacgap.helper.renderer. Una coincidencia de prefijo contra la tabla de apps instaladas atrapa la mayoría de los casos. Esta es la técnica que Apple usa internamente para algunos informes de cara al usuario.

En la práctica, un buen monitor usa las tres señales y cae con elegancia cuando una falta.

Ve ova en acción

Un monitor de ancho de banda en la barra de menú visible de un vistazo: local, firmado, ~3 MB.

Descargar para macOS

El caso especial de Electron

Las apps Electron merecen su propio párrafo porque son tan comunes. Un auxiliar de Electron llamado Slack Helper (Renderer) no abre realmente sockets, ese es el servicio de red, normalmente llamado Slack Helper (sin sufijo) o Slack Helper (Plugin) dependiendo de la versión de Electron. El renderer le habla al servicio de red por el bus IPC Mojo de Chromium.

Así que si solo ves tráfico en el Slack Helper desnudo, eso no es un bug, esa es la arquitectura. El renderer está haciendo la petición, pero el kernel ve al servicio de red haciendo el I/O. Desde la perspectiva del usuario, ambos deberían agruparse bajo "Slack". Desde la perspectiva de depuración, saber esto te ahorra una tarde cuando te preguntas por qué el renderer no se está iluminando.

Lo mismo aplica al propio Chrome: en builds recientes de Chrome, casi todo el tráfico de red viene de Google Chrome Helper (Plugin) o del auxiliar del servicio de red, no de los renderers por pestaña.

Por qué no puedes confiar en los totales simples

Una vez entiendes los auxiliares, algunas preguntas comunes se vuelven más fáciles de responder.

"¿Por qué mi uso de Chrome se ve bajo?" Porque los bytes están repartidos entre una docena de auxiliares, y tu monitor no los está sumando. Cada auxiliar individual se ve modesto.

"¿Por qué aparecieron de pronto 200 MB bajo un proceso que no reconozco?" Probablemente un renderer para un stream de vídeo, un servicio XPC manejando sincronización (CloudKit, iCloud, Dropbox), o un daemon del sistema haciendo trabajo en segundo plano. Mira la ruta del ejecutable, no solo el nombre.

"¿Por qué la misma app aparece bajo dos nombres distintos entre reinicios?" Algunos auxiliares incluyen un número de versión o un UUID en su nombre de proceso. La mayoría de monitores los quitan, pero no todos.

Agrupar en la práctica, y cuándo deshacerlo

Un monitor que agrupa auxiliares te muestra algo como:

Google Chrome    412 MB ↓   18 MB ↑
Slack             89 MB ↓    4 MB ↑
Spotify           62 MB ↓  120 KB ↑
Dropbox           34 MB ↓   12 MB ↑

…en lugar de:

Google Chrome Helper (Renderer)   38 MB ↓
Google Chrome Helper (GPU)         2 KB ↓
Google Chrome Helper (Plugin)    220 MB ↓
Google Chrome Helper             140 MB ↓
Google Chrome Helper (Renderer)   12 MB ↓
Slack Helper (Renderer)           41 MB ↓
Slack Helper                      48 MB ↓
... (continúa por 30 filas más)

La primera es lo que realmente quieres. ova hace esta agrupación automáticamente: agrupa cada PID auxiliar bajo el bundle padre para que leas "Slack" en lugar de siete filas de auxiliares.

Agrupación de procesos auxiliares
ova agrupa cada PID auxiliar bajo su app padre para que leas "Slack" en lugar de siete filas de auxiliares. Chrome, Slack, Discord, Telegram, VS Code, Figma: todos consolidados automáticamente.

Cuándo realmente quieres ver auxiliares

Hay un caso donde la agrupación se interpone: depurar una app que se está comportando mal. Si eres un desarrollador intentando averiguar qué proceso de Chromium está filtrando sockets, o si tu renderer está saltándose el servicio de red, quieres la vista cruda.

Un monitor útil te permite hacer clic en la fila agrupada y ver los auxiliares subyacentes: bytes por auxiliar, PID actual, ruta completa del ejecutable. De esa manera la vista por defecto es limpia, pero el detalle está a un toque.

Esto también es útil para diagnosticar fallos: un auxiliar que se reinicia cada 30 segundos y restablece sesiones TLS puede acumular tráfico de fondo sorprendente, y solo es visible cuando puedes ver el historial a nivel de auxiliar.

Recorrido: investigando un misterio de Slack

Supón que Slack muestra 600 MB descargados hoy y no viste ningún vídeo. Aquí va el orden que comprobaría.

  1. Comprueba el patrón por hora del día. Un pico a las 9 AM es probablemente la sincronización de puesta al día de la mañana. Una curva plana de 24 horas es más interesante.
  2. Comprueba el desglose por auxiliar. Si es 90% en Slack Helper (Plugin) (el servicio de red), es tráfico "real" de la app. Si está repartido entre renderers de manera rara, puede que tengas una pestaña filtrada abierta.
  3. Comprueba el conteo de workspaces. Cada workspace de Slack añade un WebSocket persistente y su propia caché de avatares/archivos. Tres workspaces son aproximadamente 3x el tráfico en reposo de uno.
  4. Comprueba el historial de pantalla compartida o huddle. Los huddles usan WebRTC y mascan 1-3 MB/s mientras están activos.

No necesitas una captura de paquetes para nada de esto. Necesitas un monitor por app que agrupe auxiliares y mantenga una hora de historial.

Para terminar

Los procesos auxiliares no son una rareza a sortear: son cómo las apps modernas de macOS se mantienen seguras y estables. El coste es que la vista del kernel sobre "quién usó la red" se lee como una lista plana críptica, y por eso la contabilidad del ancho de banda de los procesos auxiliares en Mac confunde a cada herramienta de propósito general. Cualquier monitor de ancho de banda decente en macOS tiene que hacer agrupación de auxiliares, y cualquiera que no lo haga te dejará sumando filas mentalmente el resto de tu vida.

Si tu herramienta actual te muestra filas de auxiliares crudas y estás cansado de leer "Google Chrome Helper (Renderer)" por milésima vez, instala ova: se sienta en la barra de menú con unos 3 MB, muestrea aproximadamente a 1 Hz y agrupa auxiliares automáticamente. Todos los datos se quedan en tu Mac. macOS 14 y posteriores, Apple Silicon e Intel.