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 leak with open_video_out #359

Open
yakir12 opened this issue May 20, 2022 · 8 comments
Open

Memory leak with open_video_out #359

yakir12 opened this issue May 20, 2022 · 8 comments

Comments

@yakir12
Copy link
Contributor

yakir12 commented May 20, 2022

When encoding a video with large frames, Julia crashes because the system runs out of memory.
I made the following MWE to illustrate this (I stole @yiyuezhuo get_memory_usage function from this gist, thank you yiyuezhuo!)

using VideoIO, ColorTypes, FixedPointNumbers
function get_memory_usage()
    open("/proc/$(getpid())/statm") do io
      parse(Int, split(read(io, String))[1])
    end            
end
n = 20
y = zeros(Int, n)
sz = (3840, 2*2160)
frame = rand(RGB{N0f8}, sz)
encoder_options = (crf=23, preset="medium")
framerate = 300
open_video_out("video.mp4", frame, framerate=framerate, encoder_options=encoder_options) do writer
  for i in 1:n
    frame = rand(RGB{N0f8}, sz)
    write(writer, frame)
    y[i] = get_memory_usage()
  end
end
using UnicodePlots
lineplot(y)

which looks like this:

          ┌────────────────────────────────────────┐ 
  2100000 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠊⠉│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠤⠤⠃⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡔⠁⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠔⠒⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠊⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⠀⢀⠤⠔⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠀⠀⡔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          │⠀⠀⠔⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
  1700000 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
          └────────────────────────────────────────┘ 
          ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀20⠀ 
@IanButterworth
Copy link
Member

What if you put a gc safepoint in the loop?

@yakir12
Copy link
Contributor Author

yakir12 commented May 20, 2022

Sorry, I forgot to mention I already tried that. I added

Base.GC.gc()

to the loop but it didn't have any affect. Maybe "gc safepoint" refers to something else?

@IanButterworth
Copy link
Member

I mean GC.safepoint() but what you did is the more explicit option to test the same thing.

Is the memory still retained after close and a sleep?

@yakir12
Copy link
Contributor Author

yakir12 commented May 20, 2022

Not sure what exactly you mean by close and sleep, but if I have more than 20 frames in the example above then Julia crashes and the memory is released. If I am careful and use only 20 frames, then the memory isn't released before I exit that Julia session.

1 similar comment
@yakir12
Copy link
Contributor Author

yakir12 commented May 20, 2022

Not sure what exactly you mean by close and sleep, but if I have more than 20 frames in the example above then Julia crashes and the memory is released. If I am careful and use only 20 frames, then the memory isn't released before I exit that Julia session.

@IanButterworth
Copy link
Member

IanButterworth commented May 20, 2022

I see the same and it's freed after close and GC

julia> begin
           n = 20
           y = zeros(Int, n)
           sz = (3840, 2*2160)
           frame = rand(RGB{N0f8}, sz)
           encoder_options = (crf=23, preset="medium")
           framerate = 300
           open_video_out("video.mp4", frame, framerate=framerate, encoder_options=encoder_options) do writer
               for i in 1:n
                   write(writer, frame)
                   @show Base.format_bytes(get_memory_usage())
               end
           end
           @show Base.format_bytes(get_memory_usage())
           GC.gc()
           @show Base.format_bytes(get_memory_usage())
           nothing
       end
Base.format_bytes(get_memory_usage()) = "4.256 MiB"
Base.format_bytes(get_memory_usage()) = "4.286 MiB"
Base.format_bytes(get_memory_usage()) = "4.293 MiB"
Base.format_bytes(get_memory_usage()) = "4.322 MiB"
Base.format_bytes(get_memory_usage()) = "4.352 MiB"
Base.format_bytes(get_memory_usage()) = "4.347 MiB"
Base.format_bytes(get_memory_usage()) = "4.377 MiB"
Base.format_bytes(get_memory_usage()) = "4.407 MiB"
Base.format_bytes(get_memory_usage()) = "4.402 MiB"
Base.format_bytes(get_memory_usage()) = "4.431 MiB"
Base.format_bytes(get_memory_usage()) = "4.461 MiB"
Base.format_bytes(get_memory_usage()) = "4.456 MiB"
Base.format_bytes(get_memory_usage()) = "4.486 MiB"
Base.format_bytes(get_memory_usage()) = "4.516 MiB"
Base.format_bytes(get_memory_usage()) = "4.511 MiB"
Base.format_bytes(get_memory_usage()) = "4.540 MiB"
Base.format_bytes(get_memory_usage()) = "4.570 MiB"
Base.format_bytes(get_memory_usage()) = "4.565 MiB"
Base.format_bytes(get_memory_usage()) = "4.595 MiB"
Base.format_bytes(get_memory_usage()) = "4.624 MiB"
Base.format_bytes(get_memory_usage()) = "4.630 MiB"
Base.format_bytes(get_memory_usage()) = "1.005 MiB"

@yakir12
Copy link
Contributor Author

yakir12 commented May 20, 2022

So is this expected?

@galenlynch
Copy link
Collaborator

galenlynch commented May 20, 2022 via email

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

No branches or pull requests

3 participants