Live data from Hacker News

Java Virtual Threads Preview

openjdk.java.net

251–260 of 270 posts

Re: Java Virtual Threads Preview

#251

There is a spectrum of solutions for dealing with slow I/O in programming languages (well, all I/O is best assumed to be slow I/O). At the two ends of the spectrum are: - continuation-passing style (CPS), hand-coded or compiler - preemptive threading / processes In between lie various solutions, like async/await (closer to CPS), and green threads (closer to preemptive threading). The key difference between the two en…

Maybe? it depends how you use them... any asynchronous operation will require memory, and that memory has to go somewhere. In CPS it goes on the heap... in the threaded style you have a stack you can put it on. This probably will waste some memory, though not as much as you might think. On the other hand, you can also reclaim the stack memory as soon as the operation finishes. The CPS technique creates garbage that a…

In CPS the state of the program is captured in the continuation, which is a closure, which is allocated on the heap, and in any ancillary data structures pointed to by it.

However, there's generally only a very small number of such closures -- typically only one -- and they are generally one-time use only. That means they can be freed as soon as they tail-call out. Hello Rust.

Re: Java Virtual Threads Preview

#252

Earlier quoted context omitted.

This is partially right. But the Java implementation under the hood is still a CPS transformation, so it only allocates the memory that is required for the "virtual stack". Compared to that Go - which has similar semantics - allocates a more classical stack for each goroutine, which can however grow over time. The CPS approach is certainly more space efficient, but but I'm not sure how much of a difference it really…

Normally a POSIX thread gets a very large stack (1MB is typically the default), and obviously these "virtual stacks" will only be as large as they grow (splayed on the heap?). But the memory for those POSIX thread stacks isn't necessarily allocated up front! The OS grows the thread when the thread traps trying to access the guard page, so it's not really a 1MB stack. Now, if you need to serve 1e6 clients with threads…

could you explain difference between CPS and using “Async/Await). I have a C# background but always assumed they where the same thing!

Re: Java Virtual Threads Preview

#254

Earlier quoted context omitted.

> For many types of common webserver workloads (i.e. lots of IO, relatively minor CPU usage), NodeJS can actually scale much better than Java with its thread-per-request model Linux can handle a ginormous amount of threads quite well, would be interesting to see a deeper investigation to this theory.

Java uses some memory for stack, about 1MB for each thread.

This doesn't in practice limit scaling though as it's linear and small in absolute terms vs what you can put in a server.

Re: Java Virtual Threads Preview

#255

Earlier quoted context omitted.

>I doubt anyone would switch to Java Virtual Threads anytime soon, unless via Kotlin. I think you're mistaken. The Java community is just so tremendously larger relative to the Kotlin one, that this will have more users within months. I really liked what Kotlin was doing, but Java since got lambdas, they have closed the biggest gaps that drove migration.

Lambda's seem like one of the least interesting features of kotlin. There's so much more going on in the kotlin world than lambdas. it seems to me that kotlin is leading the way and java is following, but the delta between them is quite large and possibly growing.

Aside from nullable types, I don't see any other feature that Java could borrow from Kotlin today to improve. Java looks up to Scala and Clojure to get ideas, there are some strong functional programming ecosystems that were bred by these languages, like Typelevel, ZIO, actor-systems like Akka, Datalog queries, contract-based systems like spec2, Stateflow testing, matcher-combinators, generally things that Clojure does differently than the evangelical notion that type-systems are the end all be all. The rest of improvements are on the JVM, like primitive objects (value types) and generic specialization.

Re: Java Virtual Threads Preview

#256
post #181

Earlier quoted context omitted.

I'm not disagreeing with what you're saying here — at all. But what I am claiming is that when it comes to interest for and adoption of Kotlin within the JVM community that pull is smaller and shrinking. And that lambdas in Java are a big part of the reason for that.

Kotlin never had any real pull on the behemoth that is Java. It’s an insignificant language (outside android, where java is not the real deal to begin with). If anything, JS and C# and other major high level languages could hurt java, but fortunately it has been developing in a fast pace, implementing whatever is worthy and was experimented by other languages.

And even on Android, many open-source projects decide to use Java as they can have access to a wider pool of programmers (Signal, etc). C# is only decreasing in usage, the runtime is just not there, C# has always been known in the enteprise as the language that skipped leg day. It's impressive how many features they've added in a short amount of time that make sense (though some will say, even a few of the Microsoft devs, that async/await was kind of rushed), but the runtime has only received some attention in the most recent times, lagging behind Java with approximately 10 years of research. JS is just JS, hate it or love it, it is here to stay, no point in arguing about this. Put some makeup on it to make things bearable with TypeScript and that's it.

Re: Java Virtual Threads Preview

#257
post #212

Earlier quoted context omitted.

Lambda's seem like one of the least interesting features of kotlin. There's so much more going on in the kotlin world than lambdas. it seems to me that kotlin is leading the way and java is following, but the delta between them is quite large and possibly growing.

When is Kotlin creating their own VM instead of following Java?

There's no point in creating a new VM, given that you can target almost everything by supporting JVM, CLR, BEAM, V8(JS transpiler) or LLVM/WASM for C-like languages. All you need is an optimized, general purpose IR that will be able to spit bytecode for each one of those and JS in the case of V8. To be fair, I don't think that a language like Kotlin will be able to accomplish this, it is just too complex. I believe that languages with small cores like Clojure with its monumental extension power through macros or Eff or Koka which "let you define advanced control abstractions, like exceptions, async/await, iterators, parsers, ambient state, or probabilistic programs, as a user library in a typed and composable way" such that it will fit runtimes. Like, provide the IR, the building blocks and let ecosystems develop. Some will argue that now you are moving the meaning of polyglot from the programming language to the libary-level, which is true, as seen in the Scala community, the divide between better-Java (Play), a different kind of OOP (Akka) a Haskell-like ecosystem (Typelevel) and an idiomatic Haskell-like ecosystem (ZIO). So you get Java, Erlang and different flavors of Haskell in one language which is Scala :). Many say that Scala is big and messy but in fact the ecosystems spawned by the core of the language made it like that. Scala's spec is smaller than Java's. I would argue that Scala is less complex than Kotlin, but this is highly opinionated.

Re: Java Virtual Threads Preview

#258
post #139

Earlier quoted context omitted.

Green threads by definition cannot use OS stack and must allocate their stack memory on heap. Although this memory can be reused, as it is known from Go to avoid performance bottlenecks at least for Go code is better to allocate the stack as single continues block and copy the stack to a bigger block when thread’s stack reaches the current stack size. But then the whole stack space is pinned to the thread and cannot…

So in Java we know a few things about the stack that are not true for other languages. We know nothing on the stack is a pointer into a Java stack frame, and nothing on the heap points into a Java stack frame. These facts allow us to mount virtual threads onto carrier threads by copying portions of the stack to and from the heap. This is normally less memory than you’d expect because although you might have a pretty…

I like CSP precisely because it requires to color-annotate the code so it is knows what can and what cannot do IO! Surely it decreases flexibility, but makes reasoning about and maintaining the code easier.

Re: Java Virtual Threads Preview

#259
post #139

Earlier quoted context omitted.

Green threads by definition cannot use OS stack and must allocate their stack memory on heap. Although this memory can be reused, as it is known from Go to avoid performance bottlenecks at least for Go code is better to allocate the stack as single continues block and copy the stack to a bigger block when thread’s stack reaches the current stack size. But then the whole stack space is pinned to the thread and cannot…

Threads use stacks. Being 1:1 to OS threads or M:N doesn't change that.

The question is can unused potion of the stack be used for anything else? With native threads the answer is no and so is with Go green threads. Time will tell if Java can pull off the trick of sharing unused space place, but I am sceptical.

Re: Java Virtual Threads Preview

#260

There is a spectrum of solutions for dealing with slow I/O in programming languages (well, all I/O is best assumed to be slow I/O). At the two ends of the spectrum are: - continuation-passing style (CPS), hand-coded or compiler - preemptive threading / processes In between lie various solutions, like async/await (closer to CPS), and green threads (closer to preemptive threading). The key difference between the two en…

> Any solution towards the thread side of the spectrum will yield significantly larger memory footprints than solutions towards the CPS side of the spectrum. The community-at-large decided that hand-tuning garbage collection was too finicky and not worth it, even though it obviously 'costs' memory. I'm frankly at a loss as to why so, so, so many blogposts and tech experts are all-in on the CPS-side of this argument;…

> it seems quite obvious to me that in the vast majority of cases, the considerably simpler* model of (green) threads means you're making the exact same trade-off: Simpler to write and debug code at the cost of needing more memory when running the app you write.

I don't find it's quite that simple.

My experience is that the complexity of CPS tends to scale linearly with use, whereas threads scale exponentially. For small uses threads are easier, but CPS quickly catches up.

CPS forces you to actually declare a dependency tree for your data. Things depend on other things, and that exists in your code. It's very easy for threads to end up a mess, where it's not clear how data is passing through the code, which causes bugs like deadlocks and race conditions.

It's deceptively easy to write code where thread A tries to lock mutexes X and Y, and thread C tries to lock mutexes Y and X, and it deadlocks because neither thread can get both locks.

It would be much harder and more arcane to do that in Javascript or in Python's async. I'm not saying it's impossible, but I don't think I've ever accidentally created a race condition or deadlock in their CPS engines.

TL;DR if your functions are only marked async so you can await something, threading probably is simpler. If you're actually passing promises around, things become much more favorable to CPS.

Post reply on HN