[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-serviceability-dev
Subject:    Re: ThreadMXBean.getThreadAllocatedBytes() allocates memory
From:       Bengt Rutisson <bengt.openjdk () gmail ! com>
Date:       2016-09-19 12:52:44
Message-ID: CAKLKxPipY4513HwTrLcTZcaCdr3ddJ_T15ZrbzF6SsinZtKY3w () mail ! gmail ! com
[Download RAW message or body]

Hi Claes and David,

Thanks for the quick responses!

Yes, a pre-allocated array is probably not the way to go. Letting the user
pass a result array is much better or just specialising the "long
getThreadAllocatedBytes(long id)" to avoid  allocations instead of re-using
the "long[] getThreadAllocatedBytes(long[] ids)" version.

As a user of the API I am not surprised that the "long[]
getThreadAllocatedBytes(long[] ids)" version needs to allocate the result
array. But since I know that "long getThreadAllocatedBytes(long id)" pretty
much just needs to read a field in the thread it surprises me that it needs
to allocate.

I'll file an RFE for 10.

Thanks again for the help with this!

Cheers,
Bengt


2016-09-19 1:45 GMT+02:00 David Holmes <david.holmes@oracle.com>:

> Hi Bengt,
>
> On 19/09/2016 7:14 AM, Bengt Rutisson wrote:
>
>>
>> Hi Serviceability,
>>
>> Not sure, but I hope this is the correct list to post this on.
>>
>
> Sure is.
>
>
> I wanted to use the ThreadMXBean.getThreadAllocatedBytes() method to get
>> some information about how much memory some Java code allocated.
>>
>> When I dug into the results they didn't properly add up until I realized
>> that the call to getThreadAllocatedBytes() actually allocates memory.
>> This was a surprise to me.
>>
>> I'm attaching a small example to illustrate what I mean.
>>
>> Running the example renders this output:
>>
>> $ javac AllocMeasure.java
>> $ java AllocMeasure
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>> Bytes allocated: 48
>>
>> What I would have expected was that it would say "Bytes allocated: 0"
>> since I would like to add my own code between line 9 and 10 in the
>> example and get the value for how much memory it allocates. As it is now
>> I have to deduct the bytes that the getThreadAllocatedBytes() allocates
>> to get the correct result.
>>
>> The problem is that getThreadAllocatedBytes() is implemented this way:
>>
>>     public long getThreadAllocatedBytes(long id) {
>>         long[] ids = new long[1];
>>         ids[0] = id;
>>         final long[] sizes = getThreadAllocatedBytes(ids);
>>         return sizes[0];
>>     }
>>
>> http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/32d957185656/
>> src/java.management/share/classes/sun/management/ThreadImpl.java#l345
>>
>> I was surprised to see the "new long[1]". I realize that it is nice to
>> reuse getThreadAllocatedBytes(long []) method, but maybe a pre-allocated
>> array can be used instead of allocating a new one for each call?
>>
>
> Did you also notice this code:
>
>   protected long[] getThreadAllocatedBytes(long[] ids) {
>         boolean verified = verifyThreadAllocatedMemory(ids);
>
>         long[] sizes = new long[ids.length];
>
> so we're allocating  another array for the return value(s).
>
> Bit difficult to use a pre-allocated array - when would you allocate it?
> when would you release it? Would you have one per-thread or a freelist of
> them? It all gets a bit too hard to manage.
>
> A better API would allow the user to pass in the result array as well - to
> allow for array allocation and reuse outside of the region of code that is
> being measured.
>
> I know the specification for this method is kind of fuzzy, but is this
>> to be considered a bug or does it work as intended?
>>
>
> I'd call it a quality of implementation issue. It would be better if the
> allocation could be avoided, but that requires two entry points to the VM
> code. Certainly the query for a single thread should avoid the need for any
> array allocation. But I think this pattern is common throughout the
> management code.
>
> You should a file a RFE for 10.
>
> Cheers,
> David
>
>
> Thanks,
>> Bengt
>>
>

[Attachment #3 (text/html)]

<div dir="ltr"><br><div>Hi Claes and David,</div><div><br></div><div>Thanks for the \
quick responses!</div><div><br></div><div>Yes, a pre-allocated array is probably not \
the way to go. Letting the user pass a result array is much better or just \
specialising the &quot;long getThreadAllocatedBytes(long id)&quot; to avoid   \
allocations instead of re-using the &quot;long[] getThreadAllocatedBytes(long[] \
ids)&quot; version.</div><div><br></div><div>As a user of the API I am not surprised \
that the &quot;<span style="font-size:13px">long[] getThreadAllocatedBytes(long[] \
ids)</span>&quot; version needs to allocate the result array. But since I know that \
&quot;long getThreadAllocatedBytes(long id)&quot; pretty much just needs to read a \
field in the thread it surprises me that it needs to \
allocate.</div><div><br></div><div>I&#39;ll file an RFE for \
10.</div><div><br></div><div>Thanks again for the help with \
this!</div><div><br></div><div>Cheers,</div><div>Bengt</div><div><br></div></div><div \
class="gmail_extra"><br><div class="gmail_quote">2016-09-19 1:45 GMT+02:00 David \
Holmes <span dir="ltr">&lt;<a href="mailto:david.holmes@oracle.com" \
target="_blank">david.holmes@oracle.com</a>&gt;</span>:<br><blockquote \
class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex">Hi Bengt,<span class=""><br> <br>
On 19/09/2016 7:14 AM, Bengt Rutisson wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"> <br>
Hi Serviceability,<br>
<br>
Not sure, but I hope this is the correct list to post this on.<br>
</blockquote>
<br></span>
Sure is.<div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"> I wanted to use the \
ThreadMXBean.getThreadAllocate<wbr>dBytes() method to get<br> some information about \
how much memory some Java code allocated.<br> <br>
When I dug into the results they didn&#39;t properly add up until I realized<br>
that the call to getThreadAllocatedBytes() actually allocates memory.<br>
This was a surprise to me.<br>
<br>
I&#39;m attaching a small example to illustrate what I mean.<br>
<br>
Running the example renders this output:<br>
<br>
$ javac AllocMeasure.java<br>
$ java AllocMeasure<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
Bytes allocated: 48<br>
<br>
What I would have expected was that it would say &quot;Bytes allocated: 0&quot;<br>
since I would like to add my own code between line 9 and 10 in the<br>
example and get the value for how much memory it allocates. As it is now<br>
I have to deduct the bytes that the getThreadAllocatedBytes() allocates<br>
to get the correct result.<br>
<br>
The problem is that getThreadAllocatedBytes() is implemented this way:<br>
<br>
      public long getThreadAllocatedBytes(long id) {<br>
            long[] ids = new long[1];<br>
            ids[0] = id;<br>
            final long[] sizes = getThreadAllocatedBytes(ids);<br>
            return sizes[0];<br>
      }<br>
<br>
<a href="http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/32d957185656/src/java.management/share/classes/sun/management/ThreadImpl.java#l345" \
rel="noreferrer" target="_blank">http://hg.openjdk.java.net/jdk<wbr>9/jdk9/jdk/file/32 \
d957185656/<wbr>src/java.management/share/<wbr>classes/sun/management/<wbr>ThreadImpl.java#l345</a><br>
 <br>
I was surprised to see the &quot;new long[1]&quot;. I realize that it is nice to<br>
reuse getThreadAllocatedBytes(long []) method, but maybe a pre-allocated<br>
array can be used instead of allocating a new one for each call?<br>
</blockquote>
<br></div></div>
Did you also notice this code:<br>
<br>
   protected long[] getThreadAllocatedBytes(long[] ids) {<br>
            boolean verified = verifyThreadAllocatedMemory(id<wbr>s);<br>
<br>
            long[] sizes = new long[ids.length];<br>
<br>
so we&#39;re allocating   another array for the return value(s).<br>
<br>
Bit difficult to use a pre-allocated array - when would you allocate it? when would \
you release it? Would you have one per-thread or a freelist of them? It all gets a \
bit too hard to manage.<br> <br>
A better API would allow the user to pass in the result array as well - to allow for \
array allocation and reuse outside of the region of code that is being measured.<span \
class=""><br> <br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"> I know the specification for this method is kind of fuzzy, \
but is this<br> to be considered a bug or does it work as intended?<br>
</blockquote>
<br></span>
I&#39;d call it a quality of implementation issue. It would be better if the \
allocation could be avoided, but that requires two entry points to the VM code. \
Certainly the query for a single thread should avoid the need for any array \
allocation. But I think this pattern is common throughout the management code.<br> \
<br> You should a file a RFE for 10.<br>
<br>
Cheers,<br>
David<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"> Thanks,<br>
Bengt<br>
</blockquote>
</blockquote></div><br></div>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic