On Mon, Jun 24, 2013 at 8:01 PM, Andras H.
[email protected]wrote:
For that wouldn’t it be sufficient to monitor memory usage of the
process
over time?
And also to see the history of memory usage by methods compared to each
other so that I know which part of the code I should rewrite to make it
more memory efficient.
Considering a call stack of, say, 10 levels how would you attribute
memory
usage to methods? Would you sum it up along the hierarchy? How would
you
consider different invocations of the same method at different points in
time? Assuming you could count the bytes allocated during a call of
method
x: now, since that figure tells you nothing about the allocation pattern
you do not really gain information with regard to the complete memory
usage. For example, you could allocate 10,000 objects in a loop one per
iteration and forget them immediately OR you allocate them, stuff them
in
an Array and loose them only at method exit. In the latter case you may
need more memory since GC cannot collect earlier. Considering that,
total
memory of the process may be a better metric.
If you consider memory usage at method exit vs. method entry a method
which
allocates lots of objects that it releases shortly after might be
actually
much worse for the program in terms of CPU and GC activity than another
method which steadily allocates objects which are returned in a
collection
although the latter looks much worse with this statistics.
I usually found “ruby -r profile” helpful. You can also use module
Benchmark for measuring timing of specific parts of code. You can even
use
Benchmark.measure { … } around a specific piece and you’ll get CPU,
system and wall clock time in an instance of class Benchmark::Tms,
I use these tools and they work great. Only they’ve got nothing to do
with memory consumption.
Didn’t you also ask for “process time output”?
For memory leak detection I once created a small tool with ObjectSpace
which just counts instances per class and outputs deltas. You might
find
it in the archives of this forum.
If I understand you correctly, you say I can only see the counted sum of
these objects? But I reckon I still won’t be able to calculate memory
usage by this.
You could create metrics though which might not be bytes but
nevertheless
relevant: you count the number of instance variables. With that you
have a
measurement of the relative size of instances of different classes. For
String you could use e.g. bytesize / 4 (or how many bytes a reference
takes
up). That would still not give you exact bytes but the information
about
relative sizes would be enough for optimization - if you actually have a
memory issue.
Advantage of this approach would be that it would not need any
modifications of the runtime - and it would be fun to hack.
ruby-prof would have similar with its RubyProf::ALLOCATIONS I believe,
unfortunately I can’t get it to work. But anyway, your solution can be
more than nothing. I’ll check it out later on. Though I’m still keen to
find a solution for what I described above.
I think for a real solution you would need something like JProfiler,
which
records allocation sites and call stacks so you can identify paths
through
code with the worst allocation behavior. You could create something
like
this by exchanging implementation of Class#new and counting as suggested
above. In combination with #caller you can even get the call stack.
The
only problem here is to subtract the measurement code from the
statistic…
Kind regards
robert