Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory usage steadily increases without recovery in Electric instance #2229

Open
sullyo opened this issue Jan 14, 2025 · 8 comments
Open

Memory usage steadily increases without recovery in Electric instance #2229

sullyo opened this issue Jan 14, 2025 · 8 comments
Labels

Comments

@sullyo
Copy link

sullyo commented Jan 14, 2025

We're experiencing steadily increasing memory usage in our Electric instance that doesn't recover until restart.

Current behavior:

  • Memory usage shows continuous growth over time
  • No automatic recovery of unused memory
  • Requires manual restarts to reset memory levels

Environment:

  • Electric deployed on render via container
  • 2gb memory, 1 cpu

Theory:

  • Could be related to total requests. Saw memory exceed limit with more requests

Reproduction steps:

  1. Run Electric instance
  2. Monitor memory usage over time
  3. Observe steady increase in memory consumption
  4. Eventually requires restart to recover

Current workaround:
Manual restart of the instance clears the memory back to normal levels.

Image

Image

Image

@balegas
Copy link
Contributor

balegas commented Jan 15, 2025

Hi, we've seen this happen before. We think it is related with how Elixir manages processes memory. We're gonna work on a fix ASAP.

@balegas balegas added the bug label Jan 15, 2025
@robacourt
Copy link
Contributor

robacourt commented Jan 15, 2025

Please could you try something for us? We think garbage collection is causing the issue so please could you try running it manually:

On the machine with the electric docker image running run

docker exec -it IMAGE_NAME bin/entrypoint remote

(Use docker ps to get the IMAGE_NAME)

This will get you into an elixir shell, where you can run:

:erlang.garbage_collect()

It's worth running this 5 times to get the memory use right down.

Let us know if this helps, if it does we can automate the garbage collection to solve your issue.

@robacourt
Copy link
Contributor

Another thing to try is to let electric use all 2GB of your container's RAM and see what happens. If our hypothesis is correct then hitting the container limit will cause a garbage collection and so electric should flatline at 2GB memory use and continue to operate normally.

If you'd like it to flatline at a lower value, the container's memory can be restricted with the --memory=1g docker run flag or with your cloud provider's settings.

@sullyo
Copy link
Author

sullyo commented Jan 15, 2025

 :erlang.garbage_collect()
true
iex(electric@)2> :erlang.garbage_collect()
true
iex(electric@)3> :erlang.garbage_collect()
true
iex(electric@)4> :erlang.garbage_collect()
true
iex(electric@)5> :erlang.garbage_collect()
true
iex(electric@)6> :erlang.garbage_collect()
true
iex(electric@s7> 

Ran it a few times here

And not seeing any memory reducing here

Image

@sullyo
Copy link
Author

sullyo commented Jan 15, 2025

Another thing to try is to let electric use all 2GB of your container's RAM and see what happens. If our hypothesis is correct then hitting the container limit will cause a garbage collection and so electric should flatline at 2GB memory use and continue to operate normally.

If you'd like it to flatline at a lower value, the container's memory can be restricted with the --memory=1g docker run flag or with your cloud provider's settings.

Going to try something like 1.5g

@robacourt
Copy link
Contributor

I've reproduced an issue that fits this description and have a PR ( #2240 ) out that fixes it. I'll let you know as soon as it's been approved and we have a release for you to try.

robacourt added a commit that referenced this issue Jan 22, 2025
…sses (#2240)

Potential fix for #2229

Electric's memory footprint can get very large due to shape processes
holding on to memory even when idle. This PR hibernates idle shape
processes after 30 seconds of inactivity which garbage collects unused
memory.

This first graph shows 10MB changes coming in for 100 shapes (2 shapes
per second). You can see this taking up 2000MB of memory which is not
released even though the memory is no longer needed (it's been written
to disk).
<img width="679" alt="Screenshot 2025-01-22 at 12 06 41"
src="https://github.com/user-attachments/assets/ae0d5da9-731f-4a9b-9fc1-3f47fa2ffab4"
/>
Not only is the memory not released, but the memory is amplified. In
this example it's amplified by 2x since 2000MB is twice the 1000MB
needed (10MB * 100 shapes). This is due to a binary copy that happens
when CubDB persists data to file. Amplification can increase further do
to having a binary version of the change as well as an Elixir term
version of the change which is used for where clause filtering.

This second graph is with `ELECTRIC_SHAPE_HIBERNATE_AFTER` set to
`50ms`. A value this short is unlikely to be used in production but
allows the effect to be seen quickly for the purposes of this benchmark.
<img width="667" alt="Screenshot 2025-01-22 at 12 09 38"
src="https://github.com/user-attachments/assets/5c22fa32-5e83-49aa-ab2b-d233a5af9c4d"
/>
As you can see, memory use flatlines at 120MB with hibernation rather
than blowing up to 2000MB without hibernation.
@robacourt
Copy link
Contributor

robacourt commented Jan 22, 2025

@sullyo We've just released version 1.0.0-beta.4 which includes a potential fix for this issue. Please could you try it to see if it helps?

It hibernates shapes if they are not in use for 30 seconds, reducing memory consumption. This value is configurable with the ELECTRIC_SHAPE_HIBERNATE_AFTER environment variable, so to hibernate shapes after their idle for 10 seconds set ELECTRIC_SHAPE_HIBERNATE_AFTER to 10s

@sullyo
Copy link
Author

sullyo commented Jan 24, 2025

@robacourt I'll update and give it a try!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants