Project Panama Overview
Total Page:16
File Type:pdf, Size:1020Kb
Project Panama Overview Vladimir Ivanov Senior Principal Software Engineer HotSpot JVM Compiler team Java Platform Group Oracle Corp. July, 1, 2019 Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 2 Project Panama: What’s in there? http://hg.openjdk.java.net/panama/dev $ hg branches foreign-memaccess 56962:45e5cd40b16b foreign+linkToNative 56956:644db9ac21f0 foreign+vector 55994:713e1f63be92 foreign 56953:9352af5aeb3c linkToNative 56952:d0393811439a vectorIntrinsics 55993:73fd0971fb14 vector-unstable 56964:872744a24575 … Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 3 Project Panama: What’s in there? http://hg.openjdk.java.net/panama/dev $ hg branches foreign-memaccess 56962:45e5cd40b16b foreign 56953:9352af5aeb3c JNI 2.0 linkToNative 56952:d0393811439a vectorIntrinsics 55993:73fd0971fb14 Vector API vector-unstable 56964:872744a24575 foreign+linkToNative 56956:644db9ac21f0 branch merges foreign+vector 55994:713e1f63be92 … Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 4 Better JNI “Codes like Java, works like native” $ hg branches … foreign 56953:9352af5aeb3c linkToNative 56952:d0393811439a JNI 2.0 foreign-memaccess 56962:45e5cd40b16b … Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 5 What’s in there? • foreign – jeXtract, libclang bindings (Henry, 2014-2016; Maurizio, Sundar, 2017-now) – Universal adapter (Mikael, 2015-2016) – Binder, vectors, etc. (Mikael Vidstedt, 2015-2016) – MemoryRegion, Scope, Pointer (Henry, Mikael, 2016) • linkToNative – MethodHandle-based native invoker (Vladimir Ivanov, 2015-now) • foreign-memaccess – attempt to decompose Pointer into a lower-level API (Maurizio, 2019-now) Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 6 JNI JNR Foreign User-defined Interfaces produced User-defined Interfaces by jextract generated generated bindings on-the-fly bindings on-the-fly Java JNR Java j.l.i Native libffi Native JVM stubs Library Target Target Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 7 Getpid in Java JNI workflow Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 8 Getpid in Java Panama workflow Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 9 Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 10 jeXtract - Header file -> Java interface unistd.class package mypackage; unistd.h #ifndef _UNISTD_H @Header(path=”unistd.h”) #define _UNISTD_H public interface unistd { @C(file=”unistd.h”, line=3, column=1, USR=”c:@F@getpid”) pid_t getpid(void); @NativeType(ctype=”pid_t (void)”, size=1) @CallingConvention(1) #endif // _UNISTD_H public int getpid(); } Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 11 Example: getpid() // Load native library Library lib = NativeLibrary.load(“c”); // Weave a class for the unistd interface, // and return an instance unistd unistd = NativeLibrary.create(lib, unistd.class) // Call the system getpid() function int pid = unistd.getpid(); Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 12 Off-heap Access Pointers and Arrays • Native pointers are modelled with generic class Pointer<X> – Pointer<X> = address + layoutpointee+ carrier • Basic operations – Offset, cast, dereference (get/set), iteration • Pointers lifecycle managed by Scope – Cannot dereference a pointer whose owning scope has been closed! • Native arrays are modelled with generic class Array<X> – Array<X> = Pointer<X> + size Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 13 Off-heap Access Pointers and Arrays Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 14 Native Method Handles MethodType mt = MethodType.methodType(int.class); MethodHandle mh = NativeLookup.findNative(“getpid", mt); int pid = mh.invokeExact(); Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 15 Native Method Handles Java Native Construction Lookup.findVirtual() et al Lookup.findNative() Reference DirectMethodHandle NativeMethodHandle (typed) Reference MemberName NativeEntryPoint (direct) Linker MH.linkToVirtual() et al MH.linkToNative() Invocation indy, MH.invoke(), MH.invokeEXact() “Making native calls from the JVM” by John Rose http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 16 Performance getpid Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 17 Native Method Handles linkToNative // int pid = mh.invokeExact(); @ 8 LambdaForm$MH::invokeExact_MT (29 bytes) force inline by annotation @ 11 Invokers::checkExactType (17 bytes) force inline by annotation @ 1 MethodHandle::type (5 bytes) accessor @ 15 Invokers::checkCustomized (23 bytes) force inline by annotation @ 1 MethodHandleImpl::isCompileConstant (2 bytes) (intrinsic) @ 25 LambdaForm$NMH::invokeNative_I (27 bytes) force inline by … @ 7 NativeMethodHandle::internalNativeEntryPoint (8 bytes) force inline … @ 23 MethodHandle::linkToNative(L)I (0 bytes) direct native call Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 18 Native Method Handles linkToNative callq 0X1057b2eb0 ; native method entry getpid JNI 13.7 ± 0.5 ns Direct call 3.4 ± 0.2 ns Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 19 Calling Convention Java vs C hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp: “The Java calling convention is a "shifted" version of the C ABI. By skipping the first C ABI register we can call non-static jni methods with small numbers of arguments without having to shuffle the arguments at all. Since we control the java ABI we ought to at least get some advantage out of it.“ System V AMD64 ABI arg 1st 2nd 3rd 4th 5th 6th … C RDI RSI RDX RCX R8 R9 stack Java RSI RDX RCX R8 R9 RDI stack Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 20 “Universal Adapter” • jdk.internal.nicl.NativeInvoker – static native void invokeNative(long[] args, long[] rets, long[] recipe, long addr); – alternative to MH.linkToNative() • Very powerful mechanism – fully programmable calling conventions through “recipe” • Rich functionality support – varargs – struct-by-value argument + return – callbacks (function pointers) • Hard to optimize by JITs Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 21 Optimize checks void run() { nativeFunc1(); // checks & state trans. nativeFunc2(); // checks & state trans. nativeFunc3(); // checks & state trans. } Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 22 Java Heap Thread State Thread Java Native VM Native Memory Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 23 Optimize checks void run() { if (!performChecks()) jump failed; transJavaToNative(); call nativeFunc1(); call nativeFunc2(); call nativeFunc3(); transNativeToJava(); } Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 24 Java Heap Thread State Thread Java Native VM Native Memory Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 25 Advanced Use Cases Structs Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 26 Advanced Use Cases Callbacks Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 27 qsort Benchmark / JNI Panama Panama Native # of upcalls Raw 0 41.2 ±1.1 43.3 ±5.8 44.0 ±1.1 45.3 ±1.1 ops/us 2 5.0 ±0.8 16.1 ±0.3 20.8 ±0.5 34.7 ±0.7 10 278 ± 16 1473 ± 23 2490 ± 25 14067 ±890 … ops/ms 10^3 3.1 ±0.1 15.7 ±1.3 28.6 ±0.6 249 ±6.6 10^6 3.1 ±0.1 13.1 ±0.4 28.1 ±1.3 246 ±3.3 ops/s JNI upcall to Java using JNI int cmp(int x, int y) { return x - y; } Panama l2N-based upcall to Java (Pointer p1, Pointer p2) -> { p1.get() - p2.get() } Panama Raw l2N-based upcall to Java (long p1, long p2) -> { U.getInt(p1) - U.getInt(p2) } Native No upcalls int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; } Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 28 Upcalls Benchmark / JNI Foreign linkToNative # of upcalls 0 (baseline) 11.6 ±0.4 12.0 ±0.4 10.9 ±0.5 ns/op 1 171 ± 13 104 ±3.9 42 ±5.9 10 1608 ± 21 962 ± 23 382 ± 16 1000 159 ±6.9 94 ±4.2 33 ±0.6 us/op Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 29 Panama: Foreign Scorecard • Ease of use: from header files to native bundles with jeXtract • Rich API provides seamless integration with native code – much of the JNI boilerplate can now be eXpressed in Java! • A safer alternative to JNI – Scope API manages resource lifecycles (pointers, structs, callbacks, …) • Room for performance improvement is huge – Reduce latency of native calls, hoist native transitions out of loops, ... • Not just for C! Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 30 Panama: Foreign http://hg.openjdk.java.net/panama/dev/raw-file/9352af5aeb3c/doc/panama_foreign.html Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | 31 Panama: Foreign What’s next? • function like