Panama feedback
Ty Young
youngty1997 at gmail.com
Tue Mar 31 13:06:07 UTC 2020
On 3/30/20 6:48 PM, Maurizio Cimadamore wrote:
> I hear you - one of the reasons we might want an allocator other than
> malloc, beside performance, is precisely this: diagnosability
> (especially if such allocator would be used JDK-wide, even by native
> code). This of course doesn't fully protect from native memory
> allocated by the API, but it would cover all the one allocated via the
> memory segment API.
>
> Then there's the problem of forgetting to close() some segments; and I
> think Netty did some experiments in this area to run the code in a
> special, slower mode which reported error for every buffer which
> became unreacheable before its close method could be called. Something
> along those lines could be added.
IMO, just like with the "warn" option of jdk.incubator.foreign.Foreign
system property, there needs to be more information than simply
"WARNING: MemoryAddress reference handle has become unreachable!". There
needs to be a robust, IDE hookable solution so that native memory
allocated via Panama can be viewed just like normal on-heap JVM memory.
Simply spamming doesn't provide enough useful information.
>
> While the native interop API is not in a state where we can say that
> we've optimized it for memory footprint, what you say sounds weird.
> The only widespread-enough use of maps that I can think of, is that
> for storing memory layouts attributes. So, when creating lots and lots
> of garbage layouts, I guess it's also possible to create lots and lots
> of garbage maps.
>
> As for profilers, in the past I found Eclipse Memory Analyzer quite
> useful and fast in processing even gigabytes of heap. Perhaps you
> could take a look at that.
Probably just JavaFX then. I'll have to look into it in-depth later.
>
> These are all good suggestions and part of a bigger topic that at some
> point we'll need to revisit about how to filter bindings in the
> optimal way. Generating only layouts is another way to filter the
> binding output to only include types (for which we're thinking about
> adding a lot more helper functions than we do at the moment, we're
> doing some experiments there).
>
> There are many ways to skin the cat there:
>
> * command line options
> * user-defined plugins/visitors
> * side-files which contain list of desired symbols to be extracted
>
> As you say with filtering there's always a problem of defining what
> happens when you have a symbol S1 which is inside the filter which
> refers to a symbol S2 which is outside the filter; again, many
> possible behaviors:
>
> * error - stop
> * warning - try to figure out something that still makes some kind of
> sense
> * force-include what was left out
>
> While I don't have a specific solution to propose at this time, my
> feeling is that we should provide tools to help people to generate as
> small bindings as possible; and then perhaps have a 'I don't care
> mode' where the tool is allowed to pull in the entire world. But the
> former mode is gonna be crucial in context where you need to limit the
> amount of static footprint and classes being loaded.
Absolutely. I kind of prefer to do bindings by hand simply because of
the small footprint where as with jextract I'd have to include X server
headers simply because they were included. In the vast majority of
instances, the custom types are just standard types anyway, but because
of how jextract works, you have to pull in everything.
FWIW, I think just skipping any struct that uses a not included type is
the best option here. Attempting to make guesses as to what something is
will probably end badly.
>>
>> A minor API gripes is that, *currently, there is no way to create
>> zero length arrays.* I think this can be added by introducing
>> "INVALID" constant SequenceLayout which, when passed to
>> AllocateNative, results in AllocateNative returning
>> MemoryAddress.NULL. Since the byte size of MemoryAddress.NULL is
>> zero, I feel like this should be a safe thing to do.
>
> Uhm - not sure; why would you want to create the layout of a
> zero-length array?
Specifically for functions like this:
https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html#group__nvmlDeviceQueries_1g7eacf7fa7ba4f4485d166736bf31195e
In other words, arrays which depend on another pointer's value which may
be 0. This can result in situations where code might run fine on one
persons computer(or same computer, different config) but not on another,
as with the function above.
You can just do manual safeguard checks, yes, but someone might not know
or forget them.
> You mean? Passing Java code as a function pointer to some native call?
> Sure there is a way to do that! If this is really what you are looking
> for I can give you pointer to some examples using that feature.
Yes, please!
> One question for you - given some feedback you gave recently on some
> of the messages I posted on a pull request; after having tried this
> stuff some more, what is your feeling towards the choice of making
> native pointers non-de-referenceable by default? You seemed to be very
> skeptical at first on this one - but your message the other day gave
> me the impression that you might have a different opinion now; is my
> reading correct? E.g. is it something that, after getting used to,
> gets better, or that you don't bump into it too often, or is it just
> plain annoying - based your experiments?
I don't think my views on anything specific within Panama's foreign
memory access API has changed in any major way but rather how I view the
API as a whole has. Coming from the old Pointer API I was expecting a
power drill but what I found was a screwdriver. As someone who doesn't
really care about the bindings himself, it wasn't(and still isn't) ideal.
So I took that screwdriver and made a power drill(abstraction layer)
with it, sort to speak. Now that I have my abstraction layer, my gripes
with it aren't as big of a deal. In most cases the only difference
between a "MemoryValue" abstraction that utilizes a "safe" MemoryAddress
and a "unsafe", natively allocated MemoryAddress is which constructor is
used:
"safe" if the constructor only accepts a ValueLayout.
"unsafe" if the constructor accepts a MemoryAddress AND a ValueLayout.
Note that an otherwise safe, sliced MemoryAddress goes through here too.
Otherwise they are basically the same. I've basically been using
ValueLayout(s) not just as a reliable way of creating a MemoryAddress,
but also an interpreted view of an existing MemoryAddress(which makes
sense).
There are things I still have gripes with such as the exceptions and the
way unsafe access is granted(bindings can just change to permit anyway),
but overall I'm happy with it.
>
> Cheers
> Maurizio
>
More information about the panama-dev
mailing list