I’ve just been looking at my application details in Task Manager - Handles, Threads, User Objects and GDI Objects.
Right now it has 1055 Handles, 26 Threads, 856 User Objects and 1761 GDI Objects.
How many is too many?
GDI Objects is the one that concerns me as some users are getting the occasional Out Of System Resources exception that follows a GDIError.
The default limit is 10,000
In our App the user can do things that result in heaps of them being required.
We have only ever had one user exceed 10,000
The upper limit is 64k, you can google the registry entry to change easily enough. Note that there are two entries, I think it is 32 or 64bit apps, but it is not particularly clear which is which.
In an effort to reduce resource use I have just changed a few forms from Auto Create to creating them only as required then freeing them afterwards. Those forms are only used occasionally and often never in a some usage sessions. This reduced the base GDI Objects count by about 300.
I’m not sure how to track down the occasion Out Of Resources though as I have never been able to replicate the error on my systems.
Something I’ve just noticed is that the GDI Object count creeps by 2 each time I use (create and free) one particular form. It doesn’t sound like much, but I don’t like that it seems to leak resources. I’ve checked through the code and can’t see where I’m allocating anything that’s not being freed again. How would I go about tracking that down?
This package is extremely helpful for these types of tasks
It looks like TMS bought that out. Ironically the leak seems to be in the TMS grid when adding images.
Are you sure it’s a leak, it may take several to many GDI objects to ‘support’ each added image, maybe even more depending on what you can do with that image, or if it’s just a plain image vs composite.
Yes, if after deleting the image the GDI objects doesn’t go back down it’s probably a leak, but whilst it’s there it’s quite possible the increase is valid.
When the form containing the TMS grid and images is freed, all of the associated resources should be freed too though?
But like a lot of ms ‘counters’ the count might not go down instantly, so you need to allow for a bit of inconsistency.
I’m actually looking at this issue for FinalBuilder 9 - which uses twice as many GDI objects as FinalBuilder 8 - FB8 was compiled with XE7, FB9 compiled with 11.2 - trouble is I have also updated every library so haven’t figured out what is using so many GDI objects yet - could be a library or could just be the VCL using more objects
About your GDI resources creeping up, I have struggled with this one as well. I write reasonably complex multi-threaded applications (with minimal interfaces) that process/convert sizeable incoming data & audio every 5 mn, 24/7, and while I was always happy when a FastMM4 report only found a very few GDI/unknown tiny leaks, I could never tame these, and they did creep up over months of continuous use. Not worryingly, since at least once a year an update or server reset would restart the applications and reset associated memory, but enough to annoy me.
Following the ebb and flow of these creeps over time (via GetProcessMemoryInfo()), I came to the conclusion that Windows, perhaps not surprisingly, wasn’t doing a consistent cleanup job of resources it (as opposed to Delphi) allocated.
For me, relief came from half a dozen lines of code. Once a day, at some idle time, I now ask Windows to finish cleaning up properly, and the results are quite startling:
//clear mem once a day, Windows lets it creep up over time
hProcess := OpenProcess(PROCESS_SET_QUOTA, false, GetCurrentProcessId);
SetProcessWorkingSetSize(hProcess, $FFFFFFFF, $FFFFFFFF);
After this call, memory footprint is about the size it was on first startup, all stray GDI/unknowns creeps forgotten.
Would be interesting to see if this call (or a related one) also effects such a slimming cure on handles and other niggles you mention - haven’t checked, these were never a worry in my case.