Home > Profiling Results
Semi-statistical data collection in Memory Profiling
The total number of objects allocated for each class that Profiler presents
(in both "Record Object Creation" and "Record Object Creation and Garbage
Collection" modes) is exact, whereas other numbers (such as total object size)
and the reverse call graphs are by default
obtained statistically. This is one of the many performance improvement
measures available in the Profiler.
Statistical data collection works as follows: there is a counter associated
with each profiled type (that is, a class or an array type), which is initially
equal to 10 (you can change the default value in Analyze Memory Usage command
dialog or in Custom
Memory Profiling). Every time an instance of the given class is allocated,
the counter is decremented. When it reaches zero, the size of the allocated
object is determined, a stack trace is taken, and the counter is assigned the
initial value again. The reverse call graph for object allocations that Profiler
displays is created out of these stack traces, and the total size of objects
reported by Profiler is the size of only those objects for which stack traces
have been taken.
Note also that the number of method invocations that you see in
the allocation calls graph are not the same as those you see in CPU profiling.
In case of memory profiling, these are not actually the number of times that
a given method was invoked, but rather the number of stack traces taken, when
this method was found on stack in the given context. So you may find that e.g.
the main application method has more than one invocation. In fact, if your application
is single-threaded, the total number of "invocations" displayed for
the main method will be the same as the total number of stack traces taken.
When statistical data collection is used, information about some of the
call paths may of course be lost. However, in practice it is usually important
to determine only the most active object allocation sites and call paths. They
will be evident even with the statistical stack sampling described above. If
you would like to collect precise information about call paths, just set the
stack sampling interval value equal to 1. This, however, may lead to a very
noticeable decline in performance. The default stack sampling interval equal
to 10 has been chosen as a reasonable compromise between the accuracy of the
collected information and the performance impact.
Note also that Profiler does not use exactly the fixed stack sampling interval
during this kind of profiling. This is done to avoid undesirable data correlations.
For example, if your program has one loop that causes 9 allocations of instances
of X in a row in method foo() and then one instance in method bar(),
sampling the stack precisely on every 10th allocation of X could result in getting
information only about allocations that happen in bar() and nothing
about foo() which would be a rather distorted result. To
fix this problem, after every time Profiler takes a stack trace, it sets the object
allocation counter to a random value slightly different from the user-defined
one. If the defined interval is 10, the actual starting values for the counter,
as the profiler runs, may look like e.g. 8, 11, 10, 7, 9, 12, ... In this way, the
information that is eventually presented to you is guaranteed to be generally
statistically reliable.
See also