Panama feedback
Ty Young
youngty1997 at gmail.com
Mon Mar 30 20:35:27 UTC 2020
Hi all,
After doing abstraction layer, multiple hand-made bindings, and an
entire API swap from old Pointer API to new foreign memory-access at the
OO layer, my JavaFX application has been rebased on current Panama.
There are a few things that have come out of it.
For reference, the old project dependency hierarchy looked like:
Pointer Bindings -> OO API -> JavaFX
The new dependency hierarchy looks like:
Foreign Memory Access API -> abstraction layer -> hand-made bindings ->
OO API -> JavaFX
The JavaFX application has a single background thread that updates the
GPUs attribute information(like 50 of them) with a 1 second wait between
updates. I'm also using a newer version(14) of JavaFX right now then I
was then with the Pointer API.
The first being that *there isn't, AFAIK, a way to find *native* memory
leaks.* Most object references within the OO API are final, as there
will always need to be, for example, an int pointer to read a GPUs temp
for the life time of that GPU.
However, hypothetically if there was a memory leak, I don't know how i'd
go about finding it. A few bytes memory leak is hardly noticeable even
after hours of use. If there isn't already, It would be nice if there
was a way to profile native memory allocations via MemoryAccess.
Going along with that, *there seems to be a significant increase in
allocations.* I don't have a build of the old Pointer JDK so I can't
compare, but at about 135MB min heap sizes according to Netbeans's
profiler, it feels like there is a lot of needless allocations happening.
It might just be JavaFX(which is known to have memory issues), I don't
know, but according to Netbean's profiler *something* is allocating MB
worth of HashMaps and HashNodes and heap allocations of those goes as
high as 30 MB before dropping to 8 MB once a GC is finished. There
doesn't seem to be any leaks per se, just a crazy amounts of allocations
that are then thrown away. Without better memory profiler
tools(jProfiler) I can't really see what's causing it.
Moving away from memory issues, *I'd like to see a feature added to
jextract to be able to just dump layout information*. I have no interest
in using jextract for creating bindings as I have said before, but a
tool for generating the correct struct layouts is still very useful. I'd
rather it just dump the information to console rather than to on-disk
too, if it's possible.
*As a bonus, it would be nice if you didn't need to include every
required header file that would normally be required to generate
jextract bindings.***In other words, if a struct uses a type which is
defined in another header that isn't included, a warning is thrown and
it just spits out layouts for what it can figure out.
As for major API gripes,*l**ooking at the new "Foreign" API, it feels to
me like it's a bit too thin and there isn't enough there to justify it.*
Taking out the string utility code leaves 3 methods, one of which is
just a getter for SystemABI.
Personally I'd like to see SystemABI reverted back and provide both
platform specific and runtime layouts. An interface which defines a
standard way of getting standard cross-platform types and the ABI name
can be defined and implemented by "WindowsABI", "SysVABI", and
"AArch64ABI" classes. SystemABI would then provide those classes via
static constants(not the interface implementations, the actual class
since platforms have their own specific layout types) and implement the
interface so that it provides current ABI layouts.
(Or just have a getABI() method. Probably the easiest.)
I think at that point what remains of MemoryLayouts(Java, padding, etc)
could then be merged into MemoryLayout. This would add a better divide,
making things less blurry, I think. Runtime layouts are currently just
thrown into MemoryLayouts right next to Java ones and it feels a bit off.
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.
*There is also currently no explicit null input argument checks for
things like unsafe operations methods.* Don't know if that's intentional
or not, but if possible, I'd like to see explicit checks, especially on
"unsafe" operations. I had a bit of a "WTF" moment when making stdlib
bindings because I forgot to change FunctionDescriptor/MethodHandle to
return something which resulted in a semi-unhelpful NullPointerException
when I attempted to make a null unsafe MemoryAddress safe.
(That new JDK 14 Helpful NullPointerExceptions feature is really nice, BTW!)
Maybe i'm just blind but *there doesn't seem to be a way to do
callbacks*. I'm guessing since you use downcall to get a function
address that you do upcall, but I'm not sure how to go about using it.
That pretty much covers it. I can't speak about performance or anything
else since what I'm using Panama for doesn't require every last drop of
performance. I can say that weird oddities like getting random numbers
from a Pointer<Integer>, for example, no longer happen which is nice.
Getting a really large, seemingly random number when asking what the
GPU's utilization(0-100%) was was a bit "WTF".
I should also probably take the time here to say thanks to everyone
who's working on this. I really appreciate the amount of time, thought,
and overall effort that is being put into this. Panama is making native
binding creation a breeze so far. Many thanks to everyone!
More information about the panama-dev
mailing list