Author Topic: Chasing Memory Leaks  (Read 1029 times)

Wayne McHugh

  • Posts: 91
Chasing Memory Leaks
« on: 12 Aug '24 - 09:12 »
I noticed, when I set my MIDI player to play a long playlist straight through that it was leaking a lot of memory.  I've spent a small age chasing down the leaks until I've come down to one, the memory that gets used when I call
m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, getVSTiPlugin()->getPluginFilePath(), BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);
does not get released when I call
BASS_VST_ChannelFree(m_hVST_stream);

Just under 15M of the heap is taken when I call BASS_VST_ChannelCreate, but only .71K is released when I call BASS_VST_ChannelFree.  In the destruction process, the VST_ChannelFree call comes before any other BASS/BASMIDI/BASSVST release related call.  When all the dust has settled, I I am down by the amount of memory I expected would be released by BASS_VST_ChannelFree.

I am not activating the VSTi console, so hopefully that isn't coming into play.  I haven't spotted anything in the forums or docs that helps me get past this. Are there any likely culprits for this memory leak?

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #1 on: 12 Aug '24 - 13:23 »
The BASS_CONFIG_HANDLES value (from BASS_GetConfig) can be useful for detecting leaks. That tells you how many HMUSIC/HRECORD/HSAMPLE/HSTREAM handles exist (includes VSTi), so if it's rising over time then there may some handles that are never being freed, in which case you can try logging all handle creation and freeing to find out which it is.

If BASS_CONFIG_HANDLES doesn't show a handle leak, then are you having the problem with a particular VSTi or all? If you try creating and freeing the VSTi channel multiple times, does it appear to leak the same amount each time or only the first time?

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #2 on: 13 Aug '24 - 06:38 »
Hi Ian.  What an interesting time I've had investigating the answers to your questions.  It turns out the answers are quite straight forward, though perhaps not helpful.
1. The handle count was correct.  The correct number were created and destroyed.
2. I have (finally) tested several of the VSTi's I'm using, and every one of them leaks identically.  A different amount of memory is involved, but on destruction I get back .71k.  It feels like a pointer or a structure is being released, but not everything that lies behind that pointer or structure. Anyway, that is a guess based purely on the tiny amount released.
3. I just ran a static create/destroy test.  You can see the test in the two images attached.  There are three calls in my primary VSTi setup.  I copied the releases directly from my destructor and put them immediately after the creates, inserted 5sec sleeps to ensure the work is done before measuring - repeated 3 times to establish the pattern, and took heap measurements after each block.  You'll see (far right) that there is a minor discrepancy (that is a question on its own), but at least most of what was claimed is released.  If I leave it to the destructor, I get back .71K.  So it essentially works, but the question then remains - what can cause the releases to succeed (because they report success) but not release the memory under their control?

Falcosoft

  • Posts: 203
Re: Chasing Memory Leaks
« Reply #3 on: 13 Aug '24 - 11:59 »
Hi,
I do not know if this can explain all your 'leaks' fully but one thing is sure:
The very first call to BASS_VST_ChannelCreate() not only creates the necessary Bass stream but it also has to load the plugin dll. In case of Windows this means calling LoadLibrary(). Loadlibrary loads the plugin into the address space of your executable together with all resources needed by the library. This can be seen as additional used memory by your executable.
And BASS_VST_ChannelFree() does NOT unload the loaded plugin library, it only frees the Bass stream handle, nothing more. In case of Windows this means that FreeLibrary() is not called by BASS_VST_ChannelFree().

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #4 on: 13 Aug '24 - 12:09 »
Hi Falcosoft. That is why I largely ignore the first call to BASS_VST_ChannelCreate(). Instead my testing is repeated load and unload, watching the heap through developer studio snapshots. If I release after load I get almost all memory back. If I leave it to its proper release I get virtually nothing back.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #5 on: 13 Aug '24 - 14:32 »
BASS_VST does unload freed VST(i) (eg. calls FreeLibrary) but only after a 10s delay, so perhaps that delay explains what you're seeing? You could try disabling it with a new BASS_VST_NODELAYUNLOAD flag, which was introduced in an update posted here:

   www.un4seen.com/forum/?topic=20170.msg141216#msg141216

Btw, it looks like the handles in your BASS_StreamFree and BASS_VST_ChannelFree calls are the wrong way round? Not a big deal because BASS_VST_ChannelFree actually simply calls BASS_StreamFree, so you could just always use the latter.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #6 on: 13 Aug '24 - 21:23 »
I know I didn't give you much to go on.  I continued experimenting with the early release, since it released most of the memory if applied immediately after creating the streams. I pushed my early release code further and further down the execution path, hoping I would find the point at which it failed to release the memory.  I was successful.  There was a place where I was inadvertently setting chunk data to an empty string.  It did not display any error, stop any VSTi from running, and it did not stop the VSTi console displaying, nor malfunction in any way except that releases on the VST stream no longer released the memory associated with the stream.  It was a careless error, but perhaps useful to expose the behaviour if it does happen.

Having eliminated the error, there is now only a relatively slow leak of memory.  Running a song with 6 of 7 channels running VSTi and one channel running an SF2 instrument, measuring from the second load (acknowledging the first run carries base load), my app runs idle (no song loaded) at 72M, and jumps to 1286M running this song, drops to 96.7M (after the 10sec wait). Subsequent load/run/remove results in an idle memory footprint of (M) 117.8, 142.6, 168.2, 191.1, 211.0, 222.5, which maps as increases of (M) 24.1, 21.1, 24.8, 25.6, 22.9, 19.9 and 11.5.  In the meantime, running footprints went from 1280M to 1380M, which is 100M, a little less than the idle increase.

I will look a little longer to see if I can explain the continuing leak of memory, and if I learn anything useful I'll report it back here.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #7 on: 14 Aug '24 - 12:07 »
Memory leaks are tricky to track in a system of many moving parts - moving even when the system is sitting still.

I have run a test, and I'd like to know

1) is it legitimate to create and free a VST stream and expect the free to get back the memory that create used. If it is not, then how is the memory retrieved such that the system isn't just using more and more memory without letting it go, and
2) is this test of repeatedly running the following code and watching heap snapshots a valid way of demonstrating the leak of memory:
   m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, getVSTiPlugin()->getPluginFilePath(), BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);
   BASS_StreamFree(m_hVST_stream);
   Sleep(15000);

In the first attachment you can see on the lower right panel the snapshot summaries.  Once setup leveled off you can see the create takes about 1.2M more than the free sets free.
The second version of the test ran from free to free, snapping the nett movement. Almost the entire way, there were 11 unresolved allocations amounting to 1311,048 bytes, as shown in the second image.  This is 11 memory allocations out of 5,400, but on this VSTi it amounts to 1.2M of memory lost each time.  This VSTi is SI-DrumKit, the free drumkit plugin available with Cakewalk.  I got exactly same same results with SI-BassGuitar.  However I had much bigger numbers with Addictive Keys (demo), the biggest of the VSTi's I'm using.  Each create/release saw a discrepancy of nearly 79,000 memory allocations amounting to around 10M of lost memory each time.

Still using Addictive Keys, I've then added the same song into my playlist about 8 times and played through them watching the memory usage in Windows task manager.  While the numbers jump around more, they are averaging an increase of about 14M per song.  So there is likely more to be found, but it seems most likely the 10M increase I measured earlier is real in the broader context.

Is there a memory leak in BASS_VST_ChannelCreate / BASS_VST_ChannelFree?  If not, how is the memory I'm losing meant to be recovered?

That is the best information I have at this stage.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #8 on: 14 Aug '24 - 17:44 »
1) is it legitimate to create and free a VST stream and expect the free to get back the memory that create used. If it is not, then how is the memory retrieved such that the system isn't just using more and more memory without letting it go, and

The memory should be free for reuse, but that might not (all) show in the process's memory info. For example, freed memory might be held by the run-time library and it'll be reused when the app requests some. So to detect a leak, you should repeatedly allocate and free resources, and see if the usage keeps climbing.

2) is this test of repeatedly running the following code and watching heap snapshots a valid way of demonstrating the leak of memory:
   m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, getVSTiPlugin()->getPluginFilePath(), BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);
   BASS_StreamFree(m_hVST_stream);
   Sleep(15000);

Yes, doing that should be good for detecting a leak.

In the first attachment you can see on the lower right panel the snapshot summaries.  Once setup leveled off you can see the create takes about 1.2M more than the free sets free.
The second version of the test ran from free to free, snapping the nett movement. Almost the entire way, there were 11 unresolved allocations amounting to 1311,048 bytes, as shown in the second image.  This is 11 memory allocations out of 5,400, but on this VSTi it amounts to 1.2M of memory lost each time.  This VSTi is SI-DrumKit, the free drumkit plugin available with Cakewalk.  I got exactly same same results with SI-BassGuitar.  However I had much bigger numbers with Addictive Keys (demo), the biggest of the VSTi's I'm using.  Each create/release saw a discrepancy of nearly 79,000 memory allocations amounting to around 10M of lost memory each time.

Still using Addictive Keys, I've then added the same song into my playlist about 8 times and played through them watching the memory usage in Windows task manager.  While the numbers jump around more, they are averaging an increase of about 14M per song.  So there is likely more to be found, but it seems most likely the 10M increase I measured earlier is real in the broader context.

Is there a memory leak in BASS_VST_ChannelCreate / BASS_VST_ChannelFree?  If not, how is the memory I'm losing meant to be recovered?

If BASS_CONFIG_HANDLES shows no leak then that means BASS_VST is at least feeing its BASS resources, but I'm not very familiar with the workings of VST, so I can't say for certain about all that stuff. Are are you seeing the leaks even with the simple BASS_VST_ChannelCreate+BASS_StreamFree code above, and is it affecting all VSTi or only some? You could try the BASS_VST_NODELAYUNLOAD flag that I mentioned earlier and see if that changes things.

If you would like to look for leaks, the BASS_VST source code is available here:

   https://github.com/r10s/BASS_VST/tree/master

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #9 on: 14 Aug '24 - 20:35 »
Thanks Ian. It happens with every VSTi I’m using. With the repeated create/free test it climbs by almost the same amount each time, though by a different amount for different vst’s.  I will try the flag, but that allowance was the reason for the 15sec sleep on each iteration of the test. I will also try to bring in the vst source code for the test, but it might be delayed into next week.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #10 on: 14 Aug '24 - 22:46 »
The DLL provided for BASS_VST_NODELAYUNLOAD breaks my player. With no change to my coding, the VST instrument doesn't play. My existing BASSVST dll was 2.4.1.0.  My development platform is Windows 64 bit.
« Last Edit: 15 Aug '24 - 08:14 by Wayne McHugh »

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #11 on: 15 Aug '24 - 12:42 »
I would love to build the bass_vst source and go hunting for my memory leak. The github project says I need:
  • bass-addon.h which I couldn't find on un4seen.com
  • aeffectx.h, which I couldn't find on steinberg.net

I found these files in another github project, and took copies on the outside chance they don't change and haven't been changed. aeffectx.h includes aeffect.h, which is not suggested, so I grabbed it as well.  These files shouldn't be changed, given they are meant to be definitive.

bass-addon.h is 6,321 bytes and its header comments are:
/*
   BASS 2.4 add-on C/C++ header file
   Copyright (c) 2003-2008 Un4seen Developments Ltd.
*/

Does this stack up as the right file?  I'm yet to have time to try and build the library yet.  Available time taken trying to source the files needed.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #12 on: 15 Aug '24 - 13:12 »
The DLL provided for BASS_VST_NODELAYUNLOAD breaks my player. With no change to my coding, the VST instrument doesn't play. My existing BASSVST dll was 2.4.1.0.  My development platform is Windows 64 bit.

Oh, that's strange. Are any calls failing, eg. BASS_VST_ChannelCreate? Also confirm what flags you're using. That update does also have some changes relating to SPEAKER flags.

I would love to build the bass_vst source and go hunting for my memory leak. The github project says I need...

I don't think the VST2 SDK is publicly available these days. I'll PM the files to you.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #13 on: 15 Aug '24 - 23:07 »
Quote
BASS_VST_ChannelCreate? Also confirm what flags you're using.
All calls return a handle, and code execution follows it's proper path. I've traced it to the notes being sent and all looks good, but no sound.
chan = BASS_MIDI_StreamCreateFile(FALSE, this->getFilename(), 0, 0, BASS_MIDI_ASYNC | BASS_MIDI_DECAYEND | BASS_SAMPLE_FLOAT, 44100);
m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, getVSTiPlugin()->getPluginFilePath(), BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);

I have just seen, allowing it to run on, eventually I get an error message popup:
BASS_VST_ProcessEvent(hVST_Stream, event->chan, event->event, event->param)
fails, and my messagebox reports "Error sending VST event 1, note 53, error 1."

Is it possible VST events are not being processed, and are queuing until the queue reaches its limit, hence this message?

On the BASS-Addon build, I'm using MS Developer Studio 2022 and when trying to build it reports that it requires the 2017 compiler toolset. Develooper Studio is supposed to offer me the option of upgrading to the latest toolset, but it doesn't.  Is it wired to an older toolset?  I'm a learner outside my normal confines, so I don't really know where to poke.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #14 on: 16 Aug '24 - 15:46 »
All calls return a handle, and code execution follows it's proper path. I've traced it to the notes being sent and all looks good, but no sound.
chan = BASS_MIDI_StreamCreateFile(FALSE, this->getFilename(), 0, 0, BASS_MIDI_ASYNC | BASS_MIDI_DECAYEND | BASS_SAMPLE_FLOAT, 44100);
m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, getVSTiPlugin()->getPluginFilePath(), BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);

I have just seen, allowing it to run on, eventually I get an error message popup:
BASS_VST_ProcessEvent(hVST_Stream, event->chan, event->event, event->param)
fails, and my messagebox reports "Error sending VST event 1, note 53, error 1."

Is it possible VST events are not being processed, and are queuing until the queue reaches its limit, hence this message?

Ah, I think I see what it is now. That update also added some processing buffer allocation tweaks, which aren't working properly when the VST has 0 inputs, eg. a VSTi. Here's another update that should fix that:

   www.un4seen.com/stuff/bass_vst.zip

Let me know if it still isn't working properly for you.

On the BASS-Addon build, I'm using MS Developer Studio 2022 and when trying to build it reports that it requires the 2017 compiler toolset.

It should be possible to change that in the project's "Platform Toolset" setting in its "General" properties page.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #15 on: 17 Aug '24 - 01:48 »
That new bass_vst.dll file got my playing playing VSTi again.  The same amount of memory is lost on each create/free iteration as before.

I'm working on getting the debug bass_vst made and working.  I come down to an unresolved external bassfunc.  I cannot find what delivers the implementation of that function, so the extern can be resolved.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #16 on: 19 Aug '24 - 16:45 »
Ah. The BASS_VST code is expecting an older version of the BASS add-on API, which imports the BASS functions a different way. With a newer version, try adding this line at the start of the mainInit function:

Code: [Select]
const BASS_FUNCTIONS *bassfunc;

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #17 on: 23 Aug '24 - 03:14 »
Sorry ... this is a bit long.

I have minimised my memory loss and loading speed problems by creating a pool of VST Streams, creating one VST stream per VSTi on startup.  When I finish a song I release the VST channel and DSP handles, but instead of freeing the VST stream I make it available again in the pool.  The result: no memory leaks, however the pool can grow to a size larger than I would like to keep, so I would like to implement a cull on the pool, and sadly that will reintroduce the memory leak.

So ... I successfully got bass_vst to debug build, and I'm able to debug with it in my app - thank you for the help to get that far.  Now to comment on the reported leaks (using MS Developer Studio 2022 heap snapshots).

I have created an infinite loop, thus:

Quote
m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, lpszFilePath, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);
while (true)
{
   BASS_VST_ChannelFree(m_hVST_stream);
   Sleep(10000);
   m_hVST_stream = BASS_VST_ChannelCreate(44100, 2, lpszFilePath, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE);
}

... and I break after the sleep and then look at the heap differences (ignoring the first time, because of possible startup extras)

Because I do not have a debug version of BASS, I cannot investigate beyond BASS_VST.  My detailed testing was on the Addictive Keys VSTi. There are 79,050 "unresolved allocations" reported after the second snapshot, but they come from quite a small number of calls:

  • My call to BASS_VST_ChannelCreate(); traces as far as BASS_VST_ChannelCreateEx() where it calls BASS_StreamCreate() but I can trace no further.  This reports one single allocation of 128 bytes still allocated, which is of no consequence unless it's a pointer to something else that should get destroyed but is not.
  • BASS_VST_ChannelCreateEx() calls loadVstLibrary() after which the call stack takes me into the VSTi dll, which I can't debug.  This call is reported 78,910 times.  Most are for small amounts, but one is 2.3M.  Total 10,876,895 bytes.
  • BASS_VST_ChannelCreateEx() calls this_->aeffect->dispatcher(this_->aeffect, effMainsChanged, 0, 1/*resume*/, NULL, 0.0); after which the call stack disappears into the VSTi dll. This call is reported 7 times, accounting for only 401 bytes in total.
  • My call to BASS_Channel_Free routes through BASS and reappears in BASS_VST in the onChannelDestroy callback. The second unrefHandle() call to free the channel calls destroyHandle(ptrToDestroy); since the usage counter hits 0, which makes the call this_->aeffect->dispatcher(this_->aeffect, effClose, 0, 0, NULL, 0.0); - this call is reported 88 times, accounting for 4,719 bytes in total.

There are other miscellaneous memory allocations reported, but not every time.  The above get reported every time around my loop, and therefore appears to me to constitute a memory leak.  I tested the loop 12 times for this report, and heap usage jumped 10.5M (+/- 100k) each time.

I then tested Cakewalk's SI-Bass Guitar and SI_Drum kit. The first 128 bytes (1, above) was common, but only 2 (above) in addition, and not many of them.
I then tested Strum Session 2.  Again, 128 bytes (1, above), then quite a few of 2 (above), and then some belonging entirely to Strum Session 2, so not our concern.

An additional note that seemed a bit peculiar:
static VstIntPtr audioMasterCallbackImpl(...) called from this_->aeffect->dispatcher(this_->aeffect, effSetBlockSize, 0, sampleRate/*one second*/, NULL, 0.0); in LoadVSTLibrary()
- reported "plug called opcode #23" falling to default case for opcode  (only for the Addictive Keys VSTi)
- reported "plug called audioMasterWantMidi" called from this_->aeffect->dispatcher(this_->aeffect, effMainsChanged, 0, 1/*resume*/, NULL, 0.0); in LoadVSTLibrary()  (all VSTi's I tested)

Does that information make sense?  Does any of it trigger thoughts (apart from "I wish this guy would go away)?

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #18 on: 23 Aug '24 - 17:41 »
  • My call to BASS_VST_ChannelCreate(); traces as far as BASS_VST_ChannelCreateEx() where it calls BASS_StreamCreate() but I can trace no further.  This reports one single allocation of 128 bytes still allocated, which is of no consequence unless it's a pointer to something else that should get destroyed but is not.

This looks like some memory related to holding stream handles, which will be reused for later streams. There may be multiple such blocks, so you may see this "leak" multiple times but there should eventually be no more of them.

Regarding the others, are they all in the VSTi, or are you seeing some in BASS or BASS_VST too? I think removing the VSTi unloading delay would make things easier to track, and shouldn't be any need for "Sleep" then. You can add support for the BASS_VST_NODELAYUNLOAD option by making this change in the destroyHandle function:

Code: [Select]
if (this_->createFlags & BASS_VST_NODELAYUNLOAD)
{
#ifdef _WIN32
FreeLibrary(this_->hinst);
#elif __linux__
dlclose(this_->hinst);
#else
// CFBundleUnloadExecutable(this_->hinst); // causes a crash with some VST?
CFRelease(this_->hinst);
#endif
}
else
{
// unload the library delayed - otherwise we get some curious crashes here and there ...
// if the library is aleady pending, increase the unload counter
EnterCriticalSection(&s_idleCritical);
long oldVal = (long)sjhashFind(&s_unloadPendingInstances, this_->hinst, 0);

sjhashInsert(&s_unloadPendingInstances, this_->hinst, 0,
(void*)(oldVal + 1)/*pData*/);

s_unloadPendingCountdown = IDLE_UNLOAD_PENDING_COUNTDOWN;
createIdleTimers();
LeaveCriticalSection(&s_idleCritical);
}

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #19 on: 23 Aug '24 - 22:28 »
I added the code for immediate dll unload.

After 21 times around the loop, the 128 bytes from bass is no longer listed, as you predicted.  The other 3 remain pretty much identical.

loadVstLibrary(): this_->aeffect = (dllMainEntryFuncPtr)(audioMasterCallbackImpl);  Reports 78,959 allocations remaining, equals 10,876,431 bytes
loadVstLibrary(): this_->aeffect->dispatcher(this_->aeffect, effMainsChanged, 0, 1/*resume*/, NULL, 0.0); Reports 7 allocation remaining, equals 400 bytes
destroyHandle(): this_->aeffect->dispatcher(this_->aeffect, effClose, 0, 0, NULL, 0.0);  Reports 89 allocations remaining, equals 4,783 bytes

I then stepped 50 times around the loop, watching the memory graph grow roughly uniformly throughout, and took snapshots again at 50, 51 and 52. The memory increments were +10,663k and +10,10,627k - exactly as I've been seeing all along.

I think 50 times around the loop demonstrating a roughly constant increase each time demonstrates leaking memory.  The amount leaked is very different per VSTi, but I would expect that.

All the call stacks for these unreleased allocations end in the VSTi, not in BASS or BAS_VST.  I take that to mean it is not BASS or BASS_VST directly leaking memory.  However it could still mean something is not being called to release memory held by the VSTi.  I wish I could dig deeper, but this data is all I have at present.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #20 on: 27 Aug '24 - 17:33 »
To perhaps narrow it down a bit, do you also get leaks when using VST with BASS_VST_ChannelSetDSP, or only when using VSTi with BASS_VST_ChannelCreate?

I'll try playing around with the BASS_VST code myself and see if I find anything.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #21 on: 27 Aug '24 - 21:20 »
All my testing up until now has been exclusively with BASS_VST_ChannelCreate.  I've done the following test with BASS_VST_ChannelSetDSP.

Code: [Select]
int nCount = 0;
while (true)
{
BASS_ChannelRemoveDSP(m_hVST_channel, m_hVSTDSP);
Sleep(1);
nCount++;
m_hVSTDSP = BASS_ChannelSetDSP(m_hVST_channel, DSP_Callback, (VOID*)this, 0);
}
There is a slow leak, one of which tracks into BASS, of 48 bytes per time around the loop.  There is occasionally a nett zero, but they may be +BASS (48 bytes) minus something else (48 bytes).  However I let the loop run 1645 times and memory increase was 280k.  Stopped again at 2748 times around the loop, and it was +180k.  So it is slow but constant, and so small as to be irrelevant to operation.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #22 on: 28 Aug '24 - 14:32 »
I tried the Yamaha S-YXG50 VSTi in a BASS_VST_ChannelCreate+BASS_StreamFree loop, and there was no memory leak - it remained constant through many 1000s of iterations. So the problem doesn't seem to affect all VSTi, or perhaps it's somehow system-specific? You can get that VSTi for your own comparisons from here:

   https://veg.by/en/projects/syxg50/

Regarding BASS_VST_ChannelSetDSP testing, be sure to call BASS_VST_ChannelRemoveDSP (rather than BASS_ChannelRemoveDSP) to free them. You can also use the BASS_VST_NODELAYUNLOAD flag here to avoid delayed unloading.

Regarding the BASS_ChannelSetDSP loop above, was that during playback/decoding? If not, that would explain the small leaks, as BASS_ChannelRemoveDSP just marks the DSP instance for release in the channel's next update cycle (this allows a DSPPROC to free itself). This also applies to BASS_VST_ChannelSetDSP, which uses BASS_ChannelSetDSP internally.

Wayne McHugh

  • Posts: 91
Re: Chasing Memory Leaks
« Reply #23 on: 28 Aug '24 - 22:16 »
Hi Ian, S-YXG50 won't load for me but is that because it is a 32 bit VSTi?  My app is 64 bit only.  I don't know the internals of VST2 plugins, but is the testing of such a small and old VSTi a fair test?

Because of the very limited skills of my user base, I'm wiring specific VST2 instruments into the app. Of course each has to be installed first. Specifically these are Cakewalk's SI-Bass Guitars, SI-Drum kits, SI-Strings, XLN-Audio's Addictive Keys (demo), and AAS's Strum Session 2 (all but Strum Session 2 are free).  All of them result in continuously increasing memory usage, whether tested in in an artificial Create/Release loop or creating/releasing as songs are loaded/unloaded - Addictive Keys much more than the others.  That is not to be critical of any of these VSTi's; they are all doing a great job.

As to my DSP test, it was an artificial loop, and as such I expect you are right that in real life it would get cleaned up.  I don't see a way to measure them in anything except an isolated loop.

In my app I have created a VSTi stream pool whereby a minimum number of VSTi streams are kept alive for reuse, and extra ones only created and destroyed for songs that require them. I set my player to play through a playlist of over 100 MIDI files overnight, which it did perfectly, and the memory increase was not concerning.  So while the leak is still there, I've found a workable way to limit its effect, and in "normal" use it will no longer be a problem in my app.

Thank you for all your attention on this, and for the sake of BASS_VST I'm sorry it didn't reach a clearer outcome.  I'll keep it in the back of my mind in case anything arises that might lead to more clarity or a resolution.

Ian @ un4seen

  • Administrator
  • Posts: 26102
Re: Chasing Memory Leaks
« Reply #24 on: 29 Aug '24 - 17:26 »
Hi Ian, S-YXG50 won't load for me but is that because it is a 32 bit VSTi?  My app is 64 bit only.  I don't know the internals of VST2 plugins, but is the testing of such a small and old VSTi a fair test?

It's the only VSTi I have :)

If you would still like to look into this and you have a link to a problematic free VSTi (preferably one that can be just dropped in without an installer) then please post (or PM) that. Btw, have you tried to reproduce the problem with the same VSTi in other software? I guess the tricky part is getting other software to repeatedly load and unload the VSTi.