[HN Gopher] Java 21: The Nice, the Meh, and the Momentous
___________________________________________________________________
Java 21: The Nice, the Meh, and the Momentous
Author : pwpwp
Score : 204 points
Date : 2023-09-22 15:02 UTC (7 hours ago)
(HTM) web link (horstmann.com)
(TXT) w3m dump (horstmann.com)
| billfruit wrote:
| Does it add stdint style names for integer types, unsigned
| integer types etc?
| layer8 wrote:
| The size of the integer types are already fixed by the JVM
| specification ( _int_ is always 32 bits, etc.), and there are
| no unsigned integer types in Java except for _char_ (a 16-bit
| unsigned integer type). Furthermore, Java does not support
| alias names for types. Hence it's unclear what your question is
| aiming at.
| szatkus wrote:
| AFAIK Java 8 added a few methods that helps you handle integers
| as if they were unsigned, like `toUnsignedString`. I think it's
| enough for any exotic cases.
| PaulHoule wrote:
| (1) It's a bit of a bad smell (which he points out) that records
| aren't being used much at all in the Java stdlib, I wrote
| something that built out stubs for the 17 and 18 stdlibs and that
| stood out like a sore thumb. I do like using records though.
|
| (2) I've looked at other ways to extend the collections API and
| related things, see
|
| https://github.com/paulhoule/pidove
|
| and I think the sequenced collections could have been done
| better.
|
| (3) Virtual Threads are kinda cool but overrated. Real Threads in
| Java are already one of the wonders of the web and perform really
| well for most applications. The cases where Virtual Threads are
| really a win will be unusual but probably important for somebody.
| It's a good thing it sticks to the threads API as well as it did
| because I know in the next five years I'm going to find some case
| where somebody used Virtual Threads because they thought it was
| cool and I'll have to switch to Real Threads but won't have a
| hard time doing so.
| yankput wrote:
| Virtual threads are strictly better than normal threads, no? I
| am thinking of any reason to still use traditional threads. Is
| there any downside?
| papercrane wrote:
| Currently virtual threads aren't a good match if you have a
| CPU heavy workload. The scheduler isn't fair and if your code
| doesn't enter into any blocking code it won't be unmounted
| from the carrier thread.
| yankput wrote:
| Ahh. It makes sense. But it's much better fit for file
| io/sockets/db.
| papercrane wrote:
| I suspect if we had records from the start they'd be all over
| the stdlib, but because of backwards compatibility they'll
| likely only be considered for new APIs.
| twic wrote:
| I think the biggest impact of virtual threads is that the
| ecosystem will abandon asynchronous APIs. No more futures,
| callbacks, servers where you have to make sure not to block the
| thread, reactive frameworks, etc. Just nice simple imperative
| blocking code. Nima is the first example i've seen:
|
| https://helidon.io/nima
|
| We've had two production bugs in the last two weeks caused by
| handlers blocking the server thread in apps using an async web
| framework, which would simply not have happened with a
| synchronous server.
| jayd16 wrote:
| You'll still have the structured concurrency calls but that's
| much better than pure callback hell.
| zmmmmm wrote:
| I think virtual threads are huge.
|
| The problem with regular threads is (a) multi-kb memory stack
| per thread and (b) consuming a file handle.
|
| Either of those severely limits the scalability of the most
| "natural" parallelism constructs in Java (perhaps generally).
| Whole classes of application can now just be built "naturally"
| where previously there were whole libraries to support it
| (actors, rxJava, etc etc).
|
| It make take a while for people to change their habits, but
| this could be quite pervasive in how it changes programming in
| general in all JVM languages.
| logicchains wrote:
| Does anyone know if Java virtual threads will also have channels
| and a select concept, like in Go?
| aardvark179 wrote:
| I think at some point yes. We certainly discussed it but it's
| one of those things that takes time to really get right and
| performant.
| mrkeen wrote:
| In the code example for virtual threads, I have no idea what will
| happen in parallel.
|
| How do I reason about the order in which the calls change the
| state of the world?
| Jtsummers wrote:
| That's all sequential code, it would be run inside a single
| "virtual thread". Note that the async code on the right is also
| sequential, just structured through an async API.
| Svenskunganka wrote:
| From my perspective they're not entirely equivalent. The
| async variant seems to be batching getImages and saveImages,
| while the sync variant gets and saves each image
| individually, sequentially.
| Jtsummers wrote:
| They aren't perfectly equivalent because the virtual thread
| example uses a loop instead of the following (dropping the
| try/catch): // client.sendAsync(request,
| HttpResponse.BodyHandlers.ofString()) var response =
| client.send(request, HttpResponse.BodyHandlers.ofString());
| // .thenApply(HttpResponse::body) var body =
| response.body(); // .thenApply(this::getImageURLs)
| var urls = getImageURLs(body); //
| .thenCompose(this::getImages) var images =
| getImages(urls); // .thenAccept(this::saveImages)
| saveImages(images);
|
| And if it had been written this way it would have been
| clearer that they are, in fact, equivalent. But generally
| people don't write like this, they use looping constructs.
|
| Regardless, the important bit is that the
| parallel/concurrent bit of the async one is that it is cast
| off into an async system. The following execution steps
| are, well, steps. Each executed in sequence. Just like the
| body of the virtual thread example would be executed, but
| without the cumbersome noise of _thenApply_ and
| _thenCompose_ and such.
| Someone1234 wrote:
| If you're viewing that website on a desktop, I strongly suggest
| removing max-width: 90ch from the body css. Instead of 50% white
| space, it goes full width and makes the table substantially more
| readable (particularly the code samples).
| munk-a wrote:
| Hilariously enough I was initially confused by this comment
| because the webpage rendered so readably for me - the base CSS
| is actually quite reasonable and because I have JS disabled by
| default the page never re-rendered into the thinner mode.
| Someone1234 wrote:
| It may be my specific setup. But on a 1440p display, 125% OS
| scale, I'm seeing more white left/right than actual content
| in the middle. It is also wrapping the code making it
| difficult to read.
|
| Completely readable at 100% width though.
| anonymousDan wrote:
| Can anyone explain this comment: "In the past, a thread pool
| didn't just throttle the incoming requests but also the
| concurrent resources that your app consumed. If you now accept
| many more incoming requests, you may need other ways to manage
| resource consumption."
| yCombLinks wrote:
| Yeah, if your server maxed out at 256 system threads you didn't
| have to worry about the fact that 1024 simultaneous calls would
| crash your DB. But now you're not limited by system threads
| [deleted]
| hinkley wrote:
| What's the Scala community think about this development? I would
| think this would affect them quite a lot.
|
| Google is not helping.
| discodachshund wrote:
| The Typelevel folks on Discord are of the opinion it's not of
| much interest to them
| Vicinity9635 wrote:
| The examples having to word wrap in a tiny text box look even
| more absurd and unreadable when the page is only using 1/3rd of
| the screen.
|
| What is with this awful formatting?
| https://i.imgur.com/nQmt7Qo.png
| marginalia_nu wrote:
| > Miscellaneous new methods -- meh
|
| Dunno, several of these are tangible QoL boosts:
|
| Math.clamp(), List.reversed(), List.addFirst(), List.addLast(),
| Character.isEmoji()
| bcrosby95 wrote:
| > List.reversed(), List.addFirst(), List.addLast()
|
| These fall under sequenced collections, not "miscellaneous new
| methods".
| marginalia_nu wrote:
| I guess? I found them under the API diff linked as
| "miscellaneous new features".
| waynesonfire wrote:
| > Over 10,000 bug fixes
|
| Most of which were likely introduced during new feature
| development in recent releases. To suggest that this on its own
| somehow manifests a more stable jdk compared to some ancient,
| battle tested version of the jdk is debatable.
|
| I find it rather concerning that so many bugs exist to begin
| with. Why are these not caught sooner?
|
| Has the whole world gone crazy? Am I the only one around here who
| gives a shit about quality? Mark it zero!
| specialist wrote:
| Randomly looking at bugs fixed the last 10 weeks, it seems like
| a healthy mix of old and new bugs.
|
| https://bugs.openjdk.org/browse/JDK-8316305?filter=-7&jql=pr...
|
| Being allergic to JIRA, my JIRA-fu is weak, so there's probably
| an easier/faster way to report bugs fixed in v21.
|
| Any way.
|
| > _Am I the only one around here who gives a shit about
| quality?_
|
| Ages ago, I was a QA/Test manager. So I appreciate your
| sentiment. But it seems to me that Oracle's being a _FANTASTIC_
| shepherd of Java. Definitely a huge upgrade, at the very least.
| doodpants wrote:
| You might be the only person in the world who writes bug-free
| code on the first try.
| Vicinity9635 wrote:
| [flagged]
| ecshafer wrote:
| Java getting better pattern matching is a great change. Id really
| like more of the functional features to make it into Java.
|
| I would love if Java pattern matching could at least get to the
| level of ruby pattern matching. Ruby pattern matching will allow
| you to deconstruct arrays and hashes to get pretty complicated
| patterns, which is really powerful. Right now it seems like Java
| might have that with a lambda in the pattern, but its not going
| to be as elegant as ruby where:
|
| case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]}
| in name:, friends: [{name: first_friend}, *] "matched:
| #{first_friend}" else "not matched" end #=> "matched: Jane"
|
| But the big change here is virtual threads which should be a game
| changer.
| unregistereddev wrote:
| Pattern matching is a neat tool to keep in the toolbox. When
| it's the right tool for the job, it is really cool and is a lot
| cleaner than a bunch of conditional checks. However, I rarely
| reach for it. Maybe my use cases are unusual? I am genuinely
| curious how often other developers find pattern matching to be
| the best tool for the job.
| weatherlight wrote:
| In languages that have strong support for pattern matching,
| whether it be on values or types, I find myself reaching for
| it instead of conditionals. It's all about the explicitness
| for me. You have to list out all the cases you care about, so
| there's no room for ambiguity. Plus, the compiler will
| usually warn you if you've missed a case, which is like a
| built-in bug catcher. It's also great for working with
| immutable data, less state to worry about. And let's talk
| about readability; the code basically documents itself
| because you can see the shape of the data right in front of
| you. You can even destructure data on the fly, pulling out
| exactly what you need. If you're using a statically-typed
| language, pattern matching adds an extra layer of type
| safety. And, not to forget, it nudges you toward a more
| functional style of coding, which I find leads to cleaner,
| more modular code. So yeah, I reach for pattern matching
| quite a bit; it often feels like the right tool for the job.
| grumpyprole wrote:
| One example for you: anytime you needed to use the "Visitor
| pattern" to do a transformation from one representation to
| another - you don't need it now. Sealed classes and pattern
| matching will be more succinct and easier to reason about.
| ecshafer wrote:
| I think that you can replace almost any If else with pattern
| matching. Pattern matching makes type checks easier, which if
| you are really heavily using types through your program,
| makes pattern matching even better.
| hibikir wrote:
| Pattern matching is what makes sum types ergonomic enough to
| be used. Many a Java design doesn't use said interface-based
| sum types because it's so cumbersome to use them. But whena
| language has pattern matching, then suddenly designing with
| sum types in mind is done a lot, and therefore you see
| examples of good pattern matching everywhere.
|
| When I teach Scala, a very high percentage of the teaching
| time is ultimately down to re-introducing how to design
| business domains, because seasoned devs just reach for large
| classes with a million optional fields, which not only can
| represent valid systems states, but thousands of invalid
| ones.
| bcrosby95 wrote:
| It probably depends on the language you're using. Pattern
| matching is awesome in Erlang and Elixir. In most other
| languages it ranges from "nice" to "bleh".
| nayuki wrote:
| Pattern matching is awesome in Rust. It carries the stellar
| legacy of Haskell.
| Jtsummers wrote:
| When available, I pretty much always use pattern matching. It
| tends to shorten code while not reducing clarity (often
| increasing it) which means fewer opportunities for errors to
| creep in. Statically typed languages that can detect
| incomplete case handling also reduces the chances for some
| errors (as long as you don't make a catch-all case) but also
| helps when you change something so that a new case is needed.
| It also tends to shift the code to the left, reducing the
| indentation. So shorter, clearer, less unnecessary
| indentation. Generally a positive.
| frou_dh wrote:
| I really like that Ruby throws NoMatchingPatternError if none
| of the patterns match. It's a bit like the much-acclaimed
| exhaustive pattern matching in static languages (though at
| runtime rather than compile-time, obviously) and better than
| just silently falling off the end, which IIRC is what Python's
| pattern matching does.
| rusk wrote:
| In Python you can terminate a for loop with else, which will
| be run whenever the loop runs to the end without breaking
| specialist wrote:
| Neat. Will check it out.
|
| I recently spotted a (new to me) foreach / else construct
| in a templating language (sorry, forget which one); else is
| invoked if the list is empty. Nice sugar for common outputs
| like "no items found".
|
| I appreciate modest syntactic sugar.
|
| For instance, my #1 sugar wish is for Java's foreach is to
| do nothing when the list reference is null. Versus tossing
| a NPE.
|
| Eliminates an unnecessary null check and makes the world a
| little bit more null-safe.
| munificent wrote:
| We recently added pattern matching to Dart [1], so I'm always
| keen to see how it compares to similar features in other
| languages. In case it's interesting, here's that Ruby example
| ported to Dart: print(switch ({'name':
| 'John', 'friends': [{'name': 'Jane'}, {'name': 'Rajesh'}]}) {
| {'friends': [{'name': var firstFriend}, ...]} => "matched:
| $firstFriend", _ => "not matched" });
|
| Pretty similar! The main differences are that Dart doesn't have
| symbols, so the keys are string literals instead. Also,
| variable bindings in patterns are explicit (using "var") here
| to disambiguate them from named constant patterns.
|
| [1]: https://medium.com/dartlang/announcing-dart-3-53f065a10635
| brabel wrote:
| > We recently added pattern matching to Dart [1]
|
| I've been using that and I love it, in general... but can I
| ask you why do we need to name a variable in a pattern like
| this: switch (p) { Person(name:
| var name) => ... }
|
| That's the only thing that feels a bit annoying as you have
| to rename the variable... In Java, this would be something
| like: Person(var name) -> ...
|
| EDIT: I guess it's to support `Person(name: 'literal')`
| matches.
|
| > Dart doesn't have symbols
|
| That's weird, as I actually use sometimes `#sym` (which has
| type `Symbol`)?? print((#sym).runtimeType);
|
| This prints `Symbol` :)
|
| I know you know Dart in and out, but could you explain why
| this is not actually a symbol in the way Ruby symbols are?
| brightball wrote:
| Simple solution: JRuby.
|
| Virtual threads are going to make Ruby fibers work properly for
| JRuby so that's going to be huge as well.
|
| Charles Nutter gave an update in August. 45 minute mark he
| talks about virtual threads.
|
| https://youtu.be/pzm6I4liJlg?si=vKVICrola4OmJIal
| adra wrote:
| Virtual threads are going to be great, but they're still limited
| (still starved the pool when used with 'synchronized' blocks),
| and they aren't the structured concurrency power houses like
| kotlin coroutines, but its an invaluable tool that will only
| continue to accelerate as the ecosystem moves to adopt them.
|
| Expect a lot of libraries to start release versions that are java
| 21 baseline because of this feature alone. We're in for a little
| bit of dependency hell for the short while. Thankfully, devs have
| been exposed to a mostly final loom for a year, so my hope is
| that at least the big projects are well on their way to quick
| adoptions.
|
| Unlike the 8->11 migration which largely brought pain, the 8->21
| release brings with it a ton of value that i think will encourage
| most shops to actually pull the trigger and finally abandon 8.
| skwirl wrote:
| Do you have to baseline on Java 21 if you want to add support
| for virtual threads? Couldn't you continue using heavyweight
| threads on older versions of Java? My understanding is that
| both use the same Thread abstraction.
| adra wrote:
| From an API perpective, you can always use reflection to
| cheat past the option to create virtual threads in pre-21
| (without previews) java bytecode, but you need to do more to
| your code than just flip the switch to support virtual
| threads.
|
| A virtual thread thread pool by definition is unbound. If
| you're binding data to a thread (eg. Thread locals, you now
| have a seemingly unbound list of threads that is now
| effectively a memory leak). I bumped into that one a few
| months ago with Netty that has a per thread cache for some
| things (thankfully you can turn off that cache). It was
| creating a significantly large waste of RAM that slowed down
| the application alone.
|
| The other big one is as I mentioned the synchronized
| limitation. If you assume naively that anything can run in a
| virtual thread without worries, you're opening yourself up to
| deadlocks or at least significantly low performance code if
| you're relying on libraries/code that are synchronized using
| java monitors.
|
| There may be more examples of gotchas, but these two are the
| most notable examples I have right now.
| Quekid5 wrote:
| I believe, e.g. ZIO 2.next is doing something like this,
| dynamically deciding whether running something async or just
| doing the blocking thing depending on the availability of
| VThreads... but of course that's Scala, so YMMV.
|
| Without a way to trampoline computation (or transform code
| appropriately) it's probably impractical to do anything like
| that.
|
| (And of course, still many caveats as the sibling post points
| out.)
| larperdoodle wrote:
| Why haven't places updated already? It's not that much work to
| update. Where I work we always go to the new LTS version as
| soon as it's supported by gradle.
|
| Doesn't cross anyone's mind to _not_ upgrade.
| yCombLinks wrote:
| The services I work on pump the entire business revenue from
| start to finish. A few nice to haves for devs aren't any
| where close in the risk calculation if something breaks
| Brystephor wrote:
| 1) dependencies need to be upgraded. for example, not all
| versions of Gradle support all Java versions. So you need to
| upgrade Gradle to upgrade Java.
|
| 2) other things are deemed to have higher priority.
|
| 3) people are satisfied with existing features and don't want
| to spend energy to upgrade to something that doesn't provide
| immediate value.
|
| 4) folks aren't educated on what the benefit of switching
| would be so why would it be prioritized? This is a case of
| "they don't know what they don't know".
|
| I work on a team using Java 8 daily. It's fine. It's got
| things I wish it didn't (no null in switch statements for
| example) but I don't care about that so much that I'm going
| to go through the pain of upgrading 7-9 services in the mono
| repo, their dependencies, and then test them all to be on a
| new version of Java.
| krzyk wrote:
| Gradle/groovy is a liability for any jdk upgrades
| (similarly like lombok, but it usually supports new JDK at
| release, not before).
|
| We ditched spock because of groovy, and never looked back.
| Now at jdk 21, previously at 20.
| brabel wrote:
| That's pretty disingenuous. Groovy has always run on
| newer JDK versions before they even get released.
|
| One year ago, Gpars already supported Virtual Threads:
| https://groovy.apache.org/blog/gpars-meets-virtual-
| threads
|
| As a heavy user of Groovy/Spock, though, I agree that
| upgrading Groovy itself can be challenging,
| unfortunately. Really depends though on how many edgy
| Groovy features you relied on :).
| krzyk wrote:
| Not always for sure. We started JDK upgrades with 9 and
| went +1 every half year and Groovy was lacking with one
| of 10, 11, 12 or 13. It got so tiring that we had to let
| it go. Fortunately our tests were mostly JUnit 5, so it
| wasn't much of work.
|
| We only used it for Spock AFAIR.
| defatigable wrote:
| This is a niche case, but I spent months trying to upgrade
| one of our services from one LTS version to the next (I
| forget which). We encountered a weird bug where services
| running on the latest JRE would mysteriously corrupt fields
| when deserializing thrift messages, but only after running
| for a little while.
|
| After an enormously unpleasant debugging cycle, we realized
| that the JIT compiler was incorrectly eliminating a call to
| System::arrayCopy, which meant that some fields were left
| uninitialized. But _only_ when JIT compiled, non-optimized
| code ran fine.
|
| This left us with three possible upgrade paths:
|
| * Upgrade thrift to a newer version and hope that JIT
| compilation works well on it. But this is a nightmare since
| A) thrift is no longer supported, and B) new versions of
| thrift are not backwards compatible so you have to bump a lot
| of dependent libraries and update code for a bunch of API
| changes (in a LARGE number of services in our monorepo...).
| With no guarantee that the new version would fix the problem.
|
| * File a bug report and wait for a minor version fix to
| address the issue.
|
| * Skip this LTS release and hope the JIT bug is fixed in the
| next one.
|
| * Disable JIT compilation for the offending functions and
| hope the performance hit is negligible.
|
| I ultimately left the company before the fix was made, but I
| think we were leaning towards the last option (hopefully
| filing a bug report, too...).
|
| There's no way this is the _normal_ reason companies don 't
| bump JRE versions as soon as they come out, but it's happened
| at least once. :-)
|
| In general there's probably some decent (if misguided) bias
| towards "things are working fine on the current version, why
| risk some unexpected issues if we upgrade?"
| dihrbtk wrote:
| did you work for a very large rideshare company by any
| chance?
| jfengel wrote:
| The bigger the project, the more painful the upgrade. Package
| systems are convenient to avoid reinventing the wheel, until
| you have to upgrade any piece of it. Then you're stuck trying
| to figure out which versions of each package go together.
|
| If Package A won't run on JDK 17 your entire project is stuck
| on JDK 11. If Package B is upgraded but has conflicts with
| Package A, you have to dig through old versions until you
| find one that works -- and you don't get upgrades.
|
| The more games somebody has played with reflection,
| undocumented features, deprecations, etc. the more likely you
| are to have a conflict. And since package managers encourage
| you to depend on somebody else's code, you end up depending
| on _everybody_ else 's code.
|
| The smaller and greener the project is the more likely it is
| you can just pull the latest versions and be happy about it.
| A project that was written when Java 8 was current, and
| continued to develop, is going to be a nightmare.
| Macha wrote:
| "Oh look, I need to upgrade mockito and Spring. Oh, now I
| upgraded Spring I need to update the spring JPA plugin. Oh
| now I upgraded that I need to upgrade Hibernate. Oh now I
| need to upgrade the library built on it that that team over
| there maintains. Oh, they're not interested." etc. etc.
| [deleted]
| krzyk wrote:
| You forgot about 8->17 which ads really nice language features,
| records alone are greatest feature after lambdas.
|
| And 21 brings patterns in switch and records.
| brabel wrote:
| > Expect a lot of libraries to start release versions that are
| java 21 baseline because of this feature alone.
|
| Java has had multi-version jars since 11 I think... that allows
| library authors to ship code that benefits from new features in
| newer versions of the JDK while still supporting older ones as
| well. Hopefully library authors can leverage that, though I'm
| aware something like Virtual Threads may be very difficult to
| design around for older versions.
| tantamounta wrote:
| With the API being nearly the same, I keep just thinking that
| Virtual Threads are basically identical to Platform Threads
| except that they use far less memory (so you can have lots more
| of them).
|
| Are there any other actual differences? Better Peformance?
| noelwelsh wrote:
| The context switch time is much smaller, so yes, better
| performance.
| pron wrote:
| The relationship between throughput, latency, and concurrency
| in servers is expressed via Little's theorem. If your server
| is written in the thread-per-request style -- the only style
| for which the platform offers built-in language, VM, and
| tooling support -- then the most important factor affecting
| maximum throughput is the _number_ of threads you can have
| (until, of course, the hardware is fully utilised). Being
| able to support many threads _is_ the most effective
| improvement to server throughput you can offer.
|
| See: Why User-Mode Threads Are Good for Performance
| https://youtu.be/07V08SB1l8c
| Svenskunganka wrote:
| I watched the video and thoroughly enjoyed it, thank you
| for sharing it! I have a question that is perhaps not
| entirely related to the video, but it touches the topic of
| context switches. I've read this post [1] by Chris Hegarty,
| which explains that when calling the traditionally blocking
| network I/O APIs in the Java stdlib from a virtual thread,
| it uses asynchronous/poll-based kernel syscalls (IOCP,
| kqueue, epoll on Windows, Mac and Linux respectively) which
| I assume is to avoid blocking the carrier threads. That
| post was written in 2021, does it still hold true today in
| Java 21?
|
| Reading that, it also makes me wonder what happens for disk
| I/O? Many other runtimes, both "green thread" ones like
| Golang and asynchronous like libuv/tokio, use a blocking
| thread pool (static or elastic) to offload these kernel
| syscalls to because, from what I've read, those syscalls
| are not easily made non-blocking like e.g epoll is. Does
| Java Virtual Threads do the same, or does disk I/O block
| the carrier threads? For curiosity, does Java file APIs use
| io_uring on Linux if it is available? It is a fairly
| recently added kernel API for achieving truly non-blocking
| I/O, including disk I/O. It doesn't seem to bring much over
| epoll in terms of performance, but has been a boon for disk
| I/O and in general can reduce context switches with the
| kernel by reducing the amount of syscalls needed.
|
| [1]: https://inside.java/2021/05/10/networking-io-with-
| virtual-th...
| tantamounta wrote:
| Thanks for the video. I feel like there's a bit of
| conflation between the terms "performance(latency)" and
| "throughput", but I see the point. I'd be interested to see
| that latency graph (Time marker 15:38) between platform and
| virtual threads in the case where the server doesn't
| manufacture a 100ms delay (say, in the case of a caching
| reverse-proxy).
|
| Also - millions of Java programmers thank you for not going
| to async/await. What an evil source-code virus (among other
| things that is).
|
| I tried to watch it at 1.25x speed as I normally do, but
| you already talk at 1.25x speed, so no need !
| pron wrote:
| To understand what happens when the server doesn't
| perform IO, apply Little's formula to the CPU only.
| Clearly, the maximum concurrency would be equal to the
| number of cores, which means that in that situation there
| would be no benefit to more threads than cores. What you
| would see in the graph would be that the server fails
| once L is equal to the number of cores. The average ratio
| between IO and CPU time as portions of the average
| duration would give you an upper limit on how much more
| throughput you gain by having more threads. That's what I
| explain at 11:34.
|
| Also, both throughput and latency are performance
| metrics.
| pron wrote:
| Structured concurrency in JDK 21 is not only a powerful and
| flexible library feature, but one that is built deep into the
| runtime in a way that allows observability into the
| relationships among threads: https://openjdk.org/jeps/453
| logicchains wrote:
| Do you know if clojure will be adopting these virtual
| threads, or still using the macro-based approach?
| [deleted]
| cogman10 wrote:
| It's somewhat unfortunate that structured concurrency ended
| up being a preview feature in 21. I agree that it's a great
| addition but man it'd be nice if it made the LTS.
|
| As it stands, probably won't be heavily used until Java 25.
| [deleted]
| Quekid5 wrote:
| Congrats to you and the team on this huge milestone!
|
| Really looking forward to taking advantage of these things
| (transparently and automatically!) in ZIO/Scala... which I
| think shows the true power of the JVM-as-platform approach
| you're taking!
| baq wrote:
| > "Hello, World!".splitWithDelimiters > ("\\pP\\s\*",
| -1) > // ["Hello", ", ", "World", "!", ""]
|
| > Meh
|
| My brain just melted.
| hinkley wrote:
| I'd have a lot of uses for that. But also worry about it
| enabling more stringly-typed code.
___________________________________________________________________
(page generated 2023-09-22 23:01 UTC)