[PATCH] RFR Bug-pending: Enable Hotspot to Track Native Memory Usage for Direct Byte Buffers
Adam Farley8
adam.farley at uk.ibm.com
Fri Feb 23 12:09:17 UTC 2018
Hi Paul,
The larger picture for (read: effect of) these changes is best explained
in my email here:
http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-February/051441.html
See the hyperlink I posted, and the few lines before it.
Unfortunately the only understanding I have regarding the workings of the
native code
is would be derived from the OpenJ9 implimentation. I figured I wouldn't
be thanked for
posting that code here, so I posted what code I could share, with the
additional note
that the Hotspot native side of this should be implimented by:
1) Turning those Unsafe.java methods into native methods, and make them
abstract
(descriptor only, for the uninitiated).
2) Find the Hotspot native code for native memory allocation,
reallocation, and
freeing. Basically create a method that stores the sum total amount of
native memory
used by the DBBs, and then calls the regular allocate/reallocate/free
methods.
E.g.
NM Allocate (Java) - NM Allocate (Native)
DBB NM Allocate (Java) - DBB NM Allocate (Native) - NM allocate (Native)
3) Find the code that prints the current native memory usage in core
files, and
add a similar bit to show the native memory usage for DBBs as a subset
(see the
aforementioned linked link for an example).
This seems like a straightforward task, though that's easy for me to say.
:)
Does that answer your question?
Also, I'm unfamiliar with Java Flight Recorder. Are other developers on
the list
familiar with JFR that can snwer this? I'll put the message in IRC as
well, and
update here if I get any answers.
Best Regards
Adam Farley
From: Paul Sandoz <paul.sandoz at oracle.com>
To: Adam Farley8 <adam.farley at uk.ibm.com>
Cc: core-libs-dev <core-libs-dev at openjdk.java.net>, hotspot-dev
developers <hotspot-dev at openjdk.java.net>
Date: 22/02/2018 02:20
Subject: Re: [PATCH] RFR Bug-pending: Enable Hotspot to Track
Native Memory Usage for Direct Byte Buffers
Hi Adam,
While the burden is minimal there is a principle here that i think we
should adhere to regarding additions to the code base: additions should
have value within OpenJDK itself otherwise it can become a thin end of the
wedge to more stuff (“well you added these things, why not just add these
too?”).
So i would still be reluctant to add such methods without understanding
the larger picture and what you have in mind.
Can you send a pointer to your email referring in more detail to the
larger change sets?
This use-case might also apply in other related areas too with regards to
logging/monitoring. I would be interested to understand what Java Flight
Recorder (JFR) does in this regard (it being open sourced soon i believe)
and how JFR might relate to what you are doing. Should we be adding JFR
events to unsafe memory allocation? Can JFR efficiently access part of the
Java call stack to determine the origin?
Thanks,
Paul.
On Feb 19, 2018, at 5:08 AM, Adam Farley8 <adam.farley at uk.ibm.com> wrote:
Hi Paul,
> Hi Adam,
>
> From reading the thread i cannot tell if this is part of a wider
solution including some yet to be proposed HotSpot changes.
The wider solution would need to include some Hotspot changes, yes.
I'm proposing raising a bug, committing the code we have here to
"set the stage", and then we can invest more time&energy later
if the concept goes down well and the community agrees to pursue
the full solution.
As an aside, I tried submitting a big code set (including hotspot
changes) months ago, and I'm *still* struggling to find someone to
commit the thing, so I figured I'd try a more gradual, staged approach
this time.
>
> As is i would be resistant to adding such standalone internal wrapper
methods to Unsafe that have no apparent benefit within the OpenJDK itself
since it's a maintenance burden.
I'm hoping the fact that the methods are a single line (sans
comments, descriptors and curly braces) will minimise this burden.
>
> Can you determine if the calls to UNSAFE.freeMemory/allocateMemory come
from a DBB by looking at the call stack frame above the unsafe call?
>
> Thanks,
> Paul.
Yes that is possible, though I would advise against this because:
A) Checking the call stack is expensive, and doing this every time we
allocate native memory is an easy way to slow down a program,
or rack up mips.
and
B) deciding which code path we're using based on the stack
means the DBB class+method (and anything the parsing code
mistakes for that class+method) can only ever allocate native
memory for DBBs.
What do you think?
Best Regards
Adam Farley
>
>> On Feb 14, 2018, at 3:32 AM, Adam Farley8 <adam.farley at uk.ibm.com>
wrote:
>>
>> Hi All,
>>
>> Currently, diagnostic core files generated from OpenJDK seem to lump
all
>> of the
>> native memory usages together, making it near-impossible for someone to
>> figure
>> out *what* is using all that memory in the event of a memory leak.
>>
>> The OpenJ9 VM has a feature which allows it to track the allocation of
>> native
>> memory for Direct Byte Buffers (DBBs), and to supply that information
into
>> the
>> cores when they are generated. This makes it a *lot* easier to find out
>> what is using
>> all that native memory, making memory leak resolution less like some
dark
>> art, and
>> more like logical debugging.
>>
>> To use this feature, there is a native method referenced in
Unsafe.java.
>> To open
>> up this feature so that any VM can make use of it, the java code below
>> sets the
>> stage for it. This change starts letting people call DBB-specific
methods
>> when
>> allocating native memory, and getting into the habit of using it.
>>
>> Thoughts?
>>
>> Best Regards
>>
>> Adam Farley
>>
>> P.S. Code:
>>
>> diff --git
>> a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
>> b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
>> ---
a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
>> +++
b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
>> @@ -85,7 +85,7 @@
>> // Paranoia
>> return;
>> }
>> - UNSAFE.freeMemory(address);
>> + UNSAFE.freeDBBMemory(address);
>> address = 0;
>> Bits.unreserveMemory(size, capacity);
>> }
>> @@ -118,7 +118,7 @@
>>
>> long base = 0;
>> try {
>> - base = UNSAFE.allocateMemory(size);
>> + base = UNSAFE.allocateDBBMemory(size);
>> } catch (OutOfMemoryError x) {
>> Bits.unreserveMemory(size, cap);
>> throw x;
>> diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
>> b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
>> --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
>> +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
>> @@ -632,6 +632,26 @@
>> }
>>
>> /**
>> + * Allocates a new block of native memory for DirectByteBuffers,
of
>> the
>> + * given size in bytes. The contents of the memory are
>> uninitialized;
>> + * they will generally be garbage. The resulting native pointer
will
>> + * never be zero, and will be aligned for all value types. Dispose
>> of
>> + * this memory by calling {@link #freeDBBMemory} or resize it with
>> + * {@link #reallocateDBBMemory}.
>> + *
>> + * @throws RuntimeException if the size is negative or too large
>> + * for the native size_t type
>> + *
>> + * @throws OutOfMemoryError if the allocation is refused by the
>> system
>> + *
>> + * @see #getByte(long)
>> + * @see #putByte(long, byte)
>> + */
>> + public long allocateDBBMemory(long bytes) {
>> + return allocateMemory(bytes);
>> + }
>> +
>> + /**
>> * Resizes a new block of native memory, to the given size in
bytes.
>> The
>> * contents of the new block past the size of the old block are
>> * uninitialized; they will generally be garbage. The resulting
>> native
>> @@ -687,6 +707,27 @@
>> }
>>
>> /**
>> + * Resizes a new block of native memory for DirectByteBuffers, to
the
>> + * given size in bytes. The contents of the new block past the
size
>> of
>> + * the old block are uninitialized; they will generally be
garbage.
>> The
>> + * resulting native pointer will be zero if and only if the
requested
>> size
>> + * is zero. The resulting native pointer will be aligned for all
>> value
>> + * types. Dispose of this memory by calling {@link
#freeDBBMemory},
>> or
>> + * resize it with {@link #reallocateDBBMemory}. The address
passed
>> to
>> + * this method may be null, in which case an allocation will be
>> performed.
>> + *
>> + * @throws RuntimeException if the size is negative or too large
>> + * for the native size_t type
>> + *
>> + * @throws OutOfMemoryError if the allocation is refused by the
>> system
>> + *
>> + * @see #allocateDBBMemory
>> + */
>> + public long reallocateDBBMemory(long address, long bytes) {
>> + return reallocateMemory(address, bytes);
>> + }
>> +
>> + /**
>> * Sets all bytes in a given block of memory to a fixed value
>> * (usually zero).
>> *
>> @@ -918,6 +959,17 @@
>> checkPointer(null, address);
>> }
>>
>> + /**
>> + * Disposes of a block of native memory, as obtained from {@link
>> + * #allocateDBBMemory} or {@link #reallocateDBBMemory}. The
address
>> passed
>> + * to this method may be null, in which case no action is taken.
>> + *
>> + * @see #allocateDBBMemory
>> + */
>> + public void freeDBBMemory(long address) {
>> + freeMemory(address);
>> + }
>> +
>> /// random queries
>>
>> /**
>>
>> Unless stated otherwise above:
>> IBM United Kingdom Limited - Registered in England and Wales with
number
>> 741598.
>> Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU
>
Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU
Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU
More information about the core-libs-dev
mailing list