Sentry.Sources keeps the decoded source-code map on its heap after loading it into ETS

Abierto Apto para principiantes
#1,259 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
elixir
Área
backend

Línea de trabajo

Empieza leyendo Sentry.Sources.handle_continue/2, especialmente la cláusula :load_source_code_map, que decodifica el mapa empaquetado e inserta entradas en ETS. Revisa las pruebas del callback de GenServer y verifica que el proceso libere el mapa decodificado después de cargarlo, mientras las entradas de ETS siguen disponibles. El issue no indica ningún archivo de pruebas, así que localiza las pruebas pertinentes en el repositorio.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Environment
  • sentry 13.4.2, Elixir 1.20.4 / OTP 29.1.1, enable_source_code_context: true
  • Release with a packaged source-code map (mix sentry.package_source_code)
What happens

Sentry.Sources.handle_continue(:load_source_code_map, state) decodes the whole map (:erlang.binary_to_term/1 on the packaged file), inserts each entry into the :sentry_source_code_map ETS table and returns {:noreply, state}. The process then receives no further messages, so it never triggers a garbage collection. The decoded term, which ETS has already copied, stays on the process heap for the life of the node.

On a ~6,400-module app this was about 57 MB per node, on top of the ~54 MB the ETS table needs:

pid = Process.whereis(Sentry.Sources)
Process.info(pid, :total_heap_size)   # ~7.1M words ≈ 57 MB
:erlang.garbage_collect(pid)
Process.info(pid, :total_heap_size)   # near zero

This matters on small machines: on a 1 GB container, this one process held ~6% of RAM for nothing.

Suggested fix

Shrink the heap once the load is done, for example:

{:noreply, state, :hibernate}

or an explicit :erlang.garbage_collect() before returning from handle_continue/2. :hibernate is enough because the process is idle afterwards. Decoding the map outside the GenServer (in a short-lived task) would also avoid it.

Workaround

After the application starts, we wait for the load to finish with :sys.get_state(Sentry.Sources) and then call :erlang.garbage_collect/1 on the process.

Lenguaje dominante
Elixir
Estrellas
692
Forks
219
Merge medio
2 d 19 h
PR fusionados (30 d)
16

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de getsentry/sentry-elixir

Todos los issues de getsentry/sentry-elixir

Issues similares

Más issues de Elixir

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.