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

Faster, greener, and happier- why Quarkus should be your next tech stack

Faster, greener, and happier- why Quarkus should be your next tech stack

Java never went away, but it’s having a renaissance. After some initial teething pains on the cloud (too big, too slow, too hard to configure) a new breed of Java frameworks are changing everything. In this talk, Holly will introduce Quarkus and then delve into some of the advanced features you might not know about. She’ll cover native binaries, what makes Quarkus super-fast running on the JVM, TDD with Quarkus, and Quarkus’s carbon footprint. The talk includes some theory (what underpins Quarkus’s surprising speed?) and also live demos (does Quarkus really start faster than a light bulb? What does an integration testing flow with Quarkus look like?)

Holly Cummins

June 09, 2024
Tweet

More Decks by Holly Cummins

Other Decks in Programming

Transcript

  1. Holly Cummins Senior Principal Software Engineer, Quarkus Code Europe June

    10, 2024 @[email protected] faster greener happier why quarkus should be your next tech stack
  2. @holly_cummins #RedHat tea: slow feedback loop→developers drink a lot of

    tea the problems: typing: verbose programming model → repetitive boilerplate
  3. @holly_cummins #RedHat tea: slow feedback loop→developers drink a lot of

    tea the problems: typing: verbose programming model → repetitive boilerplate tedium
  4. @holly_cummins #RedHat “I can’t bring up the microservices in my

    Java dev stack … on my brand new Apple laptop with a M1 chip and 64GB of RAM.” - fintech CTO
  5. @holly_cummins #RedHat in production, it’s worse example microservices maths: airline

    maintenance scheduling system single service: ½ core + 1 GB RAM
  6. @holly_cummins #RedHat in production, it’s worse example microservices maths: airline

    maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances
  7. @holly_cummins #RedHat in production, it’s worse example microservices maths: airline

    maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances ~100 microservices
  8. @holly_cummins #RedHat in production, it’s worse example microservices maths: airline

    maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances ~100 microservices = 150 cores + 300 GB RAM
  9. @holly_cummins #RedHat tea: slow feedback loop→developers drink a lot of

    tea the problems: typing: verbose programming model → repetitive boilerplate
  10. @holly_cummins #RedHat tea: slow feedback loop→developers drink a lot of

    tea the problems: typing: verbose programming model → repetitive boilerplate tolls: high resource usage → paying cloud vendors lots of money
  11. @holly_cummins #RedHat the problems: c’mon, what about the rest of

    the world? internationalised version coffee, not tea
  12. @holly_cummins #RedHat coffee: slow feedback loop→developers drink too much coffee

    the problems: c’mon, what about the rest of the world? internationalised version coffee, not tea
  13. @holly_cummins #RedHat coffee: slow feedback loop→developers drink too much coffee

    the problems: copious code: verbose programming model → repetitive boilerplate c’mon, what about the rest of the world? internationalised version coffee, not tea
  14. @holly_cummins #RedHat coffee: slow feedback loop→developers drink too much coffee

    the problems: copious code: verbose programming model → repetitive boilerplate cost: high resource usage → paying cloud vendors lots of money c’mon, what about the rest of the world? internationalised version coffee, not tea
  15. @holly_cummins #RedHat Container platform machine node.js node.js node.js node.js node.js

    node.js node.js machine go go go go go go go go go go go go go go
  16. @holly_cummins #RedHat Container platform machine HotSpot Heap HotSpot Heap HotSpot

    Heap HotSpot Heap machine node.js node.js node.js node.js node.js node.js node.js machine go go go go go go go go go go go go go go
  17. @holly_cummins #RedHat traditional cloud-native java stack traditional cloud-native java stack

    traditional cloud-native java stack traditional cloud-native java stack node.js node.js node.js node.js node.js node.js node.js go go machine go go go go go go go go go go go go go go go go go go go quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus spoiler: we made stuff better :) container orchestration machine machine machine https:/ /developers.redhat.com/blog/2017/03/14/java-inside-docker/
  18. @holly_cummins #RedHat machine quarkus quarkus quarkus quarkus quarkus quarkus quarkus

    quarkus quarkus quarkus quarkus quarkus quarkus quarkus container orchestration machine traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack … a lot better quarkus native
  19. @holly_cummins #RedHat machine quarkus quarkus quarkus quarkus quarkus quarkus quarkus

    quarkus quarkus quarkus quarkus quarkus quarkus quarkus container orchestration machine traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack … a lot better quarkus native (but quarkus on jvm is also way smaller than traditional java)
  20. quarkus applications start fast quarkus + graalvm 0.014 Seconds rest

    application quarkus + open jdk 0.75 Seconds traditional cloud-native stack 4.3 Seconds https://quarkus.io/blog/runtime-performance/
  21. ok but does startup time matter? fast boot time means

    auto-scaling works better more resilience to load spikes
  22. quarkus + GraalVM 13 MB quarkus + OpenJDK 74 MB

    Traditional Cloud-Native Stack 140 MB rest application https://quarkus.io/blog/runtime-performance/ quarkus improves memory utilization
  23. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus?
  24. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus? uhh … are you supposed to shut down applications after using them?
  25. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus? uhh … are you supposed to shut down applications after using them? 120 instances (!)
  26. @holly_cummins #RedHat remember the airline scheduling application? “[With Quarkus], we

    can run 3 times denser deployments without sacrificing availability and response times of services. ” – Thorsten Pohl
  27. let’s talk about throughput. quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a

    trade-off of throughput against footprint 48 concurrent connections Traditional cloud native stack 3555 req/s
  28. but … traditional cloud native stack 3555 req/s quarkus native

    3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a trade-off of throughput against footprint 48 concurrent connections
  29. but … traditional cloud native stack 3555 req/s quarkus on

    jvm 6389 req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a trade-off of throughput against footprint 48 concurrent connections
  30. but … traditional cloud native stack 3555 req/s quarkus on

    jvm 6389 req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper no trade-off, just better :) a trade-off of throughput against footprint 48 concurrent connections
  31. traditional cloud native stack 3555 req/s quarkus on jvm 6389

    req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper
  32. traditional cloud native stack 3555 req/s quarkus on jvm 6389

    req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a trade-off of throughput against footprint
  33. traditional cloud native stack 3555 req/s quarkus on jvm 6389

    req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper no trade-off, just better :) a trade-off of throughput against footprint
  34. @holly_cummins #RedHat a highly dynamic runtime in a container is

    pointless loading classes that aren’t needed
  35. @holly_cummins #RedHat a highly dynamic runtime in a container is

    pointless loading classes that aren’t needed expensive, slow, reflection
  36. @holly_cummins #RedHat a highly dynamic runtime in a container is

    pointless loading classes that aren’t needed expensive, slow, reflection the same initialisation on every startup
  37. @holly_cummins #RedHat how does a java framework start? </> build

    time runtime load and parse • config files • properties • yaml • xml • etc.
  38. @holly_cummins #RedHat how does a java framework start? @ @

    </> build time runtime • classpath scanning and annotation discovery • attempt to load class to enable/disable features
  39. @holly_cummins #RedHat how does a java framework start? @ @

    </> build time runtime build a metamodel of the world
  40. @holly_cummins #RedHat how does a java framework start? @ @

    </> build time runtime start • thread pools • I/O • etc.
  41. @holly_cummins #RedHat how does a java framework start? @ @

    </> build time runtime ready to do work!
  42. @holly_cummins #RedHat what if we start the application more than

    once? @ @ </> @ @ </> @ @ </> @ @ </> so much work gets redone every time
  43. @holly_cummins JVM spends time loading classes for specific databases JVM

    class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database footprint example: Hibernate
  44. @holly_cummins JVM spends time loading classes for specific databases JVM

    class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database turns out they’re never used footprint example: Hibernate
  45. @holly_cummins JVM spends time loading classes for specific databases JVM

    turns out they’re never used JIT spends time unloading classes footprint example: Hibernate
  46. @holly_cummins Hibernate example: ~500 classes which are only useful if

    you're running an Oracle database loaded and then unloaded
  47. @holly_cummins Hibernate example: ~500 classes which are only useful if

    you're running an Oracle database loaded and then unloaded every single start.
  48. @holly_cummins unused implementation the one we want interface unused implementation

    unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  49. @holly_cummins unused implementation the one we want interface unused implementation

    unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  50. @holly_cummins unused implementation the one we want interface megamorphic call

    slow dispatching unused implementation unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  51. @holly_cummins the true cost of loaded classes isn’t just memory

    + start time the one we want monomorphic call fast dispatching interface
  52. @holly_cummins #RedHat @ @ </> build time runtime start •

    thread pools • I/O • etc. what if we initialize at build time?
  53. @holly_cummins #RedHat @ @ </> build time runtime ready to

    do work! start • thread pools • I/O • etc. what if we initialize at build time?
  54. ok but we don’t need native quarkus is faster and

    smaller than legacy frameworks, even running on the jvm
  55. @holly_cummins doing more up-front - speeds up start - shrinks

    memory footprint - improves throughput (!)
  56. @holly_cummins #RedHat with quarkus, developers have to type less boilerplate

    this is good, because we’re about to do a live demo with a broken finger
  57. @holly_cummins #RedHat tests are run on every code change “reverse

    code coverage” means only relevant tests run mvn quarkus:dev continuous testing
  58. @holly_cummins #RedHat testcontainers integration … without quarkus @TestConfiguration(proxyBeanMethods = false)

    public class ContainersConfig { @Bean @ServiceConnection public PostgreSQLContainer<?> postgres() { return new PostgreSQLContainer<>(DockerImageName.parse("postgres:14")); } } public class TestApplication { public static void main(String[] args) { SpringApplication .from(MySpringDataApplication::main) .with(ContainersConfig.class) .run(args); } } @Import(ContainersConfig.class)
  59. @holly_cummins #RedHat zero-config testcontainers integration the only thing you need

    to do to make testcontainers work is not configure anything # configure your datasource quarkus.datasource.db-kind = postgresql quarkus.datasource.username = sarah quarkus.datasource.password = connor quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase # drop and create the database at startup quarkus.hibernate-orm.database.generation = drop-and-create
  60. @holly_cummins #RedHat zero-config testcontainers integration the only thing you need

    to do to make testcontainers work is not configure anything # drop and create the database at startup quarkus.hibernate-orm.database.generation = drop-and-create
  61. @holly_cummins #RedHat zero-config testcontainers integration the only thing you need

    to do to make testcontainers work is not configure anything
  62. @holly_cummins #RedHat zero-config testcontainers integration the only thing you need

    to do to make testcontainers work is not configure anything quarkus also auto-invokes flyway and liquibase
  63. @holly_cummins #RedHat zero-config testcontainers integration realistically, use profiles so things

    work in production :) # configure your datasource %prod.quarkus.datasource.db-kind = postgresql %prod.quarkus.datasource.username = sarah %prod.quarkus.datasource.password = connor %prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase # on real databases, defaults to ‘none’, but let’s validate %prod.quarkus.hibernate-orm.database.generation = validate
  64. @holly_cummins #RedHat • databases • redis • keycloak • kafka

    • elasticsearch • kubernetes • … or add your own auto-provision services “dev services” using testcontainers under the hood
  65. @holly_cummins #RedHat package com.example; import org.jboss.logging.Logger; public class MyService {

    private static final Logger log = Logger.getLogger(MyService.class); public void doSomething() { log.info("It works!"); } } example: logging
  66. @holly_cummins #RedHat package com.example; import org.jboss.logging.Logger; public class MyService {

    private static final Logger log = Logger.getLogger(MyService.class); public void doSomething() { log.info("It works!"); } } example: logging import io.quarkus.logging.Log; Log
  67. @holly_cummins logging: compiled version public class MyService { // injected

    private static final Logger $logger = Logger.getLogger(Thing.class) public void doSomething() { $logger.info(“It works!”); } }
  68. @holly_cummins #RedHat package org.acme; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public

    class SpringDemo { public static void main(String[] args) { SpringApplication.run(SpringDemo.class, args); } } example: declaring an application
  69. @holly_cummins what if… you could inherit boilerplate Hibernate queries from

    a superclass, instead of having to write them all? example: hibernate
  70. @holly_cummins #RedHat @ApplicationScoped public class GreetingRepository { public Entity findByName(int

    name) { return find("name", name).firstResult(); } void persist(Entity entity) {} void delete(Entity entity) {} Entity findById(Id id) {} List<Entity> list(String query, Sort sort, Object... params) { return null; } Stream<Entity> stream(String query, Object... params) { return null; } long count() { return 0; } long count(String query, Object... params) { return 0; } } example: panache + hibernate
  71. @holly_cummins #RedHat example: panache + hibernate @ApplicationScoped public class GreetingRepository

    implements PanacheRepository<Greeting> { public Entity findByName(int name) { return find("name", name).firstResult(); } }
  72. @holly_cummins #RedHat DAO example: panache + hibernate @ApplicationScoped public class

    GreetingRepository implements PanacheRepository<Greeting> { public Entity findByName(int name) { return find("name", name).firstResult(); } } repository pattern
  73. @holly_cummins #RedHat example: panache + hibernate active record pattern @Entity

    public class Greeting extends PanacheEntity { public String name; public LocalDate issued; @Version public int version; public static List<Greeting> getTodaysGreetings() { return list("date", LocalDate.now()); } }
  74. @holly_cummins #RedHat int port = 8081; ClientInterceptor[] interceptors = new

    ClientInterceptor[3]; interceptors[0] = new EventLoopBlockingCheckInterceptor(); interceptors[1] = new IOThreadClientInterceptor(); interceptors[2] = new StorkMeasuringGrpcInterceptor(); // etc Channel channel = ManagedChannelBuilder .forAddress(“localhost", port) .usePlaintext() .build(); GreeterGrpc.GreeterStub greeter = GreeterGrpc .newStub(channel) .withInterceptors(interceptors); example: gRPC
  75. doing more up-front enables better devex runtime build time we

    can do cool code introspections here that would be too expensive and annoying to do at runtime @ @ </>
  76. @holly_cummins #RedHat the old ways all still work but you

    don’t have to type all the stuff unless you want to ok but i still don’t like magic
  77. @holly_cummins #RedHat <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-web</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-data-jpa</artifactId> </dependency>

    ok but we use spring option 1: compatibility libraries option 2: migration tooling • migration toolkit for applications (mta) • windup • open rewrite
  78. @holly_cummins #RedHat “After a week of development with quarkus, I

    was able to regain the same level of productivity as when I was developing with Spring Boot.” – Fawaz Paraïso, Decathlon
  79. @holly_cummins #RedHat density Source: Clement Escoffier experiment 1: cloud Setup:

    • 800 requests/second, over 20 days • SLA > 99% • AWS instances Assumptions: • Costs are for us-east-1 data centre
  80. @holly_cummins #RedHat Setup: • 800 requests/second, over 20 days •

    SLA > 99% Assumptions: Source: Clement Escoffier x Teads cloud carbon impact of framework choice interpolated carbon metrics
  81. @holly_cummins #RedHat Setup: • 800 requests/second, over 20 days •

    SLA > 99% Assumptions: Source: Clement Escoffier x Teads cloud carbon impact of framework choice the carbon is lower because the cost is lower interpolated carbon metrics
  82. @holly_cummins #RedHat Setup: • REST + CRUD • large heap

    • RAPL energy measurement • multiple instances to support high load
 Assumptions: • US energy mix Source: John O’Hara experiment 2: RAPL measurements
  83. @holly_cummins #RedHat Setup: • REST + CRUD • large heap

    • RAPL energy measurement • multiple instances to support high load
 Assumptions: • US energy mix Source: John O’Hara experiment 2: RAPL measurements quarkus on JVM has the lowest carbon … because it has the highest throughput
  84. • quarkus cuts carbon by ~2-3x* • native consumes more

    carbon than JVM carbon measurements: conclusions
  85. @holly_cummins #RedHat Emiliia Nesterovych Emmanuel Bernard Emre Kaplan Enrique gonzález

    Martínez Enrique Mingorance Cano Eoin Gallinagh Eric Deandrea Eric Wittmann Erik Åsén Erik Mattheis Erin Schnabel Eugene Berman Evan Shortiss Fabricio Gregorio faculbsz Falko Modler Fedor Dudinskiy Felipe Carvalho dos Anjos Formentin Felipe Henrique Gross Windmoller Fernando Comunello Fernando Henrique fhavel Fikru Mengesha Filippe Spolti Florian Beutel Florian Bütler Florian Heubeck Florin Botis Foivos Zakkak Foobartender Fouad Almalki Francesco Nigro Francisco Javier Tirado Sarti Francois Steyn Frank Eichfelder franz1981 freakse-sa Fred Bricon Frédérc Blanc Freeman Fang Fu Cheng Gabriele Cardosi Galder Zamarreño galiacheng Gavin King Gavin Ray Geert Schuring Geoffrey De Smet Geoffrey GREBERT Georg Leber George Gastaldi manofthepeace Manyanda Chitimbo Marat Gubaidullin Marc Nuri Marc Schlegel Marc Wrobel Marcel Hanser Marcel Lohmann Marcell Cruz Marcelo Pereira Marcin Czeczko Marcin Kłopotek Marco Bungart Marco Schaub Marco Yeung Marco Zanghì Marcus Paulo Marek goldmann Marek Skacelik Marián Macik Mario Fusco MarioHNogueira Mark Lambert Mark Little Mark McLaughlin Mark Sailes marko-bekhta Markus Heberling Markus Himmel Markus Schwer Martin C. Richards Martin Grammelspacher Martin Kouba Martin Muzikar Martin Panzer Martin Weiler martin-kofoed-jyskebank-dk MartinWitt Marvin B. Lillehaug masini Matej Novotny Matej Vasek Matheus Cruz Mathias Holzer Matteo Mortari Matthias Andreas Benkard Matthias Cullmann mauroal Max Andersen Max Gabrielsson Max Rydahl Andersen Victor Hugo de Oliveira Molinar Vincent Sevel Vincent van Dam Vinícius Ferraz Campos Florentino Viswa Teja Nariboina Vladimir Konkov Vojtech Juranek Vratislav Hais w.glanzer Walter Medvedeo Wayne Ellis Werner Glanzer Willem Jan Glerum William Antônio Siqueira Wim goeman Wippermueller, Frank wojciech.stryjewski Xavier Xieshen xstefank Y. Luis Yann-Thomas LE MOIGNE Yannick Reifschneider YassinHajaj Yelzhas Suleimenov yesunch9 Yoann Rodière Yoshikazu Nojima Youngmin Koo Yubao Liu yugoccp Yukihiro Okada Zaheed Beita zanmagerl zedbeit Zheng Feng Žiga Deisinger Zineb Bendhiba zohar Zoran Regvart Шумов Игорь Юрьевич 出 门 三不惹 open source community of contributors
  86. @holly_cummins #RedHat tl;dpa (too long didn’t pay attention) deployment density

    lower cloud bill frictionless development experience Medium Nano auto-provision services zero-config live coding continuous testing developer UI greener
  87. @holly_cummins #RedHat tl;sdpa (too long still didn’t pay attention) what

    problems is quarkus solving? tea typing tedium tolls taxes