From 4f44d0881671b6124b2011ea5b38767f6e1e5fe4 Mon Sep 17 00:00:00 2001 From: Oneric Date: Thu, 4 Apr 2024 17:19:58 +0200 Subject: [PATCH] [TEST] Avoid accumulating stale data in websockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some but not all instances (likely depending on usage patterns) those [i’m guessing, to be tested] process end up accumulating stale binary data in such a way it’s not included into young garbage collection cycles. At the same time, full cycles are barely ever triggered making it seem like a memory leak. To avoid this, make full sweeps more frequent for only the affected processes. TODO: actually test this theory + fix ref: https://www.erlang.org/doc/man/erlang#ghlink-process_flag-2-idp226 https://blog.guzman.codes/using-phoenix-channels-high-memory-usage-save-money-with-erlfullsweepafter (showed up in search results and inspired this) https://git.pleroma.social/pleroma/pleroma/-/merge_requests/4060 (different patch due to different socket implementation) --- lib/pleroma/web/mastodon_api/websocket_handler.ex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex index bd7c56243..9dae7bf93 100644 --- a/lib/pleroma/web/mastodon_api/websocket_handler.ex +++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -18,6 +18,8 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do @timeout :timer.seconds(60) # Hibernate every X messages @hibernate_every 100 + # Tune garabge collect for long-lived websocket process + @fullsweep_after 20 def init(%{qs: qs} = req, state) do with params <- Enum.into(:cow_qs.parse_qs(qs), %{}), @@ -59,6 +61,10 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do "#{__MODULE__} accepted websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topic #{state.topic}" ) + # process is long-lived and can sometimes accumulate stale data in such a way it's + # not freed by young garbage cycles, thus make full collection sweeps more frequent + :erlang.process_flag(:fullsweep_after, @fullsweep_after) + Streamer.add_socket(state.topic, state.oauth_token) {:ok, %{state | timer: timer()}} end