Skip to content

[Bug]: plt.savefig leaks the stack #25406

Open
@CorentinJ

Description

@CorentinJ

Bug summary

Calling plt.savefig leaks local variables from parent calling functions. These can be found in gc.get_objects() and are cleared by gc.collect()

Code for reproduction

import gc
import matplotlib.pyplot as plt


class SomeObject:
    pass

def save_plots():
    plt.plot([1, 2, 3])
    plt.savefig("test.png")

def leaky():
    some_object = SomeObject()
    save_plots()

leaky()

for obj in gc.get_objects():
    try:
        if isinstance(obj, SomeObject):
            print("Object is leaking")
    except:
        pass

Actual outcome

Object is leaking

Expected outcome

Nothing should be printed.

Additional information

  • I initially found this bug because I realized my deep learning training loop was leaking VRAM. Torch tensors were being kept in memory when Figure.savefig was called
  • I am under the impression that ExitStack within savefig is meant to hack around this issue but is somehow not working in my case?
  • I have been through issue [Bug]: plt.figure(), plt.close() leaks memory #23701, but here I am able to provide a short and reproducible example
  • I have been through Memory leaks on matplotlib 3.4.2 (and 3.4.0) #20490 as well, but the issue persists with the agg backend
  • It is not acceptable to have to call gc.collect(). Most users won't be aware of the issue. Given the prevalence of deep learning these days, it's likely objects leaking into GPU memory will be a common problem due to this bug.

Operating system

Win10 x64

Matplotlib Version

3.7.1

Matplotlib Backend

TkAgg

Python version

3.10.0

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions