BombeI don’t think that even compiles, which makes it doubly worthless!
jreicherIt's art, apparently. Heathen.
BombeCan’t argue with that, I guess.
* ptomli2 joined #java
* Everything joined #java
* Everything joined #java
* JazzJackalope joined #java
* enoq joined #java
enoqso we're gonna build a backend for frontend application pretty soon; looking at virtual threads, we could use spring servlet APIs and get a lot of performance out for free, but I'm unsure if that's a good idea if most of your application will do I/O and potentially wants to do API requests in parallel
enoqfrom what I've seen structured concurrency APIs are in preview and I don't really know how easy/well those would integrate into a classic spring boot servlet server; do I want to go with reactive instead?
ParaUse the cache, Luke :)
enoqone issue I could see when going reactive is probably hibernate; there's a reactive version available, but I'm unsure how well those work; I'll definitely go for stateless sessions btw
ParaFWIW I've found Guava's caches really useful in that. Create a cache loader which has the heavy operation inside it and let requests wait/park until result is fetched by the first caller and value result is cached.
ParaAnd definitely do things cache first, adding them as an afterthought is not fun.
ernimrilenoq, how many concurrent users are you planning to have? how long time does each request take? Do you have to care about thread handling?
enoqernimril, I don't have data yet for concurrent users; customer is very performance sensitive and has set ms response time goals
ParaThen remove Hibernate entirely.
enoqtechnically you could ofc also spin up multiple servlet apps
ernimril"ms response time goals"? as in 999 ms or as in 1 ms?
enoqbelow 100 IIRC
ParaYou'll also need proper tracing to detect hotspots, design a multi-layered cache as well. Avoid distributed caches such as memcached, their worst case scenarios/faults will kill you.
ernimrilenoq, on average or worst case?
ParaOr is that 99%?
enoqernimril, great question, I think it's probably an average but would have to look into it
ernimrilthese things matter a lot. if it is average you can do almost anything a 100 ms is a _long_ time for a computer... :-)
ParaOn tracing, you need to be able to prove _your_ part. If the request takes 60ms to come from client to your backend and that is counted as part of it, you definitely want to be able to say that someone else ate your quota... :)
ernimrilnow, if you connect to a database over a filtering tunnel and going through another country you may still have problems (yes, this has happened to me)
enoqright, the thing that sorta gives me headaches is that we potentially have a nextjs server app in front as well
enoqwe're gonna host in the same data center though (Azure) so I hope latencies will be low
ParaI did as an exercise an opentelemetry tracing Spring aspect some time ago, I could share that if you're interested. And I can find it, it's in my pile of experiments :P
enoqsure
enoqthe reason why I'm asking is because I think the need for webflux might go away once we've got structured concurrency in java
jreicherenoq: I'm probably saying something Para has already said a different way, but make sure you solve observability for your performance metrics if that's something you care about. Realistic workloads are difficult to reproduce so if you see something weird happening, that'll probably be your only chance to know why it happened.
ernimrilenoq, with the loose requirements you have today I would probably just go with whatever seems most easy (spring boot if you know and use that already, but perhaps quarkus)
enoqclassic case of premature optimization?
ernimrilmeasure, then fix, but try to plan well so you get good algorithmic complexity
* jbosmans joined #java
* MikeBux joined #java
jreicherMeasuring is really hard for stuff like this, which is why the method of measurement needs to be planned and instrumented.
* hwpplayer1 joined #java
deeboenoq: we use spring boot 3 and 4 exclusively with virtual threads in a microservice architecture where everything is just waiting for io most of the time
enoqI mean yeah, virtual threads work really well
deeboas long as you're on jdk24+ to avoid pinning issues, there's really no need to do rx and get cancer
enoqjust more concernced about parallel requests
enoqalso looking into Kotlin coroutines btw
deebodoes't really matter, we just mostly do CompletableFuture.supplyAsync(() -> api.call(), virtualThreadsExecutor), but on spring @async would work just as fine
deeboone service is graphql which does one root query, then massive amounts of parallel queries to fill the graph
deebowe don't really even do caches, except for apis that were not designed to be used like this and for example return all data at once without any filtering
dreamrealenoq: virtual threads in spring are very good
dreamrealwhat problems are you actually having
enoqdreamreal, I don't want reactive but I want to make use of parallel http requests/db calls
enoqmy impression was that I need to wait for structured concurrency in the jdk first to get that
enoqbut looks like spring has @Async
dreamrealyou don't need any of it
dreamrealjust write ordinary blocking servlets
dreamrealthen turn on virtual threads
dreamreal(requires java 21 or later)
dreamrealYou'll get 95%+ or better of the reactive performance just by doing that, and that remaining percentage affects a remarkably small number of apps
dreamrealand your code complexity will drop like a stone.
dreamrealEasier to debug, easier to reason about, easier to read, easier to do everything.
* sponkz joined #java
enoqright, I just need an escape hatch if I ever need to optimize that use case
dreamrealAre you working for netflix, amazon, anyone like that?
dreamrealIs who you're working for expecting to become netflix, amazon, anyone like that? I mean, I know we all plan for it, but even so
enoqno, they are using Magento and other PHP based software right now and migrate off because of performance issues, so it's an important topic to be able to handle that
enoqor at least have good arguments set aside if it comes up
enoqsoftware architecture itself is a tricky topic to navigate since there's so much dogma floating around
dreamrealwell. Here's more: YAGNI applies. For 99.999% of apps, including every damn one of mine, virtual threads in spring will provide everything you're looking at reactive programming to give you.
enoqcorrect, try to argue that against a competitor who throws performant async style programming requests at you ;D
dreamrealThe thread mentions caching, and maybe caching can help, too, but that's to reduce certain aspects of the process, and I don't know what you're doing, so I can't point at caching and say "yes, you want that too."
enoq+ nodejs
dreamrealenoq: competitor... internally or externally? nodejs' async programming isn't exactly a panacea, plus it's nodejs
enoqexternal; exactly, nodejs is way slower, still need a way to quickly play the bullshit bingo
dreamrealwhat the heck? Get an SLA, meet it. Your external competitor is going to be dust.
dreamrealTurn on virtual threads, boom, you have "industry standard scalability" with commodity programmers.
* Betal joined #java
dreamrealYou don't get to use the kickiest, hippest new apis, I guess, and you're not at the mercy of structured concurrency Feature O' Th' Day, and you don't get to claim to be one of the thousands of projects underusing reactive programming, I suppose, but personally I don't consider those weaknesses, I'd rather get stuff done
enoqfully agree; as mentioned, I just need a back up argument, but @Async looks like it will provide that
dreamrealWhy
dreamrealspring.threads.virtual.enabled=true # provides that with no source change
julemand101enoq: What is your backend doing that would require CPU cycles? In most applications, the slow part is going to be IO and especially database queries so if the same is the case for you, then changing to Java would not really give much benefits.
deeboin my experience you get the most out of it as long as you have http and db connection pooling
enoqjulemand101, I don't except any number crunching; almost everything will be I/O, be it REST calls or db queries
dreamrealenoq: then smart caching of consistent resources is going to be your next lever
dreamrealthis is not rocket surgery, it's barely brain salad
deebowe could run our 5+ country multitenant systems main data service on 1vcpu and 2GB mem since it's mostly io with no actual cpu work
deebobut for high availability we have "excess" capacity that's just idle :) virtual threads are basically magic in these types of services
julemand101enoq: Ok, so it is really the best way to spend your time/money to rewrite your backend into a different language? I mean, it sounds like you don't have a good understanding of where your performance bottlenecks are if you suspect your PHP code when your application are mostly IO bound?
enoqjulemand101, no rewrite happening
julemand101Ah so there are no backend at the moment?
enoqcustomer wants to transition to a cloud provider which the current backend does not support
dreamrealokay, now I'm concerned.
Drixtanenoq: there are 2 ways of handling the blocking IO problem: green threads and the "async" model (which is a stateful machine behind the scene). The "async" model, which has been popularized by C#, is known to "color" your methods with the "async" keyword (see typescript, rust, C#...). This put the code in a situation that you often have to duplicate the code: one async, one sync - where the "function coloring". The second method to manage the blocking IO is li
Drixtanke Java virtual threads or Golang green-threads for example. This approach does not color your code, so it eliminate duplication of code.
dreamrealenoq: ... you need to define scope and roles here
Drixtanenoq: as per webflux vs virtual threads, webflux was created before the virtual threads to manage this IO blocking problem, so enjoy the new pattern and use the virtual threads.
enoqI think we're going off on a huge tangent here based off a misunderstanding
dreamrealenoq: relying on #java for architecture is ... not the worst advice, I guess, in that we CAN know what we're talking about, but it's certainly still terrible advice
dreamrealenoq: yes, agreed.
dreamrealenoq: everything you've said looks TO ME like you have a spring boot app to write, and you want it to scale horizontally as well as vertically, which is pretty easy - and the easiest performance spice in spring is to write simple code with simple services (a traditional architecture) with virtual threads turned on.
dreamrealBUT I have NO insight into the app or the SLA.
dreamrealthat *approach*, plus caching resources that are expensive to retrieve but are generally constant otherwise, catches *a ton* of response time issues. But I don't know the problem space being talked about, so ANY advice has to be taken with a lot of salt and an eye to how much you've paid for it.
dreamrealthe only person with skin in the game here is YOU.
enoqright, I fully agree with that
DrixtanI think the real question was: are you safe going with Java? I think you get the answer: yes you are - performance won't be an issue, you always have a good way to optimize, you are not painting yourself in a corner.
dreamrealenoq: @Async does not help - it creates an analog to a pattern you DO NOT NEED. You can use it, but doing so is mostly doing node-like things in Java, as opposed to java-like things in java. Do java-like things in java.
enoqhow do you handle slow parallel requests to different REST endpoints then?
dreamrealdepends on what "slow" means! Virtual thread dispatch means that each blocking call blocks *only its virtual thread*
dreamreallike, okay, thread-1927 is taking 4ms to run this blocking call, oh no, while thread-1938 executes the same blocking call in ANOTHER thread, where's the competition for scarce resources?
enoqlet's imagine you need up to date data from endpoint a and b and both take 100ms to complete; if you write it naively using virtual threads, you'll end up with 200ms
dreamrealnode and python treat *threads* as scarce resources, so async makes sense
dreamrealenoq: why? Why are they executing sequentially?
enoqthat's my question: what's the recommended way to parallelize this using virtual threads
dreamrealturn on virtual threads.
dreamrealThat's the recommended way to parallelize that.
dreamrealthat's all.
dreamreal... that is, in spring.
ParaYeah, it took over a decade to materialize as a feature because they wanted it to be a turnkey thing.
ParaFlip the switch and move on :)
enoqthe 100ms requests are launched inside spring, not the frontend
dreamrealenoq: right.
dreamrealenoq: dude, I've done this. For a long time.
enoqso just turning on virtual threads will not solve this, you need to fork off threads or similar stuff
dreamrealwhy?
dreamrealWhy do YOU need to fork off threads, if the framework does it for you?
enoqoh, I think I might have misunderstood how they work
Drixtanenoq: spring 3.2+ the request handler is a virtual thread, imagine you have an "infinite" amount of "threads"
dreamrealI mean, with virtual threads turned on in spring, requests a and b will both spin up a thread without you doing anything, and they'll both run parallel; is the "up to date data" the blocking point? Can IT handle only one request at a time?
enoqis it intelligent enough to realize that both method calls have no dependency on each other and can execute in parallel?
dreamrealyes, in fact you have to work to get it to NOT run in parallel
Para...lock pool
dreamrealwe've been TRYING to give you good advice here
enoqI see, I was under the impression that it suspended execution immediately once it hit the first I/O call
dreamrealoh god no
dreamrealthat'd be bonkers mad
ParaI/O is not magical, despite especially functional programming folks wanting to make it seem like it :P
dreamrealthat's why I said that you get most of what you want with the single flag
dreamrealmaybe not all of it: if you're netflix or amazon or a very few others, well, you want to manage concurrency differentl
enoqthank you, that cleared things up massively :)
enoqand tbh makes it even more impressive
ParaI bet someone's been crazy enough to make lmax disruptor to manage tasks in Spring somewhere at some point but...don't :)
dreamrealone of my clients was saying "oh nooo what if we have to arrrgh" and I told them that if we could measure against their SLA and we could saturate within 10% of what the actually expected I'd not only eat my hat but I'd buy the hat to eat it AND we'd go reactive. Didn't happen. At all.
dreamrealPara: that's a bet you'd win, plus EAI is a thing
* ChaiTRex joined #java
deeboseeing one reactive stack trace should put you off the concept entirely
deeboonly annoyance with virtual threads i've run into, is that at least with sampling tracing in yourkit, you don't get proper grouping of samples, due to the way it's actually run on a few platform threads you get weirdly disconnected results
dreamrealand as far as annoyances go, that one's pretty mild.
dreamrealat least, in my experience.
deepyonly annoyance I got with virtual threads is that they worked so well that I forgot my app was running on a slow single vCPU in a constrained environment and then it very unexpectedly crashed under load
jreicherPara: I/O might not be magical, but it doesn't exist within any language.
jreicherThat's not specific to functional programming.
Parajreicher: FP people are insufferable about I/O at times, is my point :)
jreicherI think they're just defensive. They don't want to admit they're bad at explaining their preferred paradigm.
dreamrealor that their holy writ has giant chasms that undercut their magic claims
dreamrealFP is incredibly useful and I wish they wouldn't keep trying to sell people on it
dreamrealjust back up your shit, that's enough
jreicherI believe FP is as good as some people say, but there are other people who make false claims about it
* metalmaniac joined #java
dreamrealFP's great
deeboi'm just a highly paid data plumber (actual plumbers might make more!), the more functional and immutable stuff is the easier :)
cheeserif you're strong enough
dreamrealdeebo: sure, like I said, FP's great
dreamrealit's just not MAGIC
dreamrealmagic's not real, just like unicorns aren't real, wendigos aren't real, birds aren't real
cheeserfinland isn't real
deeboyep, the full paradigm just doesn't work for me, i've used xmonad (haskell based window manager) for like 15 years or something, and i still have no clue how my configuration works, just glad it does
* fgarcia joined #java
jreicherdeebo: what "doesn't work" about the paradigm for you? (I have a vested interested in this question)
Paradeebo: Time to descend another level and start using nixos, then.
ParaI'm self-projecting, I have a used laptop arriving soon which I'll be installing nixos onto.
* hwpplayer1 joined #java
* Anaphaxeton joined #java
* jamezp joined #java
* marcel joined #java
* five618480339176 joined #java
* stfstfm joined #java
* acidsys joined #java
* kathadris joined #java
* jwisbell35 joined #java
deebojreicher: i just can't read it, with haskells custom operators it's even worse
enoqlet's say your app calls a couple of REST APIs that you don't control (but you can add test data); what's your preferred way to test that? spin up a mock rest server? mock the http call? add test data to said REST API?
ParaMock the call, probably.
dreamrealfor THAT, mock the call, although I personally prefer spinning up a fake server that returns predetermined data
enoqany reasons why you wouldn't use test data from the live system?
ParaLegal.
dreamreal^^^
dreamrealyou don't want to rely on the live system
enoqthank you
* Odyss3us joined #java
* henbruas joined #java
sbalmosthe most advanced company I worked at for a year contractually had a mostly-automated weekly system that took a snapshot of prod on Saturday nights overnight and sanitized as much as it could into normative names etc
* hwpplayer1 joined #java
* mindCrime joined #java
* Anaphaxeton joined #java
* ChaiTRex joined #java
* JazzJackalope joined #java
* Anaphaxaway joined #java
* leppard joined #java
* stfstfm joined #java
* monkeyPlus joined #java
* tmm88 joined #java
jreicherdeebo: interesting. Is it any better when do notation is used?