another rootpath

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
stijn
Posts: 23
Joined: Thu Jun 28, 2007 2:57 pm

another rootpath

Post by stijn » Mon May 19, 2008 9:50 am

System Object[]
<GCHandle> #223 {Pinned}

Namespace Name Live instances New live instances Removed live instances Delta live instances Live bytes Max live instance size Min live instance size Delta live bytes Allocs/sec Bytes/sec
Unchecked DIASBase.ContactObjects Representative[] 1 1 0 1 16 16 16 16 0,01 0,1


Most of my business still in memory have a simular rootpath, and remain in memory

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Mon May 19, 2008 9:32 pm

A pinned <GCHandle> that references an object array often indicates a static field. However, if root identification is enabled, you should also see a root path that ends in a static field. Is the <GCHandle> root the only root for the instance? If the instance is not referenced by a static field, you might get some additional information by looking at the allocation stack of the <GCHandle> and Object[]. What do the allocation stacks for the <GCHandle> and Object[] look like?
Best regards,

Andreas Suurkuusk
SciTech Software AB

stijn
Posts: 23
Joined: Thu Jun 28, 2007 2:57 pm

Post by stijn » Sun May 25, 2008 7:46 am

I only see the rootpath when "only include identified roots" is unchecked,
and dont see the static field
the allocation stack for the GCHandle is
AppContext..ctor()
AppContext..cctor()

there are 200 allocation stacks for the object[] ,
and i dont really know how to find the right one

The allocation for my business object is :

List<T>..cctor()
List<T>..ctor()
Collection<T>..ctor()
BindingList<T>..ctor()
RuntimeType.CreateInstanceSlow(bool, bool)
RuntimeType.CreateInstanceImpl(bool, bool, bool)
RuntimeType.CreateInstanceImpl(bool)
Activator.CreateInstance(Type, bool)
RuntimeType.CreateInstanceImpl(BindingFlags, Binder, object[], CultureInfo, object[])
Activator.CreateInstance(Type, BindingFlags, Binder, object[], CultureInfo, object[])
Activator.CreateInstance(Type, object[])
SecurityUtils.SecureCreateInstance(Type, object[])
SecurityUtils.SecureCreateInstance(Type)
BindingSource.CreateBindingList(Type)
BindingSource.GetListFromType(Type)
BindingSource.ResetList()
BindingSource.EnsureInnerList()
BindingSource.EndInitCore()
BindingSource.System.ComponentModel.ISupportInitialize.EndInit()
frmNewDoc.InitializeComponent()
frmNewDoc..ctor()
frmNewDoc..ctor(string, bool)
frmMain.<>c__DisplayClass2a.<_eventBroker_ViewRequestedEvent>b__19(object, EventArgs)
Control.InvokeMarshaledCallbackDo(Control.ThreadMethodEntry)
Control.InvokeMarshaledCallbackHelper(object)
Control.InvokeMarshaledCallback(Control.ThreadMethodEntry)
Control.InvokeMarshaledCallbacks()
Control.MarshaledInvoke(Control, Delegate, object[], bool)
Control.Invoke(Delegate, object[])
Control.Invoke(Delegate)
frmMain._eventBroker_ViewRequestedEvent(object, Views, ViewActionEventHandler, object[])
EventBroker.RequestView(object, Views, ViewActionEventHandler, object[])
frmMain.importToDIASToolStripMenuItem_Click(object, EventArgs)
ToolStripItem.RaiseEvent(object, EventArgs)
ToolStripItem.OnClick(EventArgs)
ToolStripMenuItem.OnClick(EventArgs)
ToolStripItem.HandleClick(EventArgs)
ToolStripItem.FireEventInteractive(EventArgs, ToolStripItemEventType)
ToolStripItem.FireEvent(EventArgs, ToolStripItemEventType)
ToolStripItem.FireEvent(ToolStripItemEventType)
ToolStripSplitButton.OnButtonClick(EventArgs)
ToolStripSplitButton.OnMouseUp(MouseEventArgs)
ToolStripItem.HandleMouseUp(MouseEventArgs)
ToolStripItem.FireEventInteractive(EventArgs, ToolStripItemEventType)
ToolStripItem.FireEvent(EventArgs, ToolStripItemEventType)
ToolStrip.OnMouseUp(MouseEventArgs)
Control.WmMouseUp(Message&, MouseButtons, int)
Control.WndProc(Message&)
ScrollableControl.WndProc(Message&)
ToolStrip.WndProc(Message&)
Control.ControlNativeWindow.OnMessage(Message&)
Control.ControlNativeWindow.WndProc(Message&)
NativeWindow.Callback(IntPtr, int, IntPtr, IntPtr)
[Unmanaged to managed transition]
[Managed to unmanaged transition]
UnsafeNativeMethods.DispatchMessageW(NativeMethods.MSG&)
Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int, int, int)
Application.ThreadContext.RunMessageLoopInner(int, ApplicationContext)
Application.ThreadContext.RunMessageLoop(int, ApplicationContext)
Application.Run(ApplicationContext)
AppContext.Main()

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Mon May 26, 2008 6:51 pm

In my first reply I didn't notice that the new instance was an array. Additionally the size of the instance is 16 bytes, which indicates that it's an empty array. Your allocation call stack also shows this. The only allocation that takes place in the class constructor of List<T> is the allocation of an empty T array (new T[0]) which is stored in a static field. Since this is just a one-time array creation, it does not indicate a memory leak, it's just creation of data needed by the program. If you put your business objects in List<> containers, you will get one empty array for each business object class, even if no instances of the business object exists.

Static fields are stored in object[] instances, that are kept alive using a fixed <GCHandle>. Since several static fields are stored in the same object[], the <GCHandle> allocation and the object[] allocation do not normally happen at the same time as the allocation of instance that is referenced by the field. That's why the <GCHandle> allocation happens in a totally unrelated class (AppContext).
Best regards,

Andreas Suurkuusk
SciTech Software AB

stijn
Posts: 23
Joined: Thu Jun 28, 2007 2:57 pm

Post by stijn » Wed May 28, 2008 1:06 pm

thanx for the reply,

it seems like there arent that many leaks to be found in my program ...
I only happen on NON-leaks ;-p

Donmarsh
Posts: 2
Joined: Wed Jul 10, 2013 7:56 pm

Re: another rootpath

Post by Donmarsh » Wed Jul 10, 2013 8:06 pm

We have an app that uses dozens of List<> objects templatized on different classes. So I get a lot of spurious leaks of the static array created by the List<> constructor. I would like to filter these spurious leaks out. I could do it by ignoring anything allocation by the List<> constructor, or any zero-length array, or even any object held by System.Object[]. I can do this kind of filtering using the ANTS memory profiler, but it isn't as well-integrated with Visual Studio. It also doesn't do a good job with stack traces and linking to source code.

Am I missing something in .NET Memory Profiler which would allow me to do this kind of filtering?

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Re: another rootpath

Post by Andreas Suurkuusk » Wed Jul 10, 2013 8:31 pm

I'm not sure what type of filtering you are looking for, but I don't think it's currently possible to filter instances like you want. Can you provide some additional information about what type of filter you're looking for? Do you want to exclude instances matching some criteria (like zero-length array) from the information presented under the Overview view (and the other views)?
Best regards,

Andreas Suurkuusk
SciTech Software AB

Donmarsh
Posts: 2
Joined: Wed Jul 10, 2013 7:56 pm

Re: another rootpath

Post by Donmarsh » Wed Jul 10, 2013 9:09 pm

Yes, I'm mostly interested in the Overview, and I would like to exclude instances matching some criteria. The zero-length array criterion would be fine for my current problem. Being able to exclude allocations from a particular method (like the List<> constructor) would be even more powerful, but maybe a little more difficult to implement.

After evaluating .NET Memory Profiler compared to others, I think filtering is the only feature it doesn't compare as well on. There are many other things I like about it, of course.

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Re: another rootpath

Post by Andreas Suurkuusk » Wed Jul 10, 2013 9:35 pm

As I said, this is a feature that we currently don't have, but I have added it to our feature list. It will most likely be included in the next version of the profiler. Thanks for the suggestion.

We already have instance filtering based on runtime and AppDomain, and it will not be very difficult to extend this to other criteria (as long as the criteria can be evaluated very quickly). However, the current filter currently also affects allocation counts (e.g. allocations/sec and bytes/sec), but this will not work with when the filter is based on instance properties (e.g. empty array), since this information cannot be stored for each allocation.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 11 guests