|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Misbehaving COM object?We have a .NET project that makes pretty regular use of a COM object
that appears to be misbehaving. Am I correct in understanding that setting a COM object to nothing should act the same way that it would have in VB6? By this I mean it is actually destroyed and not marked for GC. We have an object that is called in a polling routine and looks to be leaking 6-8K at a time and never being reclaimed even though it is set to nothing. Is this possible in .NET or do we just have a poorly written COM object? TIA I personally faced some problems - similar to the one you describe - with
com object myself some times ago. myObject = nothing - only releases the .Net pointer reference to this object - and does not destroy it... If you have a "poorly written" (memory leaking) com object - this does not solve your problem. After checking for a "dispose" method there have been these approaches in my case: - System.Runtime.InteropServices.ReleaseComObject and the other (yes I know - you should not do that way...) - GC.Collect..... Regards Show quoteHide quote "Borco" <rgmul***@gmail.com> schrieb im Newsbeitrag news:1123875485.719125.87370@g43g2000cwa.googlegroups.com... > We have a .NET project that makes pretty regular use of a COM object > that appears to be misbehaving. Am I correct in understanding that > setting a COM object to nothing should act the same way that it would > have in VB6? By this I mean it is actually destroyed and not marked for > GC. We have an object that is called in a polling routine and looks to > be leaking 6-8K at a time and never being reclaimed even though it is > set to nothing. Is this possible in .NET or do we just have a poorly > written COM object? > > TIA > Thanks. Unfortunately we are using both of the last two solutions. This
is used in a server app where the load can be pretty high though and it seems that the GC.Collect calls still do not destroy the object immediately. I wonder if .NET is really a good choice for applications like this. Note that VB6 COM objects should run in a STA apartment else you may pay a
serious overhead when marshaling call between incompatible apartments, that's why it's important to answer following questions: - What kind of server application is this, a service or a console like application, what is it written in C# or VB.NET or...- Willy. Show quoteHide quote "Borco" <rgmul***@gmail.com> wrote in message news:1123946004.837372.116170@f14g2000cwb.googlegroups.com... > Thanks. Unfortunately we are using both of the last two solutions. This > is used in a server app where the load can be pretty high though and it > seems that the GC.Collect calls still do not destroy the object > immediately. I wonder if .NET is really a good choice for applications > like this. > But this does not help you when you have a com-object with memory leaks -
does it? Neither the framework language should make a difference.... Show quoteHide quote "Willy Denoyette [MVP]" <willy.denoye***@telenet.be> schrieb im Newsbeitrag news:u3UTVTCoFHA.3544@TK2MSFTNGP15.phx.gbl... > > Note that VB6 COM objects should run in a STA apartment else you may pay a > serious overhead when marshaling call between incompatible apartments, > that's why it's important to answer following questions: > - What kind of server application is this, a service or a console like > application, what is it written in C# or VB.NET or...- > > Willy. > > > > > > "Borco" <rgmul***@gmail.com> wrote in message > news:1123946004.837372.116170@f14g2000cwb.googlegroups.com... >> Thanks. Unfortunately we are using both of the last two solutions. This >> is used in a server app where the load can be pretty high though and it >> seems that the GC.Collect calls still do not destroy the object >> immediately. I wonder if .NET is really a good choice for applications >> like this. >> > > This is a VB.NET app which is currently running in a console but will
be converted to a service for production. I will look into the apartment issue. Unfortunately this app (not my design) gets its threads from a timer and that makes thread control a little less clear. Thanks for your help. Ok but your COM object is VB6 authored, so at best it's a STA type of
object, that means it should run in a STA initialized thread. Services run their threads in the MTA as do threadpool threads used by the timers (even in a console application), so you are in for a couple of surprises. Willy. Show quoteHide quote "Borco" <rgmul***@gmail.com> wrote in message news:1124118675.564492.158550@g49g2000cwa.googlegroups.com... > This is a VB.NET app which is currently running in a console but will > be converted to a service for production. I will look into the > apartment issue. Unfortunately this app (not my design) gets its > threads from a timer and that makes thread control a little less clear. > > > Thanks for your help. > I tried to set the CurrentThread.partmentState to STA inside the timer
elapsed event but I could not see any difference in behavior or memory usage. If I read correctly this will not work if it is already set to MTA and your post implies that this is the case since we are relying on a timer for our thread generation. Right now we are lobbying to have the COM object rewritten in managed code but for various reasons that might not happen. To get this thread under proper control it sounds like it would be best to manually spawn our own threads and control the apartment state explicitly at creation. Would you agree? I would like to be able to present alternatives for fixing this code base but am unsure which direction to take as this particular problem is new for me. Unfortunately, you can't change a thread's apartment state once it has been
set that means you can't change the apartment state of the pool threads, they are initialized to enter the MTA by the threadpool manager that creates the threads. Now what I would suggest is to write a simple console application in which on the main thread (note that the VB.NET compiler initializes this thread for STA) you: - create an instance of the object and, - call some method. While running the creation and method call in a loop, you measure the memory consumption (both native and CLR) using perfmon.exe and measure the call time. When done, you do the same on an auxiliary thread initialized for MTA, make sure the main thread blocks (call Console.ReadLine() after the aux. thread has started). Don't call GC.Collect or GC.WaitForPendingFinalizers, watch the Private Bytes counter for the process, this counter should not change that much during execution of the loop. If "Private bytes" increases during the STA test, you have a problem with the COM object, but I guess it won't. When "Private bytes" grows when running the MTA test, you have a problem with finalization of the COM reference and you should replace the Console.ReadLine() by a call to Thread.Join(). Try this and let us know the results. Willy. Show quoteHide quote "Borco" <rgmul***@gmail.com> wrote in message news:1124138728.352009.290130@g14g2000cwa.googlegroups.com... >I tried to set the CurrentThread.partmentState to STA inside the timer > elapsed event but I could not see any difference in behavior or memory > usage. If I read correctly this will not work if it is already set to > MTA and your post implies that this is the case since we are relying on > a timer for our thread generation. Right now we are lobbying to have > the COM object rewritten in managed code but for various reasons that > might not happen. > > To get this thread under proper control it sounds like it would be best > to manually spawn our own threads and control the apartment state > explicitly at creation. Would you agree? I would like to be able to > present alternatives for fixing this code base but am unsure which > direction to take as this particular problem is new for me. > OK, I instantiated and ran the COM object on both threads and the
results were nearly identical. The PrivateBytes grows on each call and never appears to be reclaimed by GC. The amount of growth appears to be identical. The method call I am doing is our troublesome open file call (the object opens a proprietary data structure from the file system and controls member access) and the file I am opening is about 900K. I do this 1000 times and private bytes is 940,000K at the end in both instances (give or take 20,000K). I can do workarounds to get size to shrink but we need this thing to go away completely. Any further thoughts? I instantiated our object in both thread states and the results were
nearly identical. The private bytes grew consistently through the loop. This COM object opens a file off the file system and controls access to members of the contained data structure. The file I am opening is about 900K. I open it 1,000 times and memory usage at the end is 940,000K. I can do a workaround to relieve the object of most of the file data in which case the object only grows by about 3,000K from initial bytes to final. The problem is that we could easily run this object 50,000 times a day so even a small memory leak is going to add up quickly. Is it simply rewrite time or is there a way to force this object to be obliterated regardless of its state? Ok, that proves there is something wrong with the COM object itself. Did you
check the build options (VB6 project) are you sure this is a STA object (apartment threaded in VB6) and not a Single threaded object. You can verify this using oleview.exe or directly in the registry (search your COM object class and verify the threadingmodel attribute). If it's marked 'Single' (or not marked at all) you'll need to re-build it as 'apartment' threaded. Willy. Show quoteHide quote "Borco" <rgmul***@gmail.com> wrote in message news:1124206496.947734.289720@g44g2000cwa.googlegroups.com... >I instantiated our object in both thread states and the results were > nearly identical. The private bytes grew consistently through the loop. > This COM object opens a file off the file system and controls access to > members of the contained data structure. The file I am opening is about > 900K. I open it 1,000 times and memory usage at the end is 940,000K. I > can do a workaround to relieve the object of most of the file data in > which case the object only grows by about 3,000K from initial bytes to > final. The problem is that we could easily run this object 50,000 times > a day so even a small memory leak is going to add up quickly. Is it > simply rewrite time or is there a way to force this object to be > obliterated regardless of its state? > Thanks for all your help with this. The object is indeed Apartment
threaded. I ran the VS.NET 2003 upgrade wizard on a branch of the source and it has quite a few conversion issues. This is pretty old school VB 5-6 code with some API goodies (As Any) some ObjPtr issues as well as some collection and compositions issues. It looks like it works well under VB6 (similar loop tests showed stable memory usage) so the problems seem to be strictly related to its use in .NET. From what I have read that should not be the case though so I am a bit baffled. One test I did in .NET was to create instances that grow the memory to 10x my page file. This was interesting as it will chug along up to the point of no memory then pause and garbage collect down to a reasonable level. Unfortunately that is not acceptable for a server app so I need to find a way to get this memory usage straightened out. A rewrite looks daunting right now I would hate to undertake it if the problem lies elsewhere.
Show quote
Hide quote
"Borco" <rgmul***@gmail.com> wrote in message Well if it's really 'Apartment' threaded it should not behave like that, but news:1124220338.703983.10070@g47g2000cwa.googlegroups.com... > Thanks for all your help with this. The object is indeed Apartment > threaded. I ran the VS.NET 2003 upgrade wizard on a branch of the > source and it has quite a few conversion issues. This is pretty old > school VB 5-6 code with some API goodies (As Any) some ObjPtr issues as > well as some collection and compositions issues. It looks like it works > well under VB6 (similar loop tests showed stable memory usage) so the > problems seem to be strictly related to its use in .NET. From what I > have read that should not be the case though so I am a bit baffled. One > test I did in .NET was to create instances that grow the memory to 10x > my page file. This was interesting as it will chug along up to the > point of no memory then pause and garbage collect down to a reasonable > level. Unfortunately that is not acceptable for a server app so I need > to find a way to get this memory usage straightened out. A rewrite > looks daunting right now I would hate to undertake it if the problem > lies elsewhere. > it behaves exactly like that when it's marked "Single" threaded in the registry. To simulate the issue, you could create a small COM object in VB6 and set it's threading behavior to Single, and run the same test as before, you'll notice the same (bad) behavior, change the threading to 'Apartment' and you'll notice the correct behavior. One other thing you could try is to release the COM object reference through a call to Marshal.ReleaseComObject(comRef). Willy. I have used OLEView as well as looking directly at the registry and it
is most definitely Apartment threaded. We are using ReleaseComObject but still seeing some growth. The frustrating point is that internally the writers are saying it works based on VB6 behavior which is true but it behaves differently when wrapped in an interop wrapper. Oh well, we will go back to searching for a solution... Some growth? How much and what exactly. I would like to see some figures
like the Private byte growth after a few million instantiations. Are you sure the memory consumption never drops? Willy. Show quoteHide quote "Borco" <rgmul***@gmail.com> wrote in message news:1124295651.718366.278450@f14g2000cwb.googlegroups.com... >I have used OLEView as well as looking directly at the registry and it > is most definitely Apartment threaded. We are using ReleaseComObject > but still seeing some growth. The frustrating point is that internally > the writers are saying it works based on VB6 behavior which is true but > it behaves differently when wrapped in an interop wrapper. Oh well, we > will go back to searching for a solution... > What we are unsure of is what we should expect from the garbage
collector. We are seeing growth on the order of 4K per instance. Running a million iterations is not realistic as this particular test uses 1 meg of data and appears to be the most effective test. We are taking another route for a short time to try to pinpoint the problem. I will get back with our results. Maybe it`s not .net but your com-object?
Have you checked this object in memory (with all it`s references)? Maybe have a look at http://www.sysinternals.com/Utilities/ProcessExplorer.html to look, where the problem is! Regards! Show quoteHide quote "Borco" <rgmul***@gmail.com> schrieb im Newsbeitrag news:1123946004.837372.116170@f14g2000cwb.googlegroups.com... > Thanks. Unfortunately we are using both of the last two solutions. This > is used in a server app where the load can be pretty high though and it > seems that the GC.Collect calls still do not destroy the object > immediately. I wonder if .NET is really a good choice for applications > like this. >
Other interesting topics
|
|||||||||||||||||||||||