Skip to content

[do not merge] Memory leak debugging - #103

Draft
awilfox wants to merge 1 commit into
mainfrom
awilfox/do-not-merge-DEV-1221-memleak-debugger
Draft

[do not merge] Memory leak debugging#103
awilfox wants to merge 1 commit into
mainfrom
awilfox/do-not-merge-DEV-1221-memleak-debugger

Conversation

@awilfox

@awilfox awilfox commented Aug 3, 2026

Copy link
Copy Markdown
Member

With this commit, you can run:

podman compose exec -e TEST_COUNT=500 -e PATH_TO_HIT=/health app bundle exec derailed exec perf:mem_over_time 1>out1.log 2>err1.log

and see a memory leak when parallel checks are enabled.

  • You can increase TEST_COUNT if you want, but there's not a whole lot of benefit unless you think you've solved the problem and want to see if it stays fixed after a number of additional requests.

  • Lower TEST_COUNT isn't helpful. The first fifty requests are still warming the app, and growth is expected. At 100, you can start to see the leaked objects, but there's still a lot of noise in the retained object list. At 500, you can really see the leak is obvious.

  • Redirection of stdout is recommended because otherwise you get a Rails firehose directed at you. Redirection of stderr is not necessary but it just suppressed this noise:

    �[4m>>>> Executing external compose provider "/opt/homebrew/bin/docker-compose". Please see podman-compose(1) for how to disable this message. <<<<
    
    �[0mDEPRECATION WARNING: ActiveSupport::Configurable is deprecated without replacement, and will be removed in Rails 8.2.
    
    You can emulate the previous behavior with `class_attribute`.
     (called from <top (required)> at /opt/app/config/application.rb:16)
    Database 'geodata-dev' already exists
    

    which didn't seem particularly helpful anyway.

  • This process creates a file in tmp/ with the format $(date -Iseconds)-$(ruby --version)-memory-$(times)-times.txt. This file contains each memory usage reading in MiB. For example, my local file tmp/2026-08-01T02:12:08+00:00-ruby 3.4.10 (2026-06-30 revision 2b0b7728dc) +PRISM [aarch64-linux]-memory-1000-times.txt looks like:

    log file contents
    149.91796875
    165.19140625
    166.83203125
    167.48828125
    168.27734375
    168.47265625
    168.66796875
    168.796875
    169.0390625
    169.6328125
    170.23828125
    170.35546875
    170.59765625
    170.9453125
    171.48046875
    171.76171875
    172.22265625
    172.20703125
    172.52734375
    172.796875
    173.109375
    173.2265625
    173.359375
    173.65625
    173.99609375
    173.75
    173.78125
    173.83984375
    174.01171875
    174.17578125
    174.2578125
    174.30859375
    174.453125
    174.60546875
    174.8515625
    175.05078125
    175.16796875
    175.09765625
    175.1484375
    175.25390625
    175.37890625
    175.31640625
    175.3671875
    175.48828125
    175.47265625
    175.41796875
    175.39453125
    175.37890625
    175.51171875
    175.4921875
    175.5390625
    175.76953125
    175.76171875
    175.7734375
    175.76171875
    180.125
    180.30078125
    180.5078125
    180.640625
    180.58984375
    180.56640625
    180.60546875
    180.67578125
    180.62890625
    180.65234375
    180.69140625
    180.7421875
    180.8828125
    180.83984375
    180.78125
    180.81640625
    180.2265625
    180.38671875
    180.41796875
    180.4453125
    180.453125
    180.515625
    180.5234375
    180.453125
    180.4921875
    180.5
    180.5703125
    180.73046875
    180.72265625
    180.66796875
    180.67578125
    180.73046875
    180.7890625
    180.6796875
    …
    

    which shows that the leak is ~stable/not happening (this example run was with parallel checks disabled)

  • To derive a list of retained objects (i.e. to see the actual leaked Fiber objects), run:
    podman compose exec -e TEST_COUNT=500 -e PATH_TO_HIT=/health app bundle exec derailed exec perf:objects > objects

    Some basic differential analysis on running it 1/10/50 times showed the leak pretty easily:

    Excel spreadsheet showing monitor being the only gem with growth, and showing it grew 88% over 10->50 runs

    And "retained memory by class" showed all of these were: 28440 Fiber

If you need any further information, please comment/@ me, happy to help.

With this commit, you can run:

`podman compose exec -e TEST_COUNT=1_000 -e PATH_TO_HIT=/health app bundle exec derailed exec perf:mem_over_time 1>out1.log 2>err1.log`

and see a memory leak when parallel checks are enabled.
@awilfox
awilfox requested a review from danschmidt5189 August 3, 2026 19:28
@awilfox awilfox self-assigned this Aug 3, 2026
# Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true
config.hosts << 'app.test'
config.hosts = []

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was necessary to make the derailed tests work.

Comment thread config/application.rb
@@ -1,5 +1,7 @@
# Read Docker secrets into the environment
Dir['/run/secrets/*'].each do |filepath|
next unless File.file?(filepath)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was so that the app ran in Podman.

Comment thread compose.yml
Comment on lines +29 to +31
extra_hosts:
- geoservices.lib.berkeley.edu:128.32.10.252
- spatial.lib.berkeley.edu:128.32.10.252

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on our Zoom call, this is a workaround for the fact that Verizon's DNS server was rate limiting my resolution of these domains and eventually returning NODATA.

Comment thread compose.yml
- SOLR_URL=http://solr:8983/solr/geodata-test
- GEODATA_SPATIAL_HEALTHCHECK_URL=https://spatial.lib.berkeley.edu/public/berkeley-status/data.zip
- GEODATA_GEOSERVER_PUBLIC_HEALTHCHECK_URL=https://geoservices.lib.berkeley.edu/geoserver/wms?service=WMS&request=GetCapabilities
- GEODATA_GEOSERVER_SECURE_HEALTHCHECK_URL=https://geoservices.lib.berkeley.edu/geoserver/wms?service=WMS&request=GetCapabilities

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically overrode the secure URL with the public one because any error from the health check kills the memory test early.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant