JuliaPy / PyCall.jl

Package to call Python functions from the Julia language
MIT License
1.47k stars 187 forks source link

Memory leak with pyplot #1019

Open gabrevaya opened 1 year ago

gabrevaya commented 1 year ago

When I create matplotlib.pyplot plots, the memory keeps increasing and is not released by the garbage collector. The following is the case I'm interested in (with subplots) and bellow I include a more basic MWE.

Example with subplots ```julia using PyCall plt = pyimport("matplotlib.pyplot") function test_pyplot() for i in 1:10000 @info i z = rand(4, 50) ẑ = rand(4, 50) fig, axs = plot_pyplot(z, ẑ) end end function plot_pyplot(z, ẑ) # plt = pyimport("matplotlib.pyplot") N = Int(size(z, 1)/2) fig, axs = plt.subplots(2, N) for i in 1:N axs[1,i].plot(z[i,:], label = "true") axs[1,i].plot(ẑ[i,:], label = "model") axs[2,i].plot(z[i+N,:], label = "true") axs[2,i].plot(ẑ[i+N,:], label = "predicted") axs[2,i].set_xlabel("time steps") axs[i].grid(true) axs[i+N].grid(true) axs[i+N].label_outer() axs[i].label_outer() end # plt.close() return fig, axs end test_pyplot() ```

I tried defining plt and closing it inside the plot_pyplot function (commented lines) but it doesn't solve the memory leak.

Here you have a simpler MWE:

using PyCall
plt = pyimport("matplotlib.pyplot")

plot_pyplot(z) = plt.plot(z)

function test_pyplot()
    for i in 1:1000000
        @info i
        z = rand(50)
        fig = plot_pyplot(z)
    end
end
Version info and status ```julia julia> versioninfo() Julia Version 1.8.2 Commit 36034abf260 (2022-09-29 15:21 UTC) Platform Info: OS: macOS (arm64-apple-darwin21.3.0) CPU: 8 × Apple M1 Pro WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-13.0.1 (ORCJIT, apple-m1) Threads: 1 on 6 virtual cores ``` ```julia (memory_leak) pkg> st Status `~/Documents/issues/memory_leak/Project.toml` [438e738f] PyCall v1.94.1 ```

I need to use pyplot directly from PyCall.jl and not through PyPlot.jl because I need to pass the fig object to Wandb.jl. Actually, maybe I could get that object from PyPlot.jl, I didn't try that yet. But since I found the bug here, I think it can be helpful to report it anyway.

itayass commented 1 year ago

I had a similar issue, adding

@pyimport matplotlib
matplotlib.use("Agg")

before plotting solved the issue.