Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Micronaut AOT: optimiser vos application pour le JIT et GraalVM

Micronaut AOT: optimiser vos application pour le JIT et GraalVM

Cédric Champeau

July 01, 2022
Tweet

More Decks by Cédric Champeau

Other Decks in Programming

Transcript

  1. Micronaut® AOT Optimizing your apps for the JIT and GraalVM

    Cédric Champeau OracleLabs @CedricChampeau Copyright © 22-7-1, Oracle and/or its affiliates Micronaut® is a registered trademark of Object Computing, Inc. Use is for referential purposes and does not imply any endorsement or affiliation with any third-party product. Unauthorized use is strictly prohibited.
  2. • Working at Oracle Labs on Micronaut  Main focus

    on build plugins and dev productivitity • Formerly working at Gradle Inc • Author of static compiler of Groovy • Amateur astronomer  @CedricChampeau  https://www.astrobin.com/users/melix/ About me Copyright © 2021, Oracle and/or its affiliates micronaut.io github.com/micronaut-projects/micronaut-core
  3. • Micronaut is focused on modern architectures like Serverless and

    Microservices • Also a complete framework for any type of application • Lightweight, reactive (HTTP Client/Server based on Netty) • Annotation processor to compute framework infrastructure at compile time Micronaut Copyright © 2021, Oracle and/or its affiliates micronaut.io github.com/micronaut-projects/micronaut-core
  4. Micronaut = Build Time Framework Infrastructure Copyright © 2021, Oracle

    and/or its affiliates Micronaut computes: • All dependency & configuration injection • Annotation metadata, meta-annotations • AOP proxies • Bean introspections • And all other framework infrastructure • Reflection, runtime proxy, and dynamic classloader free
  5. GraalVM Copyright © 2021, Oracle and/or its affiliates • High-performance

    JDK distribution • Increases application throughput, reduces latency, reduces memory use • Graal just-in-time (JIT) compiler that runs on top of HotSpot, written in Java • native-image ahead-of-time (AoT) compiler compiles Java applications into small self- contained native binaries graalvm.org github.com/graalvm/graalvm-demos oracle.com/graalvm
  6. Micronaut GraalVM ♥️ Copyright © 2021, Oracle and/or its affiliates

    • Micronaut + GraalVM Native Image are a match made in heaven • Less work to configure Native Image because Micronaut eliminates reflection, runtime proxies, bytecode generation and dynamic classloading • Startup time 20ms and Memory Consumption 18MB! ♥️
  7. Copyright © 2022, Oracle and/or its affiliates 12 Add the

    Micronaut AOT plugin Configure optimizations
  8.  Optional extension to the Micronaut framework  Available via

    build tool plugins (Gradle, Maven or CLI invocation)  Performs deployment optimizations  Generates an application which is tailored to a particular deployment environment  Generates distinct optimizations for the “regular” JVM (aka “JIT mode”) or native (aka “GraalVM”)  Can optimize  CLI applications  HTTP applications  Functions (currently tested with AWS Lambda and Oracle Cloud Functions, Azure coming) Micronaut AOT Copyright © 2022, Oracle and/or its affiliates 14
  9. Building an application without Micronaut AOT Copyright © 2022, Oracle

    and/or its affiliates 19 Sources (.java, .groovy, .kt) class files javac + Annotation processing Resources (.yaml, .properties) Jar file packaging packaging Native binary native-image
  10. Building an application with Micronaut AOT Copyright © 2022, Oracle

    and/or its affiliates 20 jar file (or classes + resources) class files AOT jar file Native AOT binary native-image Resource files Source files Metadata filtering AOT analysis
  11.  Optimizing service loading  pre-scans META-INF/service files (for some

    core types) and generates classes which avoid the use of service loader and permits parallel loading  Generated loaders are different in JIT and native!  Converting YAML files to Java  Avoids parsing YAML files at application startup  Reduces the size of the generated native binary  Caching the environment  Once the application is started, all environment variables and system properties are deemed immutable  Pre-computing bean requirements  Evaluates @Requires conditions at build time instead of runtime  Reduces the size of the generated native binary Micronaut AOT Core Optimizations Copyright © 2022, Oracle and/or its affiliates 21
  12.  Optimizing classloading  Performs Class#forName at build time to

    avoid ClassNotFoundException at run time  Deducing the environment at build time  Performs the “environment deduction” (AWS, Google Cloud, …) at build time instead of run time  Precomputing “expensive operations”  Pre-computes some constants at build-time instead of run time  For example, the mapping between environment variable names and Micronaut properties  (Experimental) Converting logback.xml to Java configuration  Avoids loading the XML parsing library at application startup Micronaut AOT Core Optimizations Copyright © 2022, Oracle and/or its affiliates 22
  13. public class StaticServicesLoader implements StaticOptimizations.Loader<SoftServiceLoader.Optimizations> { @Override public SoftServiceLoader.Optimizations load()

    { Map<String, SoftServiceLoader.StaticServiceLoader<?>> staticServices = new HashMap<String, SoftServiceLoader.StaticServiceLoader<?>>(); staticServices.put("io.micronaut.context.env.PropertySourceLoader", new PropertySourceLoaderFactory()); staticServices.put("io.micronaut.http.HttpResponseFactory", new HttpResponseFactoryFactory()); staticServices.put("io.micronaut.inject.BeanDefinitionReference", new BeanDefinitionReferenceFactory()); staticServices.put("io.micronaut.core.beans.BeanIntrospectionReference", new BeanIntrospectionReferenceFactory()); staticServices.put("io.micronaut.inject.BeanConfiguration", new BeanConfigurationFactory()); staticServices.put("io.micronaut.http.HttpRequestFactory", new HttpRequestFactoryFactory()); return new SoftServiceLoader.Optimizations(staticServices); } } Micronaut AOT: Code generation Copyright © 2022, Oracle and/or its affiliates 23
  14.  Faster startup time  10% faster, sometimes more depending

    on your context  Smaller native images  By substitution, some classes are not reachable anymore  Results depend on the transitive dependency graph  Improved time to first request  Module specific optimizations can access resources at build time Micronaut AOT: what benefits to expect? Copyright © 2022, Oracle and/or its affiliates 24
  15. graalvmNative { binaries.all { // profiling buildArgs.add("-H:-DeleteLocalSymbols") buildArgs.add("-H:+PreserveFramePointer") } }

    Micronaut AOT: profiling native applications Copyright © 2022, Oracle and/or its affiliates 25
  16.  Micronaut Serialization  Provides compile-time databinding  Replacement for

    Jackson Databind  Runtime can use Jackson, BSON or JSON-P Impact on image size Copyright © 2022, Oracle and/or its affiliates 28
  17.  Micronaut AOT supports plugins  Plugins are “source generators”

    which get access to the application context  Generated code can inject optimizations into Micronaut via dedicated API  Plugins contribute new optimizations  Eg: Micronaut Security can fetch OpenID metadata configuration from remote at build time. Can save up to 1s at the first request!  Code generators execute within the context of the target application! Micronaut AOT extensibility Copyright © 2022, Oracle and/or its affiliates 29
  18. Micronaut AOT extensibility Copyright © 2022, Oracle and/or its affiliates

    30 @Override public void generate(@NonNull AOTContext context) { context.registerStaticOptimization("KnownMissingTypesOptimizationLoader", ClassUtils.Optimizations.class, body -> { List<String> classNames = context.getConfiguration().stringList(OPTION.key()); body.addStatement("$T knownMissingTypes = new $T()", ParameterizedTypeName.get(Set.class, String.class), for (String knownMissingClass : findMissingClasses(classNames)) { body.addStatement("knownMissingTypes.add($S)", knownMissingClass); } body.addStatement("return new $T(knownMissingTypes)", ClassUtils.Optimizations.class); }); } private List<String> findMissingClasses(List<String> classNames) { List<String> knownMissingClasses = new ArrayList<>(); ClassLoader cl = this.getClass().getClassLoader(); for (String name : classNames) { try { cl.loadClass(name); } catch (ClassNotFoundException | NoClassDefFoundError e) { knownMissingClasses.add(name); } } return knownMissingClasses; } This happens in user application context
  19.  Micronaut is a modern framework which uses build-time optimizations

     Use of annotation processing for generating metadata, avoiding reflection, …  Micronaut AOT complements the approach  Not everything can be done by annotation processing  Substitution of classes/resources  Parsing configuration files  Sensitive to the build environment and therefore sensitive to the deployment environment Conclusion Copyright © 2022, Oracle and/or its affiliates 31
  20.  Micronaut Website  https://micronaut.io  Micronaut Launch  Bootstrap

    your Micronaut apps: https://micronaut.io/launch  Micronaut AOT  Documentation: https://micronaut-projects.github.io/micronaut-aot/latest/  Gradle plugin: https://micronaut-projects.github.io/micronaut-gradle-plugin/latest/#_micronaut_aot_plugin  Maven plugin: https://micronaut-projects.github.io/micronaut-maven-plugin/latest/examples/aot.html  GraalVM Community Edition  https://www.graalvm.org/ Links Copyright © 2022, Oracle and/or its affiliates 32