| Author |
Message |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Thu Sep 22, 2011 1:30 pm Post subject: analyze time spent in garbage collector |
|
|
Can Performance Profiler help me in finding out where in my code Gargabe Collection occurs the most time?
There exist 3 performance counters "# Gen X Collections" but they are just increasing steadily -- associating their delta changes with source code would be an interresting thing, wouldn't it? (At least as long GC's are not concurrent.) |
|
| Back to top |
|
 |
Brian Donahue
Joined: 23 Aug 2004 Posts: 6344 Location: Red Gate Software
|
Posted: Thu Sep 22, 2011 4:42 pm Post subject: |
|
|
I don't think it's worthwhile to try to tie GC collections down to code. If you run that code on a different system I'd imagine your GC profile could change completely.
What you can control, possibly, is the rate of allocations of objects. The GC algorithm works independently of the code being run. _________________ Brian Donahue
Technical Support
Red Gate Software Ltd.
44 (0)870 160 0037 ext 8521
US and CAN 1-866-RED GATE ext 8521 |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Fri Sep 23, 2011 10:12 am Post subject: Re: |
|
|
Sorry for being not precise enough:
I'm speaking of routines/methods which get called some million times and where it's very likely that short living (=Gen0 and Gen1) memory is allocated and freeded at recurring places -- which I want to isolate.
What I've read about your alpha/beta programm "Memory Tracker" seems to be which I'm looking for. Unfortunately it doesn't work -- either it's not compatible with .NET 4 / 64bit or something different. |
|
| Back to top |
|
 |
Brian Donahue
Joined: 23 Aug 2004 Posts: 6344 Location: Red Gate Software
|
Posted: Fri Sep 23, 2011 11:00 am Post subject: |
|
|
I'm not sure what you want to accompilsh, but if you think memory tracker would do the job, you would probably get what you need with WinDbg and SOS using !dumpheap -stat. _________________ Brian Donahue
Technical Support
Red Gate Software Ltd.
44 (0)870 160 0037 ext 8521
US and CAN 1-866-RED GATE ext 8521 |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Fri Sep 23, 2011 12:54 pm Post subject: |
|
|
My goal is to find the regions where problems are. So !dumpheap could only help when I know where to stop and debug this using SOS.
ANTS Memory Profiler does not help, too, since there are no memory leaks -- but there is heavy GC usage which I want to reduce.
The problem is that there are many hidden places where objects could be created, for example when using LINQ with lambdas which create closures. This is happening behind the scenes, there is no "new SomeObject()" constructor call you easily could spot. |
|
| Back to top |
|
 |
Brian Donahue
Joined: 23 Aug 2004 Posts: 6344 Location: Red Gate Software
|
Posted: Fri Sep 23, 2011 1:46 pm Post subject: |
|
|
Just curious to know how Memory Tracker would have helped - it was based on StrikeControl and basically made a graphoc display of what you could get in a slightly less-attractive fashion using !dumpheap.
Guess you could use Windows performance monitor and set up an alert when the app's % time spent in GC gets to a certain level and have this trigger a dumpheap and a stack dump with CDB. I've never done this but it sounds possible. _________________ Brian Donahue
Technical Support
Red Gate Software Ltd.
44 (0)870 160 0037 ext 8521
US and CAN 1-866-RED GATE ext 8521 |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Fri Sep 23, 2011 2:25 pm Post subject: |
|
|
I don't know if it would have helped. But from the choice of the 2 ANTS Profilers and the Memory tracker the last one was most promising.
Since Memory Profiler already forces non-concurrent garbage collections maybe changes are higher in finding or at least narrowing down problem areas with this tool? |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Fri Sep 23, 2011 2:45 pm Post subject: |
|
|
Another sample of hidden object creation, a LINQ query using "let" (against a LINQ-to-SQL AdventureWorks DB):
| Code: |
from h in this.TransactionHistory.AsEnumerable()
let x = h.ActualCost / h.Quantity
where x > 0
let y = char.GetUnicodeCategory(h.TransactionType)
orderby h.TransactionDate, y
select h
|
This gets translated to ILASM code whose C# translation looks like this:
| Code: |
.Select (
h =>
new
{
h = h,
x = (h.ActualCost . (Decimal)(h.Quantity))
}
)
.Where (temp0 => (temp0.x > 0))
.Select (
temp0 =>
new
{
temp0 = temp0,
y = Char.GetUnicodeCategory (temp0.h.TransactionType)
}
)
.OrderBy (temp1 => temp1.temp0.h.TransactionDate)
.ThenBy (temp1 => temp1.y)
.Select (temp1 => temp1.temp0.h)
|
So although I'm using only a well known object (of type TransactionHistory) there have been created 2 additional anonymous (and temporary) classes for each instance of TransactionHistory I`m retrieving from the DB.
While the temporary object most likely won't get promoted to Gen1 this still puts a load on GC collections which would be avoidable at all by refactoring the code into something smarter. |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Tue Sep 27, 2011 12:36 pm Post subject: |
|
|
| I see, Red Gate has no motivation in improving their products. |
|
| Back to top |
|
 |
Chris.Allen
Joined: 12 Mar 2009 Posts: 442
|
Posted: Tue Sep 27, 2011 4:11 pm Post subject: |
|
|
Hi- I think your original question is good and interesting (and it sparked off a lot of internal discussion). I'm by no means an expert on garbage collection but I do know ANTS performance profiler.
Have you tried including all the memory counters including the Gen 0/Gen 1 promoted (bytes/sec) counters - these are most useful as they give rates of activity rather than absolute values? You should then be able to correlate GC activity with your code (although, as Brian points out- it is an indirect correlation). |
|
| Back to top |
|
 |
springy
Joined: 04 Feb 2011 Posts: 12
|
Posted: Tue Sep 27, 2011 4:27 pm Post subject: |
|
|
I started the original post with these counters -- at least the pure counting ones.
Even though it's a performance problem maybe it's easier to tackle this problem using Memory profiler since Memory profiler already disabled concurrent garbage collections.
My main problem is that I see the counters increasing rapidly but don't have a clue where and why so many objects get created -- at least they don't get leaked. Most likely the main cause are these hidden LINQ closures, iterator implementation classes and hidden classes created by LINQ expressions. |
|
| Back to top |
|
 |
|