From: Robert Klemme Date: 2013-06-25T06:43:09+09:00 Subject: Re: A working memory profiling solution? --089e013a07d04f146b04dfed4ce2 Content-Type: text/plain; charset=ISO-8859-1 On Mon, Jun 24, 2013 at 8:01 PM, Andras Horvath wrote: > Robert Klemme wrote in post #1113449: > > How exactly do you imagine "memory usage by methods" to be measured? > > Are you just interested in learning how much memory is allocated > (temporarily) > from withing a method or do you have a memory leak? > > I'm interested in figuring out the memory peaks of specific code pieces. > Even if memory gets freed up at some point, I'd still like to know the > amount that was used just right before to be able to calculate the > amount that would be used by concurrent processes. > 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 -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ --089e013a07d04f146b04dfed4ce2 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable



On Mon, Jun 24, 2013 at 8:01 PM, Andras Horvath &= lt;lists@ruby-for= um.com> wrote:
Robert Klemme wrote in post #1113449:
> How exactly do you imagine "memory usage by met= hods" to be measured?
> Are you just interested in learning how much memory is allocated (temp= orarily)
from withing a method or do you have a memory leak?

I'm interested in figuring out the memory peaks of specific code = pieces.
Even if memory gets freed up at some point, I'd still like to know the<= br> amount that was used just right before to be able to calculate the
amount that would be used by concurrent processes.
For that wouldn't it be sufficient to monitor memory = usage of the process over time?
=A0
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.

Considerin= g a call stack of, say, 10 levels how would you attribute memory usage to m= ethods? =A0Would you sum it up along the hierarchy? =A0How would you consid= er different invocations of the same method at different points in time? = =A0Assuming you could count the bytes allocated during a call of method x: = now, since that figure tells you nothing about the allocation pattern you d= o not really gain information with regard to the complete memory usage. =A0= 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 an= d loose them only at method exit. =A0In the latter case you may need more m= emory since GC cannot collect earlier. =A0Considering 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 thi= s statistics.
=A0
> I usually found "ruby -r profile" helpful. =A0You can also u= se module
> Benchmark for measuring timing of specific parts of code. =A0You can e= ven
> use
> Benchmark.measure { ... } around a specific piece and you'll get C= PU,
> 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 t= o do
with memory consumption.

Didn'= ;t you also ask for =A0"process time output"?

> For memory leak detection I once cr= eated a small tool with ObjectSpace
> which just counts instances per class and outputs deltas. =A0You 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 m= etrics though which might not be bytes but nevertheless relevant: you count= the number of instance variables. =A0With that you have a measurement of t= he relative size of instances of different classes. =A0For String you could= use e.g. bytesize / 4 (or how many bytes a reference takes up). =A0That wo= uld 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 h= ack. :-)
=A0
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<= br> more than nothing. I'll check it out later on. Though I'm still kee= n to
find a solution for what I described above.

I thi= nk for a real solution you would need something like JProfiler, which recor= ds allocation sites and call stacks so you can identify paths through code = with the worst allocation behavior. =A0You could create something like this= by exchanging implementation of Class#new and counting as suggested above.= =A0In combination with #caller you can even get the call stack. =A0The onl= y problem here is to subtract the measurement code from the statistic... :-= )

Kind regard= s

robe= rt

--
remember.guy do |as, often| as.yo= u_can - without end
http://blog.rubybestpractice= s.com/
--089e013a07d04f146b04dfed4ce2--