Heremik 0 Posted September 20, 2023 Hello, We have a big problem with the window limitation of GDI Objects (10 000 by process). Our software is big (5 000 000 lines), and use a lot of TImage, TImageList, old Bitbtn and speedbutton, etc... But We use lazy initialization pour each frame and form (we create them when needed). 3 monthes ago, we have decided to modernize the GUI, and we have used the TMS Ribbon. After that, the software as begin to be instable (out of ressource, random error on imagelist, on canvas, ...) very quickly. I have checked the number of GUI Objects, and I have discover that : - TMS Ribbon use more than 5000 GDI objects for an interface of only a dozen of tabs (and related ribons) !!!!!! - VirtualTreeView (we have more near 100 virtual TreeView in our GUI) use about 100-200 GDI objects by tree !!!! (even if using virtualImageList). We have no time to allow to change TMS Ribbon for another component. I imagine two solutions : - Destroy Virtual Tree View when there are not visible et recreate them when I need them, but, it will be a big work. - Increase the window limit by process (10 000) of GDI objects by changing automatically the value in the registry for each user (more than 2000). My questions are : - Is it really dangerous to increase the Windows limit to about 16 000 by process instead of 10 000 for thousand of users ? - Do you have any other suggestion to decrease this number ? Thanks a lot for your answers, we are in ermegency as we have to deliver the new version of our software in a few weeks (Shame on me 😞 ) Share this post Link to post
Stano 143 Posted September 20, 2023 I would reach out to TMS as well. They are flexible. They respond quickly. Share this post Link to post
Anders Melander 1782 Posted September 20, 2023 1 hour ago, Heremik said: TMS Ribbon use more than 5000 GDI objects for an interface of only a dozen of tabs (and related ribons) !!!!!! Sounds like a bug to me. Have you checked the application for resource leaks? 1 Share this post Link to post
Attila Kovacs 629 Posted September 20, 2023 (edited) It's a bug for sure, either in the component or in your code. Start debugging and don't panic 🙂 First step is, turn on the GDI Objects column in the task manager and start watching it meanwhile you navigate through your app. If you are creating/freeing the forms/frames on the fly as you state, the number should drop back on closing a form, etc... you know it for sure Edited September 20, 2023 by Attila Kovacs Share this post Link to post
Kas Ob. 121 Posted September 21, 2023 14 hours ago, Heremik said: - Is it really dangerous to increase the Windows limit to about 16 000 by process instead of 10 000 for thousand of users ? Nope, no danger at all it will cause them few mega bytes in memory to can't be used, but i doubt if this is the best approach. 14 hours ago, Heremik said: - Do you have any other suggestion to decrease this number ? You have to remove the need for such very high number. With such number (i only can guess ) you application is utilizing the CPU at very high level even without user interaction, let alone moving a windows with the mouse will cause the whole PC to hug, let alone if you are using double buffering everywhere. My suggestion is before contacting TMS to figure out why Ribbon is using such very high number, the last time i used TMS Ribbon was few years back with my license expired 12 years ago, i never noticed such thing. Try to start from scratch with the Ribbon in an empty and simple form to find the culprit or at least to understand the context that increase the GDI handles, also keep an eye on how many ImageList you are using and where, as they can be very expensive, your ImageList will behave better if you combine them, you can do this on separated module after initializing, i did such by keep many of them while developing a project but in production version the lists will be combined in one them freed. ps : the more GDI handle you have the slower the system behave, as these are look up tables and the most affecting thing is: the last to be created is the last in that list so the last frame or form created and showed will be the slowest to handle and will looks sluggish. Share this post Link to post
Heremik 0 Posted September 21, 2023 Thanks for your help. I have made a ticket for TMS support, because even their sample use 500 GDI for a minimal Ribbon. I have no ressource leak in my software (I use MadExcept ressource leak to check). I create frames and forms on the fly, but I don't free them, because it is slow to create, and the user can wait 1 time to open a window, but not each time it click on the button. That's why, while usin,g the software, the number of GDI objet increase. I have tried Deleaker to check GDI leak, but my project is too big and it freeze after some minutes of usage. The main problem is the Ribbon, add a button to the ribbon use 17 GDI Objects ! (Even in sample application). But I have begun to reduce GDI usage in the remaining of the software by moving imagelist present in frames instancied several times, to a datamodule. Thanks again Share this post Link to post
Kas Ob. 121 Posted September 21, 2023 33 minutes ago, Heremik said: The main problem is the Ribbon, add a button to the ribbon use 17 GDI Objects ! (Even in sample application). This means they are caching the button animation (drawing stage) as BITMAP's, i think solving this will be easy enough for them to some extend, there is few approaches like they can fix and even make it faster by using one bitmap and change its content from raw bytes, or put all the drawing stage in one bitmap and draw parts (rectangles) as needed. Share this post Link to post
Anders Melander 1782 Posted September 21, 2023 2 hours ago, Heremik said: I have made a ticket for TMS support, because even their sample use 500 GDI for a minimal Ribbon. For comparison, I have a simple application that's using DevExpress ribbon, DevExpress grids and a virtual treeview and it uses 400-450 GDI handles. 2 hours ago, Heremik said: But I have begun to reduce GDI usage in the remaining of the software by moving imagelist present in frames instancied several times, to a datamodule. An imagelist itself uses at most one GDI handle - if any. It's the individual bitmaps that copy data from the image list that uses the handles. Share this post Link to post
Heremik 0 Posted September 21, 2023 (edited) 1 hour ago, Anders Melander said: 1 hour ago, Anders Melander said: An imagelist itself uses at most one GDI handle - if any. It's the individual bitmaps that copy data from the image list that uses the handles. I Did not know that. Now, I am completly lost, I just try to make an new application that create components to understand the gdi use. Conclusion : - TButton = 5 GDI - TBitBtn = 0 GDI - TSpeedButton = 0 GDI - TImage = 0 GDI - TVirtualImage = 0 GDI - TImageList / TVirtualImageList (with 100 Bitmap inside) = 5 GDI My conclusion is that I am going to try to convert all my tbutton in BitBtn...(with a software of course). Edited September 21, 2023 by Heremik Share this post Link to post
Attila Kovacs 629 Posted September 21, 2023 2 hours ago, Heremik said: - TButton = 5 GDI 1x TButton 5 GDI 100x TButton 5 GDI Someone should be included in this debugging. 1 Share this post Link to post
Anders Melander 1782 Posted September 21, 2023 5 hours ago, Heremik said: TBitBtn = 0 GDI Looking at the source of TBitBtn, it can either use an internal TBitmap (which will consume at least 1 handle per button) or it can use an external imagelist (which will consume at least 1 handle globally [*]). [*] Drawing an imagelist in the disabled state consumes another handle, drawing it monochrome another. I would stay away from TBitBtn. It was cute in the nineties but today few people want their application to look like it was made in the nineties... Share this post Link to post