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 27, 2023
Tweet

More Decks by Holly Cummins

Other Decks in Programming

Transcript

  1. Holly Cummins Senior Principal Software Engineer, Quarkus GOTO Amsterdam June

    27, 2023 @[email protected] faster greener happier why quarkus should be your next tech stack
  2. @holly_cummins #RedHat Container platform um … no machine NodeJS NodeJS

    NodeJS NodeJS NodeJS NodeJS NodeJS machine Go Go Go Go Go Go Go Go Go Go Go Go Go Go
  3. @holly_cummins #RedHat Container platform um … no machine HotSpot Heap

    HotSpot Heap HotSpot Heap HotSpot Heap machine NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS machine Go Go Go Go Go Go Go Go Go Go Go Go Go Go
  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 developer
  5. @holly_cummins #RedHat spoiler: we did better :) CONTAINER ORCHESTRATION Machine

    Machine Traditional Cloud-Native Java Stack Traditional Cloud-Native Java Stack Traditional Cloud-Native Java Stack Traditional Cloud-Native Java Stack Machine NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Go Machine Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus https:/ /developers.redhat.com/blog/2017/03/14/java-inside-docker/
  6. @holly_cummins #RedHat Container orchestration Node Quarkus Quarkus Quarkus Quarkus Quarkus

    Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Quarkus Node 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
  7. do quarkus applications start faster? Quarkus + GraalVM 0.014 Seconds

    REST Quarkus + OpenJDK 0.75 Seconds Traditional Cloud-Native Stack 4.3 Seconds https://quarkus.io/blog/runtime-performance/
  8. ok but does startup time matter? fast boot time means

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

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

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus?
  11. #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?
  12. #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 (!)
  13. do quarkus applications have higher throughput? 48 concurrent connections quarkus

    native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper
  14. do quarkus applications have higher throughput? 48 concurrent connections 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
  15. do quarkus applications have higher throughput? 48 concurrent connections 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
  16. 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
  17. 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
  18. 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
  19. @holly_cummins #RedHat 2010 multiple applications share a single application server

    instance application re-deployed many times between server restarts application dependencies changed while it is running
  20. @holly_cummins #RedHat a highly dynamic runtime in a container is

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

    pointless loading classes that aren’t needed expensive, slow, reflection
  22. @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
  23. @holly_cummins #RedHat how does a framework start? @ 
 @

    </> packaging 
 (maven, gradle…) build time runtime
  24. @holly_cummins #RedHat @ 
 @ </> load and parse config

    files, properties, yaml, xml, etc. Build Time Runtime how does a framework start?
  25. @holly_cummins #RedHat @ 
 @ </> • classpath scanning and

    annotation discovery • attempt to load class to enable/disable features Build Time Runtime how does a framework start?
  26. @holly_cummins #RedHat @ 
 @ </> build a metamodel of

    the world Build Time Runtime How does a framework start? how does a framework start?
  27. @holly_cummins #RedHat @ 
 @ </> start thread pools, I/O,

    etc. Build Time Runtime how does a framework start?
  28. @ 
 @ </> doing more up-front enables better devex

    @ 
 @ </> build time runtime build time
  29. @ 
 @ </> doing more up-front enables better devex

    @ 
 @ </> build time runtime runtime build time
  30. @holly_cummins #RedHat #GOTOams tests are run on every code change

    “reverse code coverage” means only relevant tests run continuous testing
  31. @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)
  32. @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); } }
  33. @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
  34. @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
  35. @holly_cummins #RedHat zero-config testcontainers integration the only thing you need

    to do to make testcontainers work is not configure anything
  36. @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
  37. @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
  38. @holly_cummins #RedHat #GOTOams • databases • redis • keycloak •

    kafka • elasticsearch • kubernetes • … or add your own auto-provision services “dev services” using testcontainers under the hood
  39. @holly_cummins #RedHat #GOTOams 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
  40. @holly_cummins #RedHat #GOTOams @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
  41. @holly_cummins #RedHat #GOTOams example: panache + hibernate @ApplicationScoped public class

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

    class GreetingRepository implements PanacheRepository<Greeting> { public Entity findByName(int name) { return find("name", name).firstResult(); } } repository pattern
  43. @holly_cummins #RedHat #GOTOams 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()); } }
  44. @holly_cummins #RedHat #GOTOams <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
  45. @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
  46. @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
  47. @holly_cummins #RedHat step 1: measure power usage wall power measurement

    more complete needs access to the wall and equipment
  48. @holly_cummins #RedHat step 1: measure power usage wall power measurement

    more complete needs access to the wall and equipment RAPL
  49. @holly_cummins #RedHat step 1: measure power usage wall power measurement

    more complete needs access to the wall and equipment RAPL programmatically accessible
  50. @holly_cummins #RedHat step 1: measure power usage wall power measurement

    more complete needs access to the wall and equipment RAPL programmatically accessible misses some components
  51. @holly_cummins #RedHat step 1: measure power usage wall power measurement

    more complete needs access to the wall and equipment data costs carbon RAPL programmatically accessible misses some components
  52. @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
  53. @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
  54. @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
  55. @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
  56. @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
  57. • quarkus cuts carbon by ~2-3x* • native consumes more

    carbon than JVM carbon measurements: conclusions
  58. @holly_cummins #RedHat “We can run 3 times denser deployments without

    sacrificing availability and response times of services. Quarkus live coding is a really good thing: Making changes and reloading pages instantaneously is a great feature.” – Fawaz Thorsten Pohl, Lufthansa AVIATAR
  59. @holly_cummins #RedHat 2019: Moved digital experience to Quarkus (from Spring

    Boot) • Startup times 40s ➡ 12s • RAM 800 MB ➡ 360 MB • Developer productivity ⬆ 30-40% – Christos Sotiriou, Vodafone Greece
  60. @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