Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

What's the Magic Behind Quarkus

What's the Magic Behind Quarkus

Quarkus is revolutionizing the way that we develop Java applications for the cloud-native era. Do you want to learn why Quarkus is different from everything else? Then come and join us on this session to take a look at how Quarkus works and the techniques it uses to achieve its dramatic startup speed improvements. As part of this we will also cover the Quarkus extension API, so you can see how to write your own extensions that take advantage of Quarkus’ unique architecture.

Edson Yanaga

July 24, 2019
Tweet

More Decks by Edson Yanaga

Other Decks in Technology

Transcript

  1. From monolith to... !4 • 1 monolith ≈ 20 microservices

    ≈ 200 functions • Scale to 1 vs scale to 0 • Start up time MONOLITH MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F
  2. !5 Why go through this pain? Agility, Scalability, Faster Business

    Reactivity Container platform App 1 Data App 2 Data App 3 Data App 4 App 5 Data
  3. • Startup overhead ◦ # of classes, bytecode, JIT •

    Memory overhead ◦ # of classes, metadata, compilation !6 The hidden truth about Java + containers RSS Heap Metaspace off-heap
  4. !7 Container platform Node NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS

    NodeJS Node Go Go Go Go Go Go Go Go Go Go Go Go Go Go Node HotSpot Heap HotSpot Heap HotSpot Heap HotSpot Heap The hidden truth about Java + containers
  5. !9 A cohesive platform for optimized developer joy: • Based

    on standards, but not limited • Unified configuration • Zero config, live reload in the blink of an eye • Streamlined code for the 80% common usages, flexible for the 20% • No hassle native executable generation Benefit No. 1: Developer Joy
  6. !10 Benefit No. 2: Supersonic Subatomic Java Memory (RSS) in

    Megabytes Quarkus + GraalVM 13 MB Quarkus + OpenJDK 74 MB Traditional Cloud-Native Stack 140 MB REST
  7. !11 Benefit No. 2: Supersonic Subatomic Java Memory (RSS) in

    Megabytes REST + CRUD Quarkus + GraalVM 35 MB Quarkus + OpenJDK 130 MB Traditional Cloud-Native Stack 218 MB
  8. !12 Benefit No. 2: Supersonic Subatomic Java Boot + First

    Response Time (in seconds) Quarkus + GraalVM 0.014 Seconds REST REST + CRUD Quarkus + OpenJDK 0.75 Seconds Quarkus + GraalVM 0.055 Seconds Quarkus + OpenJDK 2.5 Seconds Traditional Cloud-Native Stack 9.5 Seconds Traditional Cloud-Native Stack 4.3 Seconds Time to first response
  9. !13 Benefit No. 3: Unifies Imperative and Reactive • Combine

    both Reactive and imperative development in the same application • Use the technology that fits your use-case • Key for reactive systems based on event driven apps @Inject SayService say; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return say.hello(); } @Inject @Stream(”kafka”) Publisher<String> reactiveSay; @GET @Produces(MediaType.SERVER_SENT_EVENTS) public Publisher<String> stream() { return reactiveSay; }
  10. !14 Benefit No. 4: Best of Breed Frameworks & Standards

    Eclipse Vert.x Hibernate RESTEasy Apache Camel Eclipse MicroProfile Netty Kubernetes OpenShift Jaeger Prometheus Apache Kafka Infinispan
  11. GraalVM You keep using that word. I do not think

    it means what you think it means. The Enabler
  12. Closed-world assumption !17 Dead code elimination Substrate VM Classes JDK

    Classes JDK Classes Substrate VM Classes Java Application Classes Java Application Classes Native Executable
  13. !18 Not supported The Dark Side • Dynamic classloading •

    InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • Lambda, Threads (OK, pfff!) • References (similar)
  14. !19 Not supported The Dark Side • Dynamic classloading •

    InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • References (similar) The Good Parts
  15. !21 What does a framework do at startup time Move

    startup time to build time • Parse config files • Classpath & classes scanning ◦ for annotations, getters or other metadata • Build framework metamodel objects • Prepare reflection and build proxies • Start and open IO, threads etc
  16. !22 Do the work once, not at each start All

    the bootstrap classes are no longer loaded Less time to start, less memory used Less or no reflection nor dynamic proxy Build time benefits
  17. !23 Drives the gathering of metadata needed by GraalVM More

    Build time benefits • based on framework knowledge • Classes using reflection, resources, etc Minimize dependencies Help dead code elimination
  18. !24 The end result of a Quarkus build should be

    just enough bytecode to start the services that your application requires Anatomy of a Quarkus Application
  19. !25 Traditional Application Application Startup • Scan for annotations •

    Parse descriptors • Generate metamodel • Start Services Quarkus • Start Services
  20. !26 The final application contains Anatomy of a Quarkus Application

    • Your (possibly transformed) application code • All libraries needed for runtime • Generated code to wire up and start your services • Generated CDI (ArC) bean classes
  21. !27 Quarkus Extensions RESTEasy Netty Hibernate ORM Hibernate Validator MP

    OpenAPI MP JWT Eclipse Vert.X Agroal (conn pool) Narayana JTA MP Reactive Messaging Apache Camel ... Quarkus Core Arc (DI) Jandex Gizmo Graal SDK HotSpot SubstrateVM
  22. !28 Quarkus Consists of Two Parts Core Runtime Core Deployment

    Undertow Runtime Undertow Deployment ArC Runtime ArC Deployment
  23. !29 Build Process Compile Provision (curate) Wiring & Assemble (deployment)

    AOT Native Compilation Hotspot Runnable & Image Native Executable & Image app.jar frameworks Runnable java app native-app
  24. !31 Provisioning Phase • Applications only depend on runtime components

    • But we need the deployment components to execute the build • Provisioning phase resolves the required deployment dependencies
  25. !32 Provisioning Phase • Extensions contain a quarkus-extension.properties, generated by

    the extension-maven-plugin • This tells Quarkus what the corresponding deployment artifact is
  26. !34 Creating the runnable application Augmentation Phase • Processing done

    by @BuildStep methods • All processors produce and consume BuildItem instances • Ordering is based on a dependency graph, a build step is executed when all its dependencies are available
  27. !35 BuildItem • All information flows through this process via

    BuildItem instances • Two types, SimpleBuildItem and MultiBuildItem • A @BuildStep method will be run as soon as all the items it depends on have been produced • The build is seeded with some initial items (e.g. the current application root) • The build asks for some specific outputs (e.g. GeneratedClassBuildItem) • Core build items are in io.quarkus.deployment.builditem
  28. !36 Build Graph • The build is a directed graph,

    it starts with the requested outputs, and then figures out which @BuildStep methods it needs to call to achieve this and in what order • If your method does not produce anything it needs then it is not called
  29. !37 CombinedIndexBuildItem Important Items • Holds the Jandex annotation index

    • Can be used to look at any annotation or type hierarchy
  30. !38 AdditionalBeanBuildItem Important Items • Producing this turns a given

    class into a CDI bean • If you have classes in your runtime module that you want to be beans you should produce one of these
  31. !40 Declarative Config Configuration • Configuration is done via @ConfigRoot

    objects • All config is under the quarkus.* namespace • All config must have javadoc, which used as the documentation in the generated config file
  32. !42 Recorders let you invoke on an object at deployment

    time, but the actual invocation gets delayed to runtime. Bytecode Recording
  33. !43 Serializing logic and data Bytecode Recording • Recording allows

    you to specify what happens at startup time, without knowing anything about bytecode • Invocations made on a recorder are written to bytecode and executed at runtime • Primitives, JavaBean style objects and collections can all be passed as arguments • The return values can be passed into other recorders (although cannot be used directly)
  34. !44 Return Values • The return value from a recorder

    cannot be used directly (the object it represents has not actually been created yet) • But they can be passed to other recorders methods • We do this by creating proxies, so if the return type cannot be proxied wrap it in a RuntimeValue<> • This does not have to be the same recorder, or even the same build step • To pass them between build steps wrap them in a BuildItem
  35. !46 Quarkus simplifies the process Substrate • SubstrateVM has a

    lot of limitations compared to a normal JVM • Quarkus provides tools to easily work around these limitations • Most of these take the form of build items to explicitly request substrate functionality • For a full list see io.quarkus.deployment.builditem.substrate package • Also we support compile time boot
  36. !47 Not supported The Dark Side • Dynamic classloading •

    InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • Lambda, Threads (OK, pfff!) • References (similar)
  37. !48 ReflectiveClassBuildItem Native Build Items • Reflection does not work

    in native images unless it is explicitly enabled • This build item allows you to enable reflection for a given class • Fine grained, so you can choose if you want methods, fields and constructors registered
  38. !49 ReflectiveHierarchyBuildItem Native Build Items • Registers everything about the

    class for reflection • Supertypes, Field types, method parameters etc • Good for serialization use cases, where you need to set everything via reflection
  39. !50 SubstrateResourceBuildItem Native Build Items • Resources are not included

    by default in SubstrateVM • Using this build item you can specify resources that you want to include in the image
  40. !51 Boot once, run everywhere Compile time boot • When

    SubstrateVM creates a native image it can run java static initializers as part of the process • These run in a normal JVM, with no restrictions • The results are serialized directly into the native image • If you record code with @Record(ExecutionTime.STATIC_INIT) then this code will be run once at native image build time • The results are directly unpacked into memory when the native image is actually run
  41. !53 Unit and Integration Tests Extension Testing Framework • @QuarkusUnitTest

    can be used to test a different application for each test class • Quarkus is started and stopped between each class • @QuarkusTest can also be used (especially for native image), but needs its own ‘integration-tests’ module • A comprehensive test suite will generally have both