Skip to content

Memory leak in update task, retained heap of lmcoursier.internal.SbtUpdateReport$ grows linearly #8142

@mrdziuban

Description

@mrdziuban

steps

  1. Clone https://github.com/mrdziuban/sbt-update-memory-leak
  2. cd into it
  3. Run a couple commands:
    # Run 10 updates, then 50 updates
    ./run.sh 10
    ./run.sh 50
  4. Open the heap dumps that were output to the heap-dumps directory. You can either use Eclipse Memory Analyzer or VisualVM
    1. Using Eclipse Memory Analyzer
      1. Click File > Open Heap Dump...
      2. Navigate to /path/to/sbt-update-memory-leak/heap-dumps
      3. Open sbt-10-updates.hprof
      4. Under "Actions" click on "Dominator Tree"
      5. Look for the row where the Class Name is class lmcoursier.internal.SbtUpdateReport$ and take note of the Retained Heap value
      6. Repeat steps a-e, but this time opening sbt-50-updates.hprof
    2. Using VisualVM
      1. Click File > Load...
      2. Navigate to /path/to/sbt-update-memory-leak/heap-dumps
      3. Open sbt-10-updates.hprof
      4. Under "Dominators by Retained Size" click "Compute Retained Sizes" and wait for it to complete
      5. Next to "Dominators by Retained Size" click "view all"
      6. Look for the row where the Name is class lmcoursier.internal.SbtUpdateReport$ and take note of the Retained value
      7. Repeat steps a-f, but this time opening sbt-50-updates.hprof
  5. Calculate the difference between the retained heap after 10 updates vs. after 50 updates -- you'll see that after 50 updates, there is ~5x more retained heap

problem

The retained heap size of lmcoursier.internal.SbtUpdateReport$ grows linearly with the number of times update is run. On my laptop I ran run.sh with values of 10, 20, 50, 100, and 500. The retained heap of lmcoursier.internal.SbtUpdateReport$ for each was:

Number of updates Retained heap Δ from 10 updates
10 5,317,936 bytes --
20 10,685,776 bytes 2.01x
50 26,775,392 bytes 5.03x
100 53,600,336 bytes 10.08x
500 268,214,744 bytes 50.44x

expectation

The retained heap of lmcoursier.internal.SbtUpdateReport$ should remain fairly consistent with the number of updates that are run. Better yet, whatever it's currently retaining could be garbage collected.

notes

The linked repository also includes a script to show that enough updates will eventually cause an out of memory error. You can run it with

./oom.sh

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions