
Scaling Scala vs Java - rohshall
http://jazzy.id.au/default/2012/11/02/scaling_scala_vs_java.html
======
abalone
This comparison is extremely flawed.

He is not comparing Scala vs Java. He's comparing Play Framework (async i/o)
vs. a Servlet that doesn't use async i/o.

He admits later that he purposefully handicapped the Java version. His reason
is, he claims that Java's Promise pattern is _so hard to program_ that "Java
developers don't do that." Which.. wow. His evidence: he's written a lot of
Java apps and _he 's_ personally never used it.

And so he just switches off async i/o for Java.

We all know Java has more boilerplate. The Promise pattern is 2 lines of
boilerplate code per call, much like an event handler. To go from that to
claiming "Java developers don't do" Promise is a huge, unsupported leap.

Also you'd get the impression from his writing that Play Framework is only
available for Scala.. but there's a Java API too.

~~~
bad_user
First of all James Roper is one of the main engineers working on the Play
Framework. You're quick to jump to conclusions.

The "Promise pattern" is extremely awful for Java. Yes, Play does allow Java
developers to do Async I/O by means of Futures/Promises. That doesn't make it
any less awful and a quick search on Play's mailing list should highlight it.
The reason for it is because working with Future/Promise instances involves a
lot of calls to map() and flatMap(). In comparison to
java.util.concurrent.Future (which sucks), these Futures are non-blocking and
can be processed and transformed without doing a .get() ... We aren't talking
about one or two calls, but rather about chains of calls. Scala is a language
designed for this, it even has monad comprehensions and an upcoming library
that should bring C#'s async [1]

Iteratees are also one of the coolest notions for dealing with streams of data
that ever came out of the FP world. And if in Java you can sort of limp around
when it comes to simple Future/Promise objects, well Iteratees are in a
different league [2] [3]

The Play developers did an extremely awesome job by exposing a clean Java API.
But some things are sorely missing, as there's no way to expose them in Java
cleanly, which is why the internals of Play's server are written in Scala.

Also, it does make sense to compare frameworks in language comparisons. For
example you can't compare C# versus Java for web development, without
comparing the frameworks themselves. If Play also allows you to use Java,
that's only testament to the awesomeness of Scala, of the JVM and of Play's
developers.

[1] [https://github.com/scala/async](https://github.com/scala/async)

[2] [http://mandubian.com/2012/08/27/understanding-
play2-iteratee...](http://mandubian.com/2012/08/27/understanding-
play2-iteratees-for-normal-humans/)

[3]
[http://www.playframework.com/documentation/2.2.x/Iteratees](http://www.playframework.com/documentation/2.2.x/Iteratees)

~~~
brown9-2
The fact that the author is one of the main developers on the Play Framework
means that he should be even more gracious towards the framework/design he is
comparing Play against, otherwise he and his project comes off as comparing
their project against weak strawmen.

Sure, Play has some nice concepts - but the fact that it's built in Scala (and
that _there is a Java API_ ) means that all of the things that it makes
possible are also possible in plain old Java! So this isn't a performance
comparison by any means, but rather a "look at what you can do in similar
amounts of code" comparison, which is a pretty shallow comparison.

Check out the author's previous post where he concludes that Scala is faster
than Java (whatever that means, the whole concept seems to ignore the fact
that Scala compiles to JVM bytecode) was 18% faster (on a single execution?
average execution? author doesn't say):
[https://jazzy.id.au/default/2012/10/16/benchmarking_scala_ag...](https://jazzy.id.au/default/2012/10/16/benchmarking_scala_against_java.html)

~~~
gclaramunt
> Sure, Play has some nice concepts - but the fact that it's built in Scala
> (and that there is a Java API) means that all of the things that it makes
> possible are also possible in plain old Java! So this isn't a performance
> comparison by any means, but rather a "look at what you can do in similar
> amounts of code" comparison, which is a pretty shallow comparison.

If you follow that argument, what you can do in Java that you can't do by
writing bytecode by hand? Or, what you can do with a JVM lang that you can't
do in assembler? His argument is that even you can do the same in Java, is so
unnatural that (almost) nobody does it.

------
coolsunglasses
This blog post is not great. It's also not about scaling at all.

For one thing, a promises based async implementation is not incredibly helpful
when you have a strictly one-after-another ordering of data dependencies.

In the interest of comparison, however, I decided to translate the example
code to the equivalent synchronous and asynchronous Clojure code.

[https://www.refheap.com/20640](https://www.refheap.com/20640)

Things to note:

Instead of being forced to use a compiler-assisted construct, promises on
Clojure get dereferenced. Dereferencing is the same operation used to get the
value of agents, atoms, and refs as well.

Deref'ing (@) a promise over and over is totally okay.

Using promises doesn't make the Scala solution meaningfully or usefully
asynchronous unless the handler is yielding its thread while blocking on I/O.

~~~
bad_user
> _a promises based async implementation is not incredibly helpful when you
> have a strictly one-after-another ordering of data dependencies_

I don't understand what you mean. Of course it's helpful.

    
    
        memcached.get[String]("someKey") flatMap { 
          case Some(value) => Future.successful(value)
          case None =>
            database.query(...).flatMap { value =>
              memcached.set("someKey", value, 10.minutes)
            }
        }
    

The above fetches a key from memcached and in case it doesn't exist, it
fetches it from the database and once that's done, it sets the value in
memcached and once that's done the processing is done and thus you can
continue with other things. If the clients are non-blocking, than that's
totally asynchronous and scalable.

In Clojure you don't see this because in Clojure people don't work with
Monads.

> _Using promises doesn 't make the Scala solution meaningfully or usefully
> asynchronous unless the handler is yielding its thread while blocking on
> I/O._

The idea of Futures is not to use blocking I/O, but rather to either:

1) use non-blocking I/O, or

2) delegate the blocking I/O call to some sort of actor, then continue the
execution once that's done

Both are possible and quite easy.

~~~
coolsunglasses
Monads are used in Clojure, just not for this particular use-case because it's
unnecessary the majority of the time.

A good example of monad (and macros) use would be:
[http://github.com/clojure/core.async](http://github.com/clojure/core.async)

------
pron
Well, it's a good thing we've got Java lightweight threads[1]. They let you
write synchronous, blocking, simple code, which it transforms to asynchronous
calls. It gives you this "Scala scalability" to Java (or any JVM language)
without wrapping your head around functional constructs. Scalaists can think
of it as an async macro that works for all JVM languages, and can span a whole
call-stack rather than just a single expression.

[1]:
[https://github.com/puniverse/quasar](https://github.com/puniverse/quasar)

~~~
danieldk
I played a bit with Quasar a week ago. I really liked how simple it is to wrap
existing async calls (with callbacks) using FiberAsync and use them in
synchronous code.

It's still a bit to early for me to migrate from Akka. But thanks for the
great work you are doing!

------
jondot
Every now and then comes such an article and nudges me towards Scala again. It
can really be an elegant and succinct language that can be all-encompassing.

But although I have a production running Scala project, I cringe every time I
have to work with Scala just because of the tooling. It's sad to see that SBT
is cryptic and IDEs are slow and misleading.

When I work on the JVM I prefer Clojure. I think lein makes an exemplary
development, build, and dependency management tool. I wish Scala had that.

~~~
ShardPhoenix
Intellij IDEA isn't so bad as an IDE (it's faster and less buggy than the
Eclipse Scala plugin last time I checked), but SBT is utterly horrible. It's
so awful I'd literally strongly prefer to use Ant (ie clunky scripting in XML)
instead.

~~~
TelmoMenezes
Yup I second that. Intellij IDEA is currently very good with Scala, especially
if one avoids SBT. I use it with Maven and everything works smoothly in a
project with several sub-projects and various external dependencies (most to
Java libraries).

I suspect the awfulness of SBT is causing a lot of harm to Scala adoption.

~~~
jgrowl
JetBrains has a nightly build out for their sbt plugin. It is not perfect yet
but it has worked very well for me.

[http://blog.jetbrains.com/scala/2013/07/17/sbt-plugin-
nightl...](http://blog.jetbrains.com/scala/2013/07/17/sbt-plugin-nightly-
builds/)

------
js4all
The title is a bit misleading. The blog post is about async calls in Java vs
Scala using promises. Good read though.

------
voidlogic
I dislike how the Java Promises and the Scala code unnecessarily hide the
reality of the computation from the developer, take a Go version as
counterpoint:

    
    
      func stockForProdsTO(uid int, timeout time.Duration) (*Stock, error) {
      	stockCh := make(chan *Stock, 1)
      	go func() {
      		orders := ordersForUser(userById(uid).email)
      		stockCh <- stockForProds(prodsForOrders(orders))
      	}()
      	select {
      		case result := <-stockCh:
      			return result, nil
      		case <-time.After(timeout):
      			return nil, errors.New("Could not get stock for product before timeout.")
      	}
      }

------
willvarfar
I'm a bit surprised because all my big Java servers have used Netty and are
fully asynchronous. I didn't realise there's any big load of synchronous Java
servers out there.

~~~
jbrechtel
The servers in this example were configured to be asynchronous. The clients
were not. You may still be using asynchronous clients in your code but James's
argument is that Java developers don't tend to do this because it requires a
lot of boilerplate. Scala developers do this because it's very low syntatic
overhead and frameworks+libraries embrace it.

~~~
brown9-2
Developers who don't do something that would give them incredible performance
and resilience because "it requires a lot of boilerplate" are bad developers.

~~~
jebblue
Not necessarily, more code means more maintenance which translates to more
cost. Adding new features requires more research, more work, more time, more
cost. Fixing anything requiring a patch after going production with a new
feature would likely be more expensive. Testing tools have to be verified to
work with the additional code. This all increases costs which might be OK for
some organizations and not so much for others.

~~~
brown9-2
That's a different argument though than just "it's more code so I won't do
it". If we are discussing performance then the assumption is you have a
performance problem you need to fix.

------
huntc
In fairness to James, I think the comparison he's making is in regard to the
idiosyncrasies of developers, and that Java developers tend more often than
not to use synchronous blocking calls. It is entirely possible to perform
async IO in Java of course, but James's point is that being async is a more
natural state when using Scala.

