Live data from Hacker News

Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

erlang-solutions.com

91–100 of 114 posts

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#91

the author leaves out Kotlin which adds support for coroutines on the language level and still compiles to java bytecode. These are not classic continuations because they cannot be cancelled, but they're still very useful and true fibers. There's also the Quasar library that adds fiber support to existing Java projects, but its mostly unmaintained since the maintainers were pulled in to work on Project Loom. Then the…

> This will invalidate the arguments for Erlang concurrency model. What about failure domains? As far as I'm concerned, this is the strongest reason for actor-based concurrency. I can design my architecture so that groups of processes that need to die together die together. And it's usually one or two lines of code, if any. Here's a real life example. I have a process that maintains an SSH connection to a host machin…

A current discussion on the Loom mailing list is about providing Structured Concurrency [1] primitives.

It would allow you to write something like:

    try (var scope = FiberScope.open(Option.PROPAGATE_CANCEL)) {
        var fiber1 = scope.schedule(() -> sshKeepAlive());
        var fiber2 = scope.schedule(() -> trackHost());
        var fiber3 = scope.schedule(() -> trackVMs());
    }
With the garantee that if any fiber fails (which you bind to cancelling it), all others will be cancelled.

[1] http://250bpm.com/blog:71

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#92
post #71

Earlier quoted context omitted.

Fair point - all this is true. As a counter-point, I've been working on a platform for the last few years which uses Kotlin and Quasar in production. Quasar was cool at first but now it's just a nightmare and I wish we never opted to use it. It leaks abstractions all over the place with @Suspendable annotations and users of the platform find the quasar related errors super confusing. Debugging is also very difficult…

I have actually heard the same about Quasar so I have avoided using it. It hacks up the bytecode so evil bugs appear common based on my glances at issue tracker. Why didn't you use Kotlin coroutines? My understanding is that they achieve the same as Quasar without the insanity. You may also want to look at Vert.X. Its evolved into a lot more than a REST framework. It uses thread-per-core and nonblocking to achieve hi…

Sounds like you made the right decision! When we started the project four years ago, coroutines were still quite experimental so wasn't a feasible option for us. If I were to consider all the trade-offs, moving to coroutines not something we should do now as I believe it would yield only marginal benefits but would break compatibility for customers.

One of the main problems with the Quasar/coroutine based model is that the semantics are quite hard to undersand for developers who are not very familiar with concurrency. They write code that _looks_ synchronous but is actually async. We get a lot of support tickets claiming there's a bug in the platform when the reality is that they don't understand what's going on. I sympathise with them and we probably need to do a better job of hiding the complexities. As you note, the bytecode instrumentation is a bit of a pain but not only that... It also has quite a big impact on performance!

There has been talk of doing some experiments with Akka and that's something I'm interested in exploring. But I think, hypothetically, that writing parts of the platform again in Erlang/OTP would yield huge productivity benefits... gen_fsm offers exactly what we need out of the box. From the little playing around I've done with Erlang, it feels like you can get a small, competent team, up to speed fairly quickly.

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#93
post #71

Earlier quoted context omitted.

Fair point - all this is true. As a counter-point, I've been working on a platform for the last few years which uses Kotlin and Quasar in production. Quasar was cool at first but now it's just a nightmare and I wish we never opted to use it. It leaks abstractions all over the place with @Suspendable annotations and users of the platform find the quasar related errors super confusing. Debugging is also very difficult…

I have actually heard the same about Quasar so I have avoided using it. It hacks up the bytecode so evil bugs appear common based on my glances at issue tracker. Why didn't you use Kotlin coroutines? My understanding is that they achieve the same as Quasar without the insanity. You may also want to look at Vert.X. Its evolved into a lot more than a REST framework. It uses thread-per-core and nonblocking to achieve hi…

You may also look at Kotlin coroutines in VertX, that we are using and seem to work just fine.

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#94
post #23

Earlier quoted context omitted.

> When is concurrency in Java ever hard? Potentially-racey stuff: * Synchronized primitives don't compose. You can safely `synchronized get(...)` and safely `synchronized put(...)`. But their composition put(get(...)+1) isn't synchronized. And it's hard to mentally revisit it at the end of the day: if you have a class with some methods marked synchronized, nothing will tell whether you've synchronized the right metho…

Java has a large set of higher level abstractions for concurrency. You don't have to use low level locks but you can. (And that's just Java, there's also Scala, clojure ...)

As written here: https://github.com/l3nz/SlicedBread - "the over 400 rich pages of "Java concurrency in practice" show how hard it is to write and debug a good-mannered multithreaded application in standard Java."

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#95

Earlier quoted context omitted.

I started to write a response but remembered rich hickey talk I went to where he lays out problems with java style concurrency Clojure Concurrency - Rich Hickey https://www.youtube.com/watch?v=dGVqrGmwOAw Even though the talk is called clojure concurrency, first half of the talk is about the problems clojure solving in traditional concurrency. one my favorite talks I ever went to.

What are his thoughts on Erlang? (I have not finished the talk video yet.)

That it contains many good ideas but the lack of shared memory and the poor sequential performance leave a lot to be desired.

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#96
post #86
post #80

Earlier quoted context omitted.

What do you mean the cancel method doesn't cancel ? It does cancel with a CancellationException stored in the future and an optional interrupt send to the thread running the blocking operation.

> What do you mean the cancel method doesn't cancel? Try it. @Test public void cannotCancelARunningFuture() { // Future that just sleeps CompletableFuture sleeping = CompletableFuture.supplyAsync(() -> { int i = 0; while (true) { System.out.println("zzzz: " + i++); threadSleep(300); } }); // Make sure it started threadSleep(1000); sleeping.cancel(true); System.out.println("Sleep was cancelled"); threadSleep(1000); Sy…

[deleted]

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#97
post #87
post #80

Earlier quoted context omitted.

What do you mean the cancel method doesn't cancel ? It does cancel with a CancellationException stored in the future and an optional interrupt send to the thread running the blocking operation.

> optional interrupt send to the thread running the blocking operation I'm not 100% sure on what you mean by an optional interrupt, but I'm guessing it's the boolean flag on the cancel(); Let's look! public boolean cancel(boolean mayInterruptIfRunning) { boolean cancelled = this.result == null && this.internalComplete(new CompletableFuture.AltResult(new CancellationException())); this.postComplete(); return cancelled…

You are right. Even the javadoc says that `CompletableFuture` doesn't support this. Bah! will force me read the fine print next time.

mayInterruptIfRunning - this value has no effect in this implementation because interrupts are not used to control processing.

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#98

the author leaves out Kotlin which adds support for coroutines on the language level and still compiles to java bytecode. These are not classic continuations because they cannot be cancelled, but they're still very useful and true fibers. There's also the Quasar library that adds fiber support to existing Java projects, but its mostly unmaintained since the maintainers were pulled in to work on Project Loom. Then the…

> This will invalidate the arguments for Erlang concurrency model. What about failure domains? As far as I'm concerned, this is the strongest reason for actor-based concurrency. I can design my architecture so that groups of processes that need to die together die together. And it's usually one or two lines of code, if any. Here's a real life example. I have a process that maintains an SSH connection to a host machin…

That's what exceptions are for, no? If a connection dies an exception is thrown that would propagate up to the top of the thread stack. You'd then catch it and sit in a loop re-establishing the SSH connection, or terminating with a signal to whatever thread started the monitoring thread that it was dying. The act of unwinding the stack would pass through the finally handlers, closing open resources and cleaning up, before the loop starts again.

The failure domain here isn't precisely defined because shared data is allowed (but not required). You could define it as "anything reachable from the thread/fiber stack".

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#99
post #11

The JVM supports hot code loading, although this article seems to imply only BEAM supports it.

The article mentions "The JVM allows you to change the code while the program is running." However, that's not quite the same thing. The JVM allows you to change instructions, but not -data-. That is, in between versions you change what data a class contains, there is no way to change it out from the running instance. The JVM either has one version of the bytecode loaded, or the other; it has no concept of transition…

You can do that on the JVM too, just use separate classloaders and let the new objects reflect over the old to transition data across. It's not widely done though, for sure.

Re: Optimising for Concurrency: Comparing the BEAM and JVM virtual machines

#100
post #75

Earlier quoted context omitted.

So I describe the shortcomings of CompletableFutures, and you point out that there's a java.util.concurrent package? Is this method one of its gems? A cancel() which doesn't cancel? https://docs.oracle.com/javase/8/docs/api/java/util/concurre... > Synchronized primitives don't compose. You can safely `synchronized get(...)` and safely `synchronized put(...)`. But their composition put(get(...)+1) isn't synchronized.…

Java does not allow one thread to kill another due to its shared memory concurrency model. It actually used to, but this feature was removed because it caused so many deadlocks. The reason is that killing threads won't always release monitors and locks. Lack of the feature is intentional. You can get a lot better nonblocking support with third party libraries. Like RxJS in javascript, RxJava is almost a requirement w…

> Java does not allow one thread to kill another due to its shared memory concurrency model. The reason is that killing threads won't always release monitors and locks.

I can't follow the reasoning here. To refute it, you'd only need to show a language with shared memory and futures with cancel(), right? Aside from that, a second shortcoming isn't a good excuse for the first.

> You can get a lot better nonblocking support with third party libraries.

I don't doubt this. Another example is vavr.io, which gives much better Lists/Optionals/Streams than the standard Java 8 ones. And Joda-Time before that.

> RxJava is almost a requirement when doing non-blocking code.

Why can't CompletableFutures do what RxJava did?

> it relies on OS threads which aren't safe to cancel. Userspace threads don't have that problem

This bit was the most confusing to me. In my shitty understanding of the model, Java Threads are based on OS threads, which is why they're relatively heavy. CFs on the other hand are are lighter and managed by the Java runtime. Why is it then that I can cancel Threads, but I cannot cancel CFs. Your explanation would seem to justify the opposite.

Post reply on HN