Not really. Working on a 2+ year, large, monolithic phoenix liveview app at Spotify. VS Code runs dialyzer on file save, which shows type mismatches. I also run dialyzer on pre-commit for a sweeping check. Ideally, we'd have the same optional typing flexibility with a compile time check, but it seems like a marginal gain over the current setup.
Yes I was using them. But its just the repo and the documentation is quite lacking compared to the other languages. Like with most things it I referred to is workable but has just quite a bit more friction.
I have https://elixirdaily.link (an elixir/beam news aggregator running) on the smallest, free Gigalixir VM just fine. Does a ton of memory intensive work and doesn't go OOM (had to be careful with # outbound http connections).
1.5 years in and Phoenix Liveview is perfect for internal webapps. Have personally seen development take half as much time with half as much people compared to traditional stacks. You don't need super rich interactions nor offline mode for internal apps, plus they might be harder to prio against customer-facing feature work. Elixir and LiveView are really powerful tools to have in your toolbelt. Even if you can't use Elixir, look at Hotwire or Livewire for a similar programming model. You won't get zero-setup fault tolerant components (nested LiveViews can crash and not take the entire page with it, and retry side effects automatically), but you'll still cut out the JS side of the development.
And we haven't even spoken about an app-aware repl that lets you manipulate/inspect your running app (even in prod). There are so many game-changing layers in this stack. It's hard to beat once you've explored it.
For completeness, you should check out Elixir and Phoenix (channels and presence) for the server. Easy websockets, isolated player processes, non-blocking VM, plus deep introspection for debugging issues. https://youtu.be/JvBT4XBdoUE. We see more and more indie games being built with Phoenix LiveView.
I find building a simple game (like tictactoe) in Phoenix Liveview to be a good learning project. You can layer on multiplayer using Phoenix pubsub once you have a working one player version. You can also then layer on structs, typespecs, or any other idiomatic features of the language that you need practice in.
In my opinion, Java as a web language is good when you don't need to really understand what's happening (like in low-traffic situations). If concurrency isn't an issue, then the massive amount of libraries can help you a lot.
In high-traffic environments, that ignorance punishes you. I've always felt Java and the JVM are of the mindset that you need a Ph.D. to even understand how it works or how to configure it, and if you can't get it, then you're just a bad programmer.
You need to know if you're blocking threads, if there's memory contention, and if libraries you pull in are using the forkjoin common pool (which you're likely using as a default threadpool). And when something blows up, finding the reason (even for any of the above issues) is really tough. You can use flight recorder, heap dumps and gc logs all day, but good luck navigating it all unless you're a genius. I've seen too many devs end up shrugging and hoping the issues are transient.
Even figuring out proper threadpool usage isn't straightforward. Look at the number of concurrency abstractions just to model concurrency in your system: https://www.youtube.com/watch?v=yhguOt863nw. It's ridiculous.
Lots of large tech companies "seem" to "make it work." But if my experience is at all similar, they're just relying on a handful of Ph.D.'s to hold the hands of the rest of the company when it comes to troubleshooting.
Part of the reason I fell in love with Elixir/Erlang and the BEAM is that it provides a simple (actor) concurrency model (with a single concurrency primitive, a process) and guardrails (time-slice scheduling) to prevent libraries from shooting you in the foot. OTP's observer makes finding bottlenecks a breeze.
For the web, taming concurrency feels way more important than any cpu-crunching perf gains the JVM can give you. I'm too stupid for the JVM; I'll stick to tools that take away numerous categories of complexity and get me closer to mastering my system.
>In my opinion, Java as a web language is good when you don't need to really understand what's happening (like in low-traffic situations)
Huh? Java is used in huge traffic backends, including HFT with minimal latencies acceptable all the way to Google and Twitter scale.
If anything, Java is much more fast and low level than the typical languages used for huge high-traffic services -- Rails, Python, etc - never mind about what's used in "low-traffic situations".
OP isn't comparing it to Rails, Python, etc. He's comparing it to Erlang.
ANd, to that, I'd agree. I've built high traffic stuff in Java. We built it, load tested it, it was terrible. After multiple rounds of profiling, tweaking GC settings, tweaking threadpool sizes, rewriting things to be async, finding out that a client library wasn't reusing connections properly, etc, we finally had acceptable performance...that still was less than I'd gotten out of the box in similar, IO bound services, written as unoptimized Erlang.
> You need to know if you're blocking threads, if there's memory contention, and if libraries you pull in are using the forkjoin common pool (which you're likely using as a default threadpool). And when something blows up, finding the reason (even for any of the above issues) is really tough. You can use flight recorder, heap dumps and gc logs all day, but good luck navigating it all unless you're a genius.
I've seen the same troubles with alternatives, just without the amazing tools, featuresome standard library or widely-accepted conventions.
Erlang is amazing and is places concurrency in a more central position. I'm hopeful Project Loom will greatly diminish the gap while carrying legacy code forward unchanged.
In defence of Java, I read somewhere it's 25 years old ;-)
Part of the reason for its success has been its strong commitment to backward compatibility, so it's to be expected that it might accumulate many ways of doing things. Python wisdom tells us this is often a Bad Thing. [0]
I imagine Java's approach to concurrency and parallelism might be quite different if it were designed today.
I imagine Java's approach to concurrency and parallelism might be quite different if it were designed today.
Probably not, actually. Project Loom's initial goal was to rethink concurrency on the JVM from scratch. What they came up with was:
* Make threads really, really cheap
* Make thread locals work better (as scoped locals)
* Add a few Executor utilities to help you control sub-tasks better (structured concurrency)
It turns out that Java concurrency is pretty damn good already. It provides all the different paradigms you might want to explore, is efficient and well specified. Meanwhile they realised that many of the alternative approaches to concurrency are in reality trying to work around the high cost of kernel threads. When you make threads really cheap, a lot of the motivation for other approaches falls away and the existing set of tools in the JDK come to the fore.
Your characterization of Loom is, I think, pretty accurate.
There are, however, a few things in Java's early concurrency support that make various things harder, including Loom, and we're having to put some extra effort into grappling with them.
Probably the most obvious is the fact that the language and VM requires every object to have a monitor lock that can be synchronized and waited/notified. In 1996 this was viewed as "Ooooh, sophisticated, building locking and concurrency support into the platform!" In recent years this has started to get in the way. Really only a very few objects are used as locks, but the _potential_ for every object to be locked is paid by the JVM.
It also intrudes on Project Valhalla, which is trying to define "identity-less" inline types (formerly, "value types"). Ideally, we'd want all conventional objects and inline objects to be descendants of java.lang.Object. But Object has the locking APIs defined on it, and locking is intertwined with object identity. So, does Object have identity or not? There are some solutions, but they're kind of weird and special-cased.
Another issue is that the locks defined by the language/VM ("synchronized") are implemented differently from locks implemented by the library (in java.util.concurrent.locks). Loom supports virtual threads taking library-based locks, in that when a virtual thread blocks on a lock it will be dismounted from the real thread. This can't be done with language/VM locks, so there's an effort underway to migrate the those locks to delegate to library code for their implementation. This isn't an insurmountable problem, but it's yet more work to be done, and it's a consequence of some of the original designs of Java 1.0's concurrency model.
That's true but if Java had been designed with a "synchronizable" keyword applied to classes, I wouldn't consider that a radically different language. The prevalence of unnecessarily lockable things is unfortunate from a JVM implementors perspective, slightly convenient from a user's perspective, but ultimately not a defining feature of the language or platform even if it may have seemed important in 1995.
When I think about Java concurrency today I tend to think of java.util.concurrent or the JMM. Perhaps that's odd.
Isn't Android mostly based on Java 7 (for instance, the Guava artifact you need for Android is the Java 7 one)? It can't be the reason why Java 8 is popular.
I believe that the reason why Java 8 is so popular is because there were a lot of backward compatibility problems with Java 9, compounded by the fact that Java 11 (the next LTS after Java 8; both Java 9 and Java 10 had very a very short life) removed many APIs deprecated by Java 9.
Yeah, Android Java has turned into Google's own version of J++.
Worse is that Kotlin fanboys don't get it, that without access to modern Java their Java FFI is worthless, as all Java 8+ libraries on Maven Central will slowly become useless on Android no matter what.
Additionally the language cannot expose JVM capabilities, unless they had even another backend.
So it will be stuff like value types, JNI replacement, proper generics, customized JIT and SIMD on the JVM, and plain old Java 8 on ART.
What does Maven Central have to do with the development of Java by Oracle?
That is precisely my point.
Android has completely unshackled itself from Java development. Between its reliance on Open JDK and Kotlin, it literally has zero dependencies on Java.
25 years of libraries to choose from slowly not available on Android.
If the Android team plans to rewrite all of them in Kotlin, be my guest.
Maybe they will manage before Fuchsia goes live and Flutter wipes the floor, and then everyone will be doing Dart anyway.
Have you noticed how shitty are all the languages designed at Google?
Thankfully someone that was there since Java 1.0 days bought its rights.
GraalVM would have been killed at birth.
I am also looking forward to the complete Android development environment to be running on top of Kotlin/Native, otherwise it will be so funny having to port Studio and everything else that depends on the JVM to modern versions, while Android itself is frozen into a Kotlin ecosystem + Java 8 subset.
> 25 years of libraries to choose from slowly not available on Android.
> If the Android team plans to rewrite all of them in Kotlin, be my guest.
What are you talking about?
Android developers can use Maven Central like any other Java developers without care about what JDK these dependencies were compiled with nor even whether they were written in Kotlin (most did not, obviously).
> I am also looking forward to the complete Android development environment to be running on top of Kotlin/Native, otherwise it will be so funny having to port Studio and everything else that depends on the JVM to modern versions, while Android itself is frozen into a Kotlin ecosystem + Java 8 subset.
Again, what are you talking about? Android development happily upgrades to the latest version of Kotlin without any trouble. Porting Studio? What? Do you even understand anything about any of these matters?
My point is simply that Android development today has zero dependencies on Java but you seem to have a thick chip on your shoulder and determined to spew toxic bile at Java and its ecosystem, while feeling some vague hate at Google in general.
I have zero interest in this debate, have fun tilting at these windmills.
They definitely can not use them, when they they make use of JVM features or JDK libraries delivered post Java 8.
Stating otherwise just proves that you don't know Java.
Android Studio and the complete Android toolchain runs on top of a JVM implementation, as the JVM moves forward, JetBrains will be forced to update InteliJ to take advantage of newer JVM versions, which will force Google to update all their Android development environment.
Just for kicks they are already being forced to do this,
Again, another proof of total lack of knowledge regarding Android
Toxic bille at Java?!?
Quite the contrary, I love Java since 1996 that is my third pillar alongside .NET and C++, what I completely hate is that Google played a Microsoft move with their flavor of Android Java (aka Google's J++), helped Sun going bankrupt withering them the revenue stream from Java deployments on Android, didn't bother to rescue Sun hoping that it would close doors without a hiss, now with its Android Java forces Java developers to create special versions of their libraries tailored to Android, and has a bunch of Silicon Valley fanboys supporting their damaging actions to the Java eco-system.
More like shitty Java. I'm glad Java is being relegated to a second class language that is not recommended for Android development. Kotlin is the now the recommended language for Android development. I give Google 2-3 years before they deprecate Java from Android.
That's not really fair. The point of the Erlang language was its novel and opinionated approach to concurrency. Java wasn't trying to be like Erlang, it was trying to lure programmers by having significant similarities to C/C++.
There are a lot of points which I simply cannot agree with. 1) concurrency as an issue - you make it sound as if doing concurrent programming in Java is hard. Its not if you read through the documentation. In todays world of spinning up small servers, when done right, it scales to massive levels. 2) Blocking threads, memory contention etc. - i think you may be comparing against the likes of single thread programming models like Vert.x or Node.js etc. The flip side which in my opinion is more severe is that if you get even a small thing wrong on the other side, it blows up even more which is more difficult to isolate and debug. Plus the need to learn a whole new programming paradigm which is not easy to wrap your head around. 3) Lot of tech companies seem to make it work - while I agree that corporates will pretty much make everything seem to work, it requires a few engineers who understand software design principles to create design and abstractions that work well. You imply that only PhDs understand that kind of stuff whereas I am sayin that there are many other who understand and who are genuinely making things work in the Java world. I can tell you, when concurrency done right in Java, it is so performance that many will simply not believe. Just my thoughts and happy to differ.
I believe there are few runtimes out there that have such a good monitoring and profiling tools for free and out of the box as Java. Java Flight Recorder, remote debugging and monitoring can be really useful for rare production performance issues.
It's funny you should mention that in response to a post talking about Erlang. :P Because, yes, there are few. The BEAM happens to be one that definitely beats the JVM on that front.
So monitoring and profiling are pretty similar in what sort of things they tell you, but the meaningfulness tends to feel higher due to the programming model. Here's a fairly recent blog post giving an example from someone trying the BEAM for the first time, coming from the JVM - https://medium.com/@mrjoelkemp/jvm-struggles-and-the-beam-4d...
But when it comes to remote debugging, and more specifically, a general "I want to understand what is happening in production", the ability to attach a REPL, alongside your tools, is amazing. I can insert a breakpoint, sure (if I for some reason built my production instance with debug info), but just as easily (without any debug info compiled in!), and more usefully, I can query actor state, mailboxes, etc, fire a message to a process to see what happens, etc...all the things you'd get with a REPL running locally in your dev environment, basically. Do stuff like query for internal state for a process, then call a function with it to see what happens to the data, all in isolation from the normal execution flow (since immutable data gives you a degree of safety to actually run that live code, with copies of the live data, and see what happens). I can even remotely load new code, if I want, effectively allowing me to deploy a hotfix without taking the node down. And I can do all of this in prod. All of this is, of course, super dangerous, but with great power etc etc.
I hardly know anything about those things, and write java backends powering one of the most used services in my country. So I disagree with it being that complicated.
If you write the service stateless it's incredible what you can achieve with a couple small instances of a default spring boot container.
I work on a lot of legacy systems in financial services, the biggest issues related to threads is variable scope regarding servlet design patterns. I just migrated a 18 year old app off Weblogic to TomEE and we had issues with struts tags. The main app I work on has around 350 concurrent users. I have JMX on all the time and monitor it for long running threads and tune it when needed. The problem I have with Java is the massive amount of libraries that can be used and developers who copy and paste code and don't think about what the code does. The verbosity kills me too, it's so over done. I've decided to learn Go just because I'm tired of reading Java code, especially legacy code. But yes you are correct there is a lot of settings in the JVM and a lot to read to understand it. It's a powerful language with a lot of features.
> If concurrency isn't an issue, then the massive amount of libraries can help you a lot.
Can you point to another language that has anything remotely comparable to `java.util.concurrent`? Also, Java is getting green threads by means of Project Loom.
> In my opinion, Java as a web language is good when you don't need to really understand what's happening (like in low-traffic situations). If concurrency isn't an issue, then the massive amount of libraries can help you a lot.
Not sure how to interpret this comment.. If high concurrency and high performance matter, that is precisely where Java shines. The only other reasonable option would be C++ but it brings so much pain with it that Java is the way to go.
If traffic is low and performance doesn't matter (which is most sites), then sure, use whatever favorite scripting language.
I found that my JS experience made a lot of Elixir feel very familiar (lambdas, destructuring, default args, string interpolation, optional typing).
And compared to Node, the BEAM is a godsend in terms of its non-blocking process scheduling and fault isolation. A single uncaught exception in Node and kaboom. Plus, if you do anything cpu intensive with Node, your app stalls. In the BEAM, infinite loops are even fine due to time slice scheduling.
A talk in ElixirConf this year showed that the pipe operator in Elixir is just a macro. A Code BEAM V conf Q&A with Jose had a (playful, trolling) question about implementing right handed assigns and Jose said that you can just write a macro if you want it. That all reinforces that the core lang doesn't need to change really; it's extensible enough to let you do whatever you want on top. Pretty cool.