Memory not properly freed between changes an preview refresh
Selur opened this issue · 11 comments
Build latest version from git to test.
Using:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import ctypes
import sys
import os
core = vs.core
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# Loading Support Files
Dllref = ctypes.windll.LoadLibrary("F:/Hybrid/64bit/vsfilters/Support/libfftw3f-3.dll")
# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/libsangnom.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/EEDI2.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SharpenFilter/AWarpSharp2/libawarpsharp2.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DebandFilter/Neof3kdb/neo-f3kdb.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/TTempSmooth/TTempSmooth.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/DCTFilter.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DeblockFilter/Deblock/Deblock.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/FFT3DFilter/fft3dfilter.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/CTMF/CTMF.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/libmvtools_sf_em64t.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/TCanny.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/FluxSmooth/libfluxsmooth.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DerainbowFilter/BiFrost/libbifrost.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/DePan.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/GrainFilter/RemoveGrain/RemoveGrainVS.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/GrainFilter/AddGrain/AddGrain.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/DFTTest/DFTTest.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/NEO_FFT3DFilter/neo-fft3d.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/EEDI3m.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/ResizeFilter/nnedi3/vsznedi3.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/libmvtools.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/scenechange.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/fmtconv.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/MiscFilter/MiscFilters/MiscFilters.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DeinterlaceFilter/Bwdif/Bwdif.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DerainbowFilter/DeCross/libdecross.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/d2vSource/DGDecode.dll")
# Import scripts
import mvsfunc
import muvsfunc
import G41Fun
import lostfunc
import adjust
import havsfunc
import validate
# Source: 'C:\Users\Selur\Desktop\Sample\Sample.mpg'
# Current color space: YUV420P8, bit depth: 8, resolution: 720x480, frame rate: 29.97fps, scanorder: top field first, yuv luminance scale: limited, matrix: 470bg
# Loading C:\Users\Selur\Desktop\Sample\Sample.mpg using DGDecode
clip = core.dgdecode.MPEG2Source("J:/tmp/mpg_65ef6c100374fd10d8d2d894338abe7e_853323747.d2v",info=3)# 29.97 fps, scanorder: top field first
frame = clip.get_frame(0)
# Setting detected color matrix (470bg).
clip = core.std.SetFrameProps(clip=clip, _Matrix=5)
# setting color transfer (170), if it is not set.
if validate.transferIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Transfer=6)
# setting color primaries info (to 470), if it is not set.
if validate.primariesIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Primaries=5)
# setting color range to TV (limited) range.
clip = core.std.SetFrameProps(clip=clip, _ColorRange=1)
# making sure frame rate is set to 29.97fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
# making sure the detected scan type is set (detected: top field first)
clip = core.std.SetFrameProps(clip=clip, _FieldBased=2) # tff
# rainbow removal using DeCross
clip = core.decross.DeCross(clip=clip)
# Deinterlacing using QTGMC
clip = havsfunc.QTGMC(Input=clip, Preset="Fast", TFF=True) # new fps: 29.97
# Making sure content is preceived as frame based
clip = core.std.SetFrameProps(clip=clip, _FieldBased=0) # progressive
clip = clip[::2] # selecting previously even frames
# adjusting color using Tweak
clip = adjust.Tweak(clip=clip, hue=0.01, sat=1.00, cont=1.00, coring=True)
# Fixing chroma bleeding using FixChromaBleedingMod
clip = havsfunc.FixChromaBleedingMod(input=clip)
clip = havsfunc.Vinverse(clp=clip)
# stabilizing using Stab
clip = lostfunc.Stab(clp=clip,range=0,mirror=15)
# rainbow removal using BiFrost
clip = core.bifrost.Bifrost(clip=clip, variation=3, interlaced=False)
# removing grain using STPresso
clip = havsfunc.STPresso(clp=clip, planes=[0])
# removing grain using TemporalDegrain2
clip = G41Fun.TemporalDegrain2(clip=clip, degrainPlane=4, meAlgPar=False, postFFT=0, fftThreads=1)
# denoising using MCTemporalDenoise
clip = havsfunc.MCTemporalDenoise(i=clip, settings="medium", ncpu=1)
# debanding using f3kdb
clip = core.neo_f3kdb.Deband(clip, y=45, cb=44, cr=45, grainy=35, grainc=44, dither_algo=1, keep_tv_range=True, output_depth=8)
# sharpening using AWarpSharp2
clip = core.warp.AWarpSharp2(clip=clip, thresh=64, blur=2, chroma=True, planes=[1,2])
clip = muvsfunc.BlindDeHalo3(clip, strength=25, sharpness=0.01, interlaced=False)
# deringing using HQDeringmod
clip = havsfunc.HQDeringmod(clip, nrmode=2, darkthr=3.0)
# line darkening using Toon
clip = havsfunc.Toon(input=clip,str=0.25)
# applying anti aliasing using santiag
clip = havsfunc.santiag(c=clip, nns=3, pscrn=2, aa=34)
# adding Grain using AddGrain
clip = core.grain.Add(clip=clip, var=0.00, uvar=0.30, constant=True)
# adjusting output color from: YUV420P8 to YUV420P10 for NVEncModel
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P10, range_s="limited")
# set output frame rate to 29.97fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
# output
clip.set_output()
whenever I change something (for example the values of neo_f3kdb.Deband ) and refresh the preview, ram usage increases by ~450MB
Thanks for reporting. I can reproduce since the commit bfc002e . Could you check if the latest commit helps, especially when using a CUDA filter with fixed size VRAM allocation?
That does seem to help, I also noticed, that this only happens when
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DerainbowFilter/BiFrost/libbifrost.dll")
from https://github.com/dubhater/vapoursynth-bifrost is used.
The bifrost plugin looks good to me without a memory issue. I checked with a clip with big dimensions so that the memory change is evident enough.
Strange, if I remove BiFrost from my script the memory leak from refreshing basically goes away.
Just now on another PC I confirmed that VRAM allocated by filters is freed in the release build (6.6). This means filters are correctly freed on F5 refresh. But possibly, due to an unknown issue, the core is not freed. BiFrost is a temporal filter that relies on frame caches, which is managed by the core. Maybe that explains what you found.
Hmm,.. so it might be a bug in Vapoursynth itself?
Even when using a simple script as:
import vapoursynth as vs
core = vs.core
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/LSMASHSource.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DerainbowFilter/BiFrost/libbifrost.dll")
clip = core.lsmas.LWLibavSource(source="G:/TestClips&Co/files/test.avi")
clip = core.bifrost.Bifrost(clip=clip, interlaced=False)
clip.set_output()
I see the RAM usage of vedit increase by ~18MB per refresh.
If it's merely 18MB then nobody else would think it's a problem..
With this script sure, but my initial script it's 450mb per reload, which might be more concerning for most users. ;)
Replace bifrost with some other stupid temporal filter like the widely despised temporalsoften2. See if it still leaks. It may be one of gazillion filters before or after.
@myrsloik :
it happens with:
import vapoursynth as vs
core = vs.core
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/LSMASHSource.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DerainbowFilter/BiFrost/libbifrost.dll")
clip = core.lsmas.LWLibavSource(source="G:/TestClips&Co/files/test.avi")
clip = core.bifrost.Bifrost(clip=clip, interlaced=False)
clip.set_output()
(no gazillion filters before or after)
with:
import vapoursynth as vs
core = vs.core
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/LSMASHSource.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/DenoiseFilter/TemporalSoften2/libtemporalsoften2.dll")
clip = core.lsmas.LWLibavSource(source="G:/TestClips&Co/files/test.avi")
clip = core.focus2.TemporalSoften2(clip=clip)
clip.set_output()
it does not happen.
Core freed but 2 filter instance(s) still exist
I did miss interlaced=False
in my tests. Now I can reproduce the memory leak from the plugin. Otherwise there's a ~2MB memory increment on each F5 refresh (which I thought was referring to your 18MB claim).