[00:00.000 --> 00:14.800] Alright, welcome. How do you like our little Duke rock stars here? So there's stickers [00:14.800 --> 00:20.820] going around somewhere so you can get some of these stickers. I think we have four different [00:20.820 --> 00:30.360] rock stars or something. Anyway, let's talk about Quarkus, obviously. Who am I? I'm a [00:30.360 --> 00:38.020] developer advocate at Red Hat. My name is Kevin Dubois. You can find me on Twitter or [00:38.020 --> 00:50.700] Macedon. So I know we've already talked in a few sessions today about, you know, traditional [00:50.700 --> 00:57.000] Java and the startup time and all that stuff, so I'll do that some more. So we'll talk [00:57.000 --> 01:08.900] about traditional Java. So traditional Java is, can I see the little hand? Traditional [01:08.900 --> 01:14.860] Java is designed for, let's say, different times, not designed for cloud-native workloads, [01:14.860 --> 01:24.580] necessarily. It's designed for running kind of long time. And what's important in traditional [01:24.580 --> 01:29.700] Java is throughput at the expense of footprint. So footprint can be quite large, right? You [01:29.700 --> 01:37.660] typically have traditional Java applications running on pretty beefy servers. And they're [01:37.660 --> 01:45.340] designed to be long running and you have dynamic loading and all that stuff with mutable systems. [01:45.340 --> 01:52.620] But in the cloud-native world, your throughput, you get that mostly through scaling. Your [01:52.620 --> 01:58.580] workloads are ephemeral, which means that, you know, like if you think of containers, [01:58.580 --> 02:04.460] when you scale up a container, when you start up a new application, those containers are [02:04.460 --> 02:09.580] going to start up and then maybe they're going to get rescheduled on a different node. And [02:09.580 --> 02:15.060] so containers kind of come and go. They're not going to be around. And if you change [02:15.060 --> 02:20.460] something in a container, that change is not going to last, right? Because that container, [02:20.460 --> 02:28.460] whatever you change inside, that's going to be gone when that container gets removed. [02:28.460 --> 02:36.500] So in that sense, we have to think of Java in a different way. We need to think about [02:36.500 --> 02:43.260] the footprint of it because we want smaller containers that we can schedule across different [02:43.260 --> 02:49.060] servers. You know, if you are familiar with Kubernetes and clusters, there's usually multiple [02:49.060 --> 02:54.780] servers on which it schedules containers. So, you know, we need to be able to handle [02:54.780 --> 03:04.420] that. And so that's where Quark has started, was kind of invented, I guess, because it's [03:04.420 --> 03:10.540] a framework that uses Java. But it's, you know, we call it supersonic because it starts [03:10.540 --> 03:17.940] up very fast. Subatomic because it's very small, like subatomic smaller than an atom. [03:17.940 --> 03:27.060] And it's still Java. So if we think, if we look at Quarkus in terms of startup time and [03:27.060 --> 03:34.860] in terms of memory usage, you can see here, this is a test that they did with a relatively [03:34.860 --> 03:43.780] small application running on a traditional cloud native stack. It took 136 megs of memory [03:43.780 --> 03:51.220] running the same application, you know, with Quarkus, you already got, you know, pretty [03:51.220 --> 03:57.060] good gain in memory, right? And that's running on the JVM. So it's the exact same application [03:57.060 --> 04:03.140] running on the JVM. And then, you know, compiled down to a native with Grail VM, you get, [04:03.140 --> 04:09.380] of course, even less memory usage. And you can see here, too, Quarkus starts up quite [04:09.380 --> 04:14.540] a bit faster than a traditional cloud native stack, which is ideal when we're talking about, [04:14.540 --> 04:19.380] you know, cloud native. We're talking about containers, talking about serverless, where [04:19.380 --> 04:27.660] we need to start up really fast so we can react quickly to, you know, changing loads. [04:27.660 --> 04:35.260] So startup time is one thing. There's also the warmup issue. I don't know if issue is [04:35.260 --> 04:43.260] the right word, but actually, when an application starts up, it takes a while with Java before [04:43.260 --> 04:52.100] you get your maximum throughput as well. So here we can see that, you know, like a traditional [04:52.100 --> 04:59.260] Java application, this is actually the point, and I think this is like 13 seconds or something, [04:59.260 --> 05:05.620] or it's actually able to be working at maximum throughput, which, you know, for this particular [05:05.620 --> 05:11.900] use case, it needed a certain amount of throughput to be able to handle load enough. And then [05:11.900 --> 05:16.940] you can see here with Quarkus, it goes quite a bit faster. Now, Quarkus isn't just about [05:16.940 --> 05:24.180] fast startup time, it's not just about memory, but it is kind of a nice feature of Quarkus. [05:24.180 --> 05:31.140] So if we think of containers and Kubernetes nodes, traditional Java applications, running [05:31.140 --> 05:37.700] on EAP or WebSphere or whatever, running on a Kubernetes node, you can see they take [05:37.700 --> 05:44.900] up quite a bit of space. Let's say that in this case, only four instances of the application [05:44.900 --> 05:53.980] can run, which isn't so ideal because if one of the pods, one of the containers goes down, [05:53.980 --> 06:04.660] that means you lose 25% of your workload, right? If you look at Quarkus, on the JVM, [06:04.660 --> 06:08.540] you already have quite a bit more density, which means that if one of these guys goes [06:08.540 --> 06:15.060] down or needs to be rescheduled or whatever, you still have, you know, what is it, maybe [06:15.060 --> 06:23.940] 70% or something, that's still up. And, you know, we can compare that to Node.js or [06:23.940 --> 06:32.220] a Go or something, where Go has quite a smaller footprint and with Quarkus native, we can [06:32.220 --> 06:37.820] actually be very comparable with Go, which is nice because that means that we can use [06:37.820 --> 06:45.780] our Java skills and not have to, you know, change languages and reinvent the wheel and [06:45.780 --> 06:52.220] still get all the benefits in the cloud native world of having fast startup and everything. [06:52.220 --> 06:58.220] So how does that work? So a traditional Java application, basically build time is when [06:58.220 --> 07:03.420] you do your packaging and then as it starts up, it loads config files and then does class [07:03.420 --> 07:08.460] pass scanning and build kind of its model of the world and everything, but this is when [07:08.460 --> 07:13.460] it starts up. So if you think of containers, again, that means that this all happens when [07:13.460 --> 07:23.140] the container starts up and that takes a while. And then, so with Quarkus, what we try to [07:23.140 --> 07:30.100] do is instead of doing all that, you know, at runtime, at startup time, we're trying [07:30.100 --> 07:38.100] to do all of this or as much as we can during build time before the application actually [07:38.100 --> 07:43.540] gets packaged, which means that during runtime, we have a lot less to do, right? So it starts [07:43.540 --> 07:51.020] up quite a bit faster. So that's kind of the cool thing about Quarkus. And then, so you [07:51.020 --> 07:57.500] can use Quarkus on JVM or you can compile it down to native, of course, just like most [07:57.500 --> 08:04.700] other frameworks. But there's some cool things about native compilation with Quarkus as well [08:04.700 --> 08:10.100] that we'll get into in just a second. So this is my favorite part about Quarkus. It's not [08:10.100 --> 08:14.740] necessarily, I mean, yes, it's nice that it starts up fast. It's nice that it has a small [08:14.740 --> 08:21.500] memory footprint. But what's really cool about Quarkus is that it has a bunch of different [08:21.500 --> 08:32.900] ways of making the experience of working with Java and Quarkus a lot more fun. So one of [08:32.900 --> 08:38.780] them is, you know, so of course, it's based on standards. So Quarkus uses, you know, your [08:38.780 --> 08:44.940] Java EE standards, the Java standards, uses, you know, Vertex and all that good stuff. [08:44.940 --> 08:52.820] So if you're used to that, hey, great. You basically already know Quarkus for 99%. What's [08:52.820 --> 09:00.140] really cool with Quarkus is that there's this dev mode. This basically, you can start Quarkus [09:00.140 --> 09:06.300] on your local machine in dev mode. It's going to start up. And it's going to just keep checking [09:06.300 --> 09:12.500] to see if you make changes in the class path. And so every time you make a change, it's [09:12.500 --> 09:17.340] going to automatically reload when you, you know, let's say go into your browser or whatever [09:17.340 --> 09:23.460] you make a new request. It's going to automatically reload your application so you don't need [09:23.460 --> 09:29.620] to recompile, redeploy every time you want to test something. Quarkus does that automatically [09:29.620 --> 09:36.500] so you can just go to your browser, hit refresh, and it's there. So make a code change, refresh, [09:36.500 --> 09:44.300] it's there. Which, you know, if you're a developer of a couple, you know, of some other language [09:44.300 --> 09:49.740] where that just happens, then that's not so cool. But in Java, that's pretty cool, right? [09:49.740 --> 09:53.500] So we've got our little guy here that says, wait, so you just save it and your code is [09:53.500 --> 10:01.620] running and it's Java? And the guy says, I know, right? Super Sonic Java. So that's, [10:01.620 --> 10:07.900] that's pretty cool. Another cool thing with Quarkus is that it has this concept of developer [10:07.900 --> 10:15.580] services. So who knows test containers? So basically it uses test containers built into [10:15.580 --> 10:23.860] Quarkus. So let's say that I'm developing an application and I'm adding an extension [10:23.860 --> 10:33.980] to use Postgres database or a Kafka, a Kafka topic or something. Actually, well, of course [10:33.980 --> 10:39.340] you have to have a Docker or Podman or something running on your local machine. But Quarkus [10:39.340 --> 10:47.140] will look and see, hey, you've got, you've got this dependency on a database. Do you [10:47.140 --> 10:51.140] have something configured on your local machine? Do you have a database running on your local [10:51.140 --> 10:56.140] machine? Is that configured in your application properties? If not, no worries, I'm just [10:56.140 --> 11:03.900] going to start up a container with that dependency, for example, a Postgres database and wire [11:03.900 --> 11:11.300] that up. So it's going to, you know, set the configuration so that it connects to that [11:11.300 --> 11:18.740] database automatically. And then you can even go and see, you know, what exactly that configuration [11:18.740 --> 11:26.500] is and then copy it down. Anyway, so that's the developer services. So Kafka or, yeah, [11:26.500 --> 11:30.580] there's a whole bunch of different developer services that you can use just out of the [11:30.580 --> 11:35.860] box, which is pretty nice because otherwise, you know, having to configure a database on [11:35.860 --> 11:42.100] your local machine or Lord forbid, a Kafka instance with all your zookeepers and all [11:42.100 --> 11:48.380] that stuff, that's not so easy. You also, you know, so you have live coding, you also [11:48.380 --> 11:56.500] have continuous testing. So kind of the same concept. So if you have unit tests, you start [11:56.500 --> 12:04.020] your continuous testing. So every time you make a code change, it knows, hey, this class [12:04.020 --> 12:08.500] is related to this unit test. So I'm going to rerun this unit test every time I make [12:08.500 --> 12:15.940] a change here or vice versa. If you're making a change in a unit test, it knows, you know, [12:15.940 --> 12:21.020] this is what I need to rerun. So it gives you quick and immediate feedback every time [12:21.020 --> 12:28.460] as you're developing, which, yeah, again, it's pretty handy. It also has a dev UI. So [12:28.460 --> 12:34.140] it has a UI in your browser where you can go and look at all these different, you know, [12:34.140 --> 12:43.380] developer services that are running, what Quarkis is doing. So again, I was talking at the start [12:43.380 --> 12:53.180] about Quarkis doing some optimization, right? So during the compilation time, so in the [12:53.180 --> 13:00.300] dev UI, you can actually see, you know, what it's doing, how it's optimizing and what it's [13:00.300 --> 13:05.420] going to remove from the class path because Quarkis does, you know, some introspection [13:05.420 --> 13:11.300] to make sure that, hey, this is used or this actually isn't used by your code. So I'm going [13:11.300 --> 13:20.740] to remove all that from the compilation. There's a Quarkis CLI, which, again, it's [13:20.740 --> 13:29.700] not super crazy, but so you can either use Quarkis with Gradle or Maven, or you can just [13:29.700 --> 13:36.300] use the Quarkis CLI, which means that you can do, like, Quarkis dev or Quarkis build [13:36.300 --> 13:45.860] or whatever. You can even use, you can say Quarkis image build or image push, and it's [13:45.860 --> 13:55.380] going to build your application. So build your application, build a container, and you can [13:55.380 --> 14:00.380] even push it automatically all, you know, from one command, which is kind of handy, [14:00.380 --> 14:07.020] right? And then one of the last, but not least, is unification of imperative and reactive [14:07.020 --> 14:19.020] programming. So Quarkis has a lot of reactive programming kind of built in underneath. Now, [14:19.020 --> 14:25.420] me, for example, I'm not a super deep expert in reactive programming, but what's nice with [14:25.420 --> 14:30.940] Quarkis, too, is that I can write imperative code, right? So just, you know, every statement [14:30.940 --> 14:37.260] gets handled one at a time and it blocks every time, whereas with reactive, you've got these [14:37.260 --> 14:44.220] event loops. But you can use both at the same time in the same, even in the same code in [14:44.220 --> 14:48.540] the same class. So for those who are familiar with reactive, usually you kind of have to [14:48.540 --> 14:53.700] decide, hey, if I'm going to build a reactive application, that means I have to decide before [14:53.700 --> 14:59.500] I start writing this code, you know, that this framework that I'm going to use is reactive [14:59.500 --> 15:06.940] and I can't combine the both. But with Quarkis, you can, which is nice. And best of all, it's [15:06.940 --> 15:12.700] still Java, right? So you get all these kind of features. And at the end of the day, if [15:12.700 --> 15:18.180] you're, you know, if you're familiar with Java, this is really not reinventing the wheel [15:18.180 --> 15:25.220] at all. So it uses micro-profile, vertex, rest easy, you know, like, and if you want [15:25.220 --> 15:30.780] to add extensions, you can interact directly with Kubernetes. So you can push your code [15:30.780 --> 15:39.300] directly to Kubernetes. You can create config maps or secrets directly from Quarkis. You [15:39.300 --> 15:49.180] can, you know, you can work really easily with Kafka and OpenShift, of course, patchy [15:49.180 --> 15:57.860] camel and all that. So in terms of native compilation, I think we've already had a few [15:57.860 --> 16:03.020] sessions about that. So I'm not going to go too deep into that other than, you know, if [16:03.020 --> 16:09.460] you can run Quarkis on the JVM and probably for 70 to 80 percent of the use cases, that's [16:09.460 --> 16:19.380] probably a good way to go. If you really want to have the fastest startup time and the smallest [16:19.380 --> 16:25.420] footprint, then you can, you know, do a native build of your Quarkis application with Quarkis, [16:25.420 --> 16:31.500] by the way, that's really easy because if you create a new Quarkis application, it already [16:31.500 --> 16:38.340] automatically has a native profile built in. So you can decide, you know, as you're doing [16:38.340 --> 16:45.340] your compilation, whether you want to do a native build or not. But yeah, so Red Hat [16:45.340 --> 16:51.180] is on the GrowlVM advisory board and then there's the mandrel project, which is a downstream [16:51.180 --> 17:02.740] distribution of GrowlVM specifically for building Java native builds. So, and that's what Quarkis [17:02.740 --> 17:09.900] uses to, for example, if I do a native build and I don't have GrowlVM installed on my local [17:09.900 --> 17:18.300] machine, Quarkis will again pull down a container, it's really good at pulling down containers [17:18.300 --> 17:23.660] to do a native build inside a container on your local machine. So again, then you don't [17:23.660 --> 17:29.380] need to have GrowlVM installed and configured on your local machine. So it really tries [17:29.380 --> 17:37.820] to make, you know, your life as easy as possible and, you know, kind of have the benefits of, [17:37.820 --> 17:41.340] you know, a lot of the things. So if you're thinking of, you know, should I do a native [17:41.340 --> 17:49.420] build or just run on the JVM? This is kind of an opinionated scoring. But, you know, if [17:49.420 --> 17:55.100] you want the maximum developer joy, the, you know, the best and easiest monitoring peak [17:55.100 --> 18:02.180] throughput and reduced max latency, then you want to run it on the JVM. If, for you, it's [18:02.180 --> 18:07.380] important to have the lowest memory footprint, a small packaging, and a very fast startup [18:07.380 --> 18:13.100] time, then a native build is probably the way to go. [18:13.100 --> 18:21.300] So what do you want to use? You know, what can you use Quarkis for? Virtually anything. [18:21.300 --> 18:28.660] So, you know, there are Quarkis-based Kubernetes operators. So there's an operator framework [18:28.660 --> 18:39.780] where you can create, you know, these automatic components in Kubernetes that manage resources [18:39.780 --> 18:45.940] in Kubernetes. You can create GitHub actions with Quarkis. You can create, you know, just [18:45.940 --> 18:54.940] regular jobs. Yes, you can build traditional Java applications, even monoliths with it. [18:54.940 --> 19:00.540] So this is, of course, the sweet spot of Quarkis is cloud-native applications, so event-driven [19:00.540 --> 19:10.900] applications, reactive systems, microservices, and serverless and functions. So that's about [19:10.900 --> 19:18.500] it for my session. So if you want to check out Quarkis more, developers.redhat.com has [19:18.500 --> 19:26.140] a ton of resources on Quarkis, on a lot of developer stuff. This dn.dev slash Quarkis [19:26.140 --> 19:32.980] tutorial is just a, you know, kind of a nice, lightweight introduction to Quarkis where [19:32.980 --> 19:38.900] you can create an application from scratch and then, you know, kind of add some components [19:38.900 --> 19:48.900] as you go. You add a database and then, you know, check out the live, the dev mode and [19:48.900 --> 19:55.180] all that stuff. And, you know, so it's a pretty nice thing. Yeah. And like I said, if you [19:55.180 --> 20:02.500] want to keep up to date, you can follow me on Twitter or Macedon. I try to post interesting [20:02.500 --> 20:08.300] stuff, but I don't know if that's really true, but we'll see. All right. And that's it for [20:08.300 --> 20:15.300] me. Thank you. Any questions? Yes. [20:15.300 --> 20:39.100] One of the first slides you compared startup time and peak performance and, like, the crowd [20:39.100 --> 20:48.660] time. I don't, yeah, I don't remember exactly the numbers on there. Yeah. So that, yeah, [20:48.660 --> 21:00.300] so the, yeah, definitely. So the peak throughput time, there was a slide about, you know, the [21:00.300 --> 21:10.100] three graphs. So, yeah, I think with the native compilation, you're not going to have necessarily [21:10.100 --> 21:18.620] more throughput than on the JVM, but you do get the startup time, you know, like the time [21:18.620 --> 21:29.620] it takes to get to the maximum throughput is faster when you're, when you're native. [21:29.620 --> 21:36.620] Yeah. Yeah. Yeah. We can look at it later. Yeah. Yes. [21:36.620 --> 22:05.620] Yeah. That's it. Yeah. [22:05.620 --> 22:11.860] Yeah. So the question was how easy is it, is it to migrate to Quarkus from, for example, [22:11.860 --> 22:21.980] spring boots? So Quarkus has spring compatibility extensions. And so that makes it relatively [22:21.980 --> 22:29.500] easy because basically you're, for the most part, you won't have to change your code. You [22:29.500 --> 22:34.260] just have to add the, you know, add the spring extensions. Of course, in your palm, you're [22:34.260 --> 22:41.740] going to need to make some changes, but it's fairly straightforward. My colleague, Eric [22:41.740 --> 22:51.380] D'Andrea, he wrote a book on spring, let's say, Quarkus for spring developers. And he [22:51.380 --> 22:58.580] does, he does talks too, but if you want on that developers.ridhat.com, you can find, [22:58.580 --> 23:04.220] you know, there's a section about books and you can find that book. But it's, yeah, overall [23:04.220 --> 23:09.060] pretty, pretty straightforward. So like I said, there are extensions so that you can [23:09.060 --> 23:19.140] keep using your spring annotations. Now, would I recommend you just migrating your application [23:19.140 --> 23:27.100] and keeping all your spring dependencies? Probably not. But it's kind of a nice way [23:27.100 --> 23:35.660] to migrate without too much work and then afterwards maybe migrate further. All right. [23:35.660 --> 23:36.660] Any more questions? Yes. [23:36.660 --> 24:02.780] So, so the question, if I understand correctly, right, so your, the question is, why, why [24:02.780 --> 24:26.780] should you use native compilation? Because on the JVM, you have all the kind of capabilities [24:26.780 --> 24:33.460] that the JVM brings, right? So in terms of, you know, garbage collection, in terms of [24:33.460 --> 24:43.380] throughput and everything, JVM is very optimized to do that. When you do a native build, the [24:43.380 --> 24:47.380] GralVM compiler is going to do kind of an opinionated approach of how to do your native [24:47.380 --> 24:52.060] build, but then that's also it. It's not going to be able to optimize afterwards like the [24:52.060 --> 24:59.900] JVM does. So, kind of depends. Yeah. I think we're out of time. But if anybody has any [24:59.900 --> 25:00.900] more questions? [25:00.900 --> 25:01.900] Any questions, you'll be up there. [25:01.900 --> 25:02.900] Yeah, yeah. [25:02.900 --> 25:03.900] Great. Thank you so much. [25:03.900 --> 25:24.140] All right. Thank you so much.