Para información, he hecho muchas pruebas con ChatGPT. En particular, he relanzado el contenedor gladys prod con la siguiente opción para crear instantáneas.
Por lo tanto, con Gladys detenido, tengo 4,03 Go de memoria en uso.
Una vez que Gladys ha terminado de iniciarse, tengo 5,7 Go de memoria (15:43).
Hasta las 16:00 me mantengo dentro de este margen, con solo algunas fluctuaciones. Pero se puede ver que la memoria se libera bien.
A las 16:00 el cálculo de los consumos/coste se realizó correctamente con un ligero aumento de la memoria, pero inmediatamente liberado. Esto confirma que no es eso. Tareas terminadas.
1 minuto después, me dirijo al panel de control (no sabría decir si es el detonante) y de repente he pasado a 8,82 Go: la columna « RES » (= memoria reservada) pasa de 1748Mo a 4995Mo. => Nada se libera
Te pongo en bruto lo que me dice ChatGPT, y luego vemos si quieres algo más (Conversación: ChatGPT)
Sí. Ahora vemos claramente lo que está pasando, y tenías razón desde el principio: no es una fuga de heap JS, es una explosión de memoria nativa (fuera de V8), desencadenada por una operación puntual.
Te hago una lectura precisa, factual, a partir del informe “pic” que acabas de proporcionar.
Lo que dice el informe en el momento del pico (prueba numérica)
Heap JS (V8)
"usedMemory": 252011200 ≈ 240 Mo
"externalMemory": 25243016 ≈ 24 Mo
Heap perfectamente estable, casi idéntico a las instantáneas anteriores.
Ninguna fuga JS.
Memoria total del proceso
"rss": 6198140928 ≈ 5,77 Go
"maxRss": 6374838272 ≈ 5,93 Go
+4 Go fuera del heap JS aparecidos bruscamente.
Del lado de Linux (/proc)
RssAnon: 5 089 920 kB ≈ 4,85 Go
RssFile: 59 392 kB
Private_Dirty: 5 090 240 kB
Memoria anónima privada
No mapeada a archivo
No liberada después
Firma típica:
asignaciones nativas masivas (malloc / new del lado de C/C++)
Lo que NO es (importante)
No es:
- V8
- Recogedor de basura
- Objetos JS conservados
- Temporizadores o bucle de eventos bloqueados
- Fuga “clásica” de Node
Tus instantáneas lo demuestran:
la pila se mantiene en ~260 Mo mientras que el RSS explota a ~6 Go.
Lo que es (casi seguro en este punto)
Miremos los vínculos nativos cargados:
"/src/server/node_modules/duckdb/lib/binding/duckdb.node"
"/src/server/node_modules/sqlite3/lib/binding/node_sqlite3.node"
"/src/server/services/usb/.../bindings-cpp.node"
"/src/server/services/bluetooth/.../bluetooth_hci_socket.node"
El principal sospechoso: DuckDB
Es EL principal sospechoso, por varias razones:
-
DuckDB asigna masivamente en nativo
-
Utiliza:
- ejecución vectorizada
- buffers columnares
- caches intermedios
-
No siempre devuelve la memoria al SO inmediatamente
-
Puede subir varios Go en una sola consulta
Y sobre todo:
El pico es instantáneo, CPU elevado, memoria nunca baja
→ exactamente el comportamiento observado.
Por qué no baja
Muy importante de entender:
Por lo tanto:
No es una fuga infinita
Es un aumento por escalones irreversibles
El detonante probable en tu caso
Viendo tu configuración Gladys + Energy Monitoring + historial:
-
agregación energética
-
cálculos temporales
-
consultas analíticas
-
posiblemente:
- consolidación diaria
- agregados por fase / dispositivo
- recálculo histórico
Una consulta pesada de DuckDB se lanzó (cron, trabajo interno, acción UI).
Es coherente con:
- el CPU trabajando
- el aumento de RAM en 1 segundo
- ninguna creación JS visible
Confirmación absoluta (si quieres estar seguro al 100%)
En el próximo pico, lanza inmediatamente:
docker exec gladys bash -lc '
cat /proc/1/smaps | awk "
/duckdb.node/ {f=1}
/^$/ {f=0}
f && /Rss:/ {print}
"
'
Si ves cientos de MB / GB asociados a DuckDB → veredicto final.
Qué hacer concretamente (soluciones realistas)
Opción A – Limitar DuckDB (recomendada)
En Gladys (código):
- limitar el tamaño de las consultas
- evitar agregados globales en el historial completo
- dividir por período (día / semana)
Opción B – Forzar un límite de memoria de Node
Esto no resuelve la causa, pero evita el OOM del host:
-e NODE_OPTIONS="--max-old-space-size=2048 ..."
Atención: esto no limita lo nativo, pero evita apilar ambos.
Opción C – Reinicio programado (pragmático)
Si los picos son raros pero destructivos:
docker restart gladys
- semanal
- o después de una tarea pesada
Es muy común para DuckDB en producción.
Conclusión clara y neta
Tus datos son excelentes
El diagnóstico ahora es sólido
No hay fuga de memoria JS
La RAM se consume por asignaciones nativas (DuckDB muy probablemente)
La memoria no baja porque se mantiene en el área nativa
Si quieres, siguiente paso posible:
- identificar qué consulta de Gladys desencadena el pico
- o ayudarte a parchear / sortear del lado de Gladys (log SQL, throttle, split)
¡Hasta luego!