<< Passing common state to templates in Play Framework | Home | Iteratees for imperative programmers >>

Scaling Scala vs Java

In my previous post I showed how it makes no sense to benchmark Scala against Java, and concluded by saying that when it comes to performance, the question you should be asking is "How will Scala help me when my servers are falling over from unanticipated load?" In this post I will seek to answer that, and show that indeed Scala is a far better language for building scalable systems than Java.

However, don't expect our journey to get there to be easy. For a start, while it's very easy to do micro benchmarks, trying to show how real world apps do or don't handle the loads that are put on them is very hard, because it's very hard to create an app that's small enough to demo and explain in a single blog post that is at the same time big enough to actually show how real world apps behave under load, and it's also very hard to simulate real world loads. So I am going to take one small aspect of something that might go wrong in the real world, and show just one way in which Scala will help you, where Java won't. Then I will explain that this is just the tip of the iceberg, there are far more situations, and far more features of Scala that will help you in the real world.

An online store

For this exercise I have implemented an online store. The architecture of this store is in the diagram below:

As you can see, there is a payment service and a search service that the store talks to, and the store handles three types of requests, one for the index page that doesn't require going to any other services, one for making payments that uses the payments service, and another for searching the stores product list which uses the search service. The online store is the part of the system that I am going to be benchmarking, I will implement one version in Java, and another in Scala, and compare them. The search and payment services won't change. Their actual implementations will be simple JSON APIs that return hard coded values, but they will each simulate a processing time of 20ms.

For the Java implementation of the store, I am going to keep it as simple as possible, using straight servlets to handle requests, Apache Commons HTTP client for making requests, and Jackson for JSON parsing and formatting. I will deploy the application to Tomcat, and configure Tomcat with the NIO connector, using the default connection limit of 10000 and thread pool size of 200.

For the Scala implementation I will use Play Framework 2.1, using the Play WS API which is backed by the Ning HTTP client to make requests, and the Play JSON API which is backed by Jackson to handle JSON parsing and formatting. Play Framework is built using Netty which has no connection limit, and uses Akka for thread pooling, and I have it configured to use the default thread pool size, which is one thread per CPU, and my machine has 4.

The benchmark I will be performing will be using JMeter. For each request type (index, payments and search) I will have 300 threads spinning in a loop making requests with a random 500-1500ms pause in between each request. This gives an average maximum throughput of 300 requests per second per request type, or 900 requests per second all up.

So, let's have a look at the result of the Java benchmark:

On this graph I have plotted 3 metrics per request type. The median is the median request time. For the index page, this is next to nothing, for the search and payments requests, this is about 77ms. I have also plotted the 90% line, which is a common metric in web applications, it shows what 90% of the requests were under, and so gives a good idea of what the slow requests are like. This shows again almost nothing for the index page, and 116ms for the search and payments requests. The final metric is the throughput, which shows number of requests per second that were handled. We are not too far off the theoretical maximum, with the index showing 290 requests per second, and the search and payments requests coming through at about 270 requests per second. These results are good, our Java service handles the load we are throwing at it without a sweat.

Now let's take a look at the Scala benchmark:

As you can see, it's identical to the Java results. This is not surprising, since both the Java and the Scala implementations of the online store are doing absolutely minimal work code wise, most of the processing time is going in to making requests on the remote services.

Something goes wrong

So, we've seen two happy implementations of the same thing in Scala and Java, shrugging off the load I give them. But what happens when things aren't so fine and dandy? What happens if one of the services that they are talking to goes down? Let's say the search service starts taking 30 seconds to respond, after which point it returns an error. This is not an unusual failure situation, particularly if you're load balancing through a proxy, the proxy tries to connect to the service, and fails after 30 seconds, giving you a gateway error. Let's see how our applications handle the load I throw at them now. We would expect the search request to take at least 30 seconds to respond, but what about the others? Here's the Java results:

Well, we no longer have a happy app at all. The search requests are naturally taking a long time, but the payments service is now taking an average of 9 seconds to respond, the 90% line is at 20 seconds. Not only that, but the index page is similarly impacted - users are not going to be waiting that long if they've browsed into your site for the home page to show up. And the throughput of each has gone down to 30 requests per second. This is not good, because your search service went down, your whole site is now practically unusable, and you will soon start losing customers and money.

So how does our Scala app fair? Let's find out:

Now before I say anything else, let me point out that I've bounded the response time to 160ms - the search requests are actually taking about 30 seconds to respond, but on the graph, with 30 seconds next to the other values, they hardly register a line a pixel high. So what we can see here is that while search is unusable, our payments and index request response times and throughput are unchanged. Obviously, customers aren't going to be happy with not being able to do searches, but at least they can still use other parts of your site, see your home page with specials, and even still make payments for items. And hey, Google isn't down, they can always use Google to search your site. So you might lose some business, but the impact is limited.

So, in this benchmark, we can see that Scala wins hands down. When things start to go wrong, a Scala application will take it in it's stride, giving you the best it can, while a Java application will likely just fall over.

But I can do that in Java

Now starts the bit where I counter the many anticipated criticisms that people will make of this benchmark. And the first, and most obvious one, is that in my Scala solution I used asynchronous IO, whereas in my Java solution I didn't, so they can't be compared. It is true, I could have implemented an asynchronous solution in Java, and in that case the Java results would have been identical to the Scala results. However, while I could have done that, Java developers don't do that. It's not that they can't, it's that they don't. I have written a lot of webapps in Java that make calls to other systems, and very rarely, and only in very special circumstances, have I ever used asynchronous IO. And let me show you why.

Let's say you have to do a series of calls on a series of remote services, each one depending on data returned from the previous. Here's a good old fashioned synchronous solution in Java:

User user = getUserById(id);
List<Order> orders = getOrdersForUser(user.email);
List<Product> products = getProductsForOrders(orders);
List<Stock> stock = getStockForProducts(products);

The above code is simple, easy to read, and feels completely natural for a Java developer to write. For completeness, let's have a look at the same thing in Scala:

val user = getUserById(id)
val orders = getOrdersForUser(user.email)
val products = getProductsForOrders(orders)
val stock = getStockForProducts(products)

Now, let's have a look at the same code, but this time assuming we are making asynchronous calls and returning the results in promises. What does it look like in Java?

Promise<User> user = getUserById(id);
Promise<List<Order>> orders = user.flatMap(new Function<User, List<Order>>() {
  public Promise<List<Order>> apply(User user) {
    return getOrdersForUser(user.email);
  }
}
Promise<List<Product>> products = orders.flatMap(new Function<List<Order>, List<Product>>() {
  public Promise<List<Product>> apply(List<Order> orders) {
    return getProductsForOrders(orders);
  }
}
Promise<List<Stock>> stock = products.flatMap(new Function<List<Product>, List<Stock>>() {
  public Promise<List<Stock>> apply(List<Product> products) {
    return getStockForProducts(products);
  }
}

So firstly, the above code is not readable, in fact it's much harder to follow, there is a massively high noise level to actual code that does stuff, and hence it's very easy to make mistakes and miss things. Secondly, it's tedious to write, no developer wants to write code that looks like that, I hate doing it. Any developer that wants to write their whole app like that is insane. And finally, it just doesn't feel natural, it's not the way you do things in Java, it's not idiomatic, it doesn't play well with the rest of the Java ecosystem, third party libraries don't integrate well with this style. As I said before, Java developers can write code that does this, but they don't, and as you can see, they don't for good reason.

So let's take a look at the asynchronous solution in Scala:

for {
  user <- getUserById(id)
  orders <- getOrdersForUser(user.email)
  products <- getProductsForOrders(orders)
  stock <- getStockForProducts(products)
} yield stock

In contrast to the Java asynchronous solution, this solution is completely readable, just as readable as the Scala and Java synchronous solutions. And this isn't just some weird Scala feature that most Scala developers never touch, this is how a typical Scala developer writes code every day. Scala libraries are designed to work using these idioms, it feels natural, the language is working with you. It's fun to write code like this in Scala!

This post is not about how with one language you can write a highly tuned app for performance that's faster than the same app written in another language highly tuned for performance. This post is about how Scala helps you write applications that are scalable by default, using natural, readable and idiomatic code. Just like a ball in lawn bowls has a bias, Scala has a bias to helping you write scalable applications, where Java makes you swim upstream.

But scaling means so much more than that

The example I've provided of Scala scaling well where Java doesn't is a very specific example, but then what situation where your app is failing under high load isn't? Let me give a few other examples of where Scala's much nicer asynchronous IO support helps you to write scalable code:

Java 8 will make asynchronous IO simple in Java

Java 8 is probably going to include support for closures of some sort, which is great news for the Java world, especially if you want to do asynchronous IO. However, the syntax still won't be anywhere near is readable as the Scala code I showed above. And when will Java 8 be released? Java 7 was released last year, and it took 5 years to release that. Java 8 is scheduled for summer 2013, but even if it arrives on schedule, how long will it take for the ecosystem to catch up? And how long will it take for Java developers to switch from a synchronous to an asynchronous mindset? In my opinion, Java 8 is too little too late.

So this is all about asynchronous IO?

So far all I've talked about and shown is how easy Scala makes asynchronous IO, and how that helps you scale. But it doesn't stop there. Let me pick another feature of Scala, immutability.

When you start using multiple threads to process single requests, you start sharing state between those threads. And this is where things get very messy, because the world of shared state in a computer system is a crazy world where impossible things happen. It's a world of deadlocks, a world of updating memory in one thread, but another thread not seeing that change, a world of race conditions, and a world of performance bottle necks because you over eagerly marked some methods as synchronized.

However, it's not that bad, because there is a very simple solution, make all your state immutable. If all your state is immutable, then none of the above problems can happen. And this is again where Scala helps you big time, because in Scala, things are immutable by default. The collection APIs are immutable, you have to explicitly ask for a mutable collection in order to get mutable collections.

Now in Java, you can make things immutable. There are some libraries that help you (albeit clumsily) to work with immutable collections. But it's so easy to accidentally forget to make something mutable. The Java API and language itself don't make working with immutable structures easy, and if you're using a third party library, it's highly likely that it's not using immutable structures, and often requires you to use mutable structures, for example, JPA requires this.

Let's have a look at some code. Here is an immutable class in Scala:

case class User(id: Long, name: String, email: String)

That structure is immutable. Moreover, it automatically generates accessors for the properties. Let's look at the corresponding Java:

public class User {
  private final long id;
  private final String name;
  private final String email;

  public User(long id, String name, String email) {
    this.id = id;
    this.name = name;
    this.email = email;
  }

  public long getId() {
    return id;
  }

  public String getName() {
    return name;
  }

  public String getEmail() {
    return email
  }
}

That's an enormous amount of code! And what if I add a new property? I have to add a new parameter to my constructor which will break existing code, or I have to define a second constructor. In Scala I can just do this:

case class User(id: Long, name: String, email: String, company: Option[Company] = None)

All my existing code that calls that constructor will still work. And what about when this object grows to have 10 items in the constructor, constructing it becomes a nightmare! A solution to this in Java is to use the builder pattern, which more than doubles the amount of code you have to write for the object. In Scala, you can name the parameters, so it's easy to see which parameter is which, and they don't have to be in the right order. But maybe I might want to just modify one property. This can be done in Scala like this:

case class User(id: Long, name: String, email: String, company: Option[Company] = None) {
  def copy(id: Long = id, name: String = name, email: String = email, company: Option[Company] = company) = User(id, name, email, company)
}

val james = User(1, "James", "james@jazzy.id.au")
val jamesWithCompany = james.copy(company = Some(Company("Typesafe")))

The above code is natural, it's simple, it's readable, it's how Scala developers write code every day, and it's immutable. It is aptly suited to concurrent code, and allows you to safely write systems that scale. The same can be done in Java, but it's tedious, and not at all a joy to write. I am a big advocate of immutable code in Java, and I have written many immutable classes in Java, and it hurts, but it's the lesser of two hurts. In Scala, it takes more code to use mutable objects than to use immutable. Again, Scala is biased towards helping you scale.

Conclusion

I cannot possibly go into all the ways in which Scala helps you scale where Java doesn't. But I hope I have given you a taste of why Scala is on your side when it comes to writing Scalable systems. I've shown some concrete metrics, I've compared Java and Scala solutions for writing scalable code, and I've shown, not that Scala systems will always scale better than Java systems, but rather that Scala is the language that is on your side when writing scalable systems. It is biased towards scaling, it encourages practices that help you scale. Java, in contrast, makes it difficult for you to implement these practices, it works against you.

If you're interested in my code for the online store, you can find it in this GitHub repository. The numbers from my performance test can be found in this spreadsheet.

Tags : ,


Avatar: James Roper

Re: Scaling Scala vs Java

In case you've noticed the rather ironic situation where my blog went down a few hours after I published this, I'd love to say that the reason is because the blog is implemented in Java and not Scala (it is running on Pebble, a Java blog application), but the reason was actually because the load generated by this blog post, more traffic than I've ever seen before, was causing Apache to fork more processes than usual.  My server started running out of memory, and then the Linux OOM killer very kindly decided to *fix* that for me by killing Java.

So now I've made a few adjustments, I've double the amount of swap space available so Linux hopefully won't be so obliging in killing the most important process on the server again, I've switched Apache to worker mode instead of prefork which should lower the amount of memory it needs, and I've removed a few other unused services from my server.  Hopefully this should keep it up and running.

Avatar: badyl

Re: Scaling Scala vs Java

 Hi,

The same can happen in your store application - you use async IO so probably won't run out of threads (like in thread per connection model) - but it doesn't protect you from running out of JVM heap memory as you can accept (theoretically) unlimited number of connections until OOME happens.

Does Play framework provide built in feature to limit number of concurrent connections to the system so it for example quickly returns HTTP 503 allocating as little as possible on the heap?

Thanks,

badyl

Avatar: James Roper

Re: Scaling Scala vs Java

 I haven't done any formal measurements, but I suspect the amount of heap an average request takes would be around 2kb.  With a 256mb heap, you'll run out of memory at 125000 concurrent requests.  That's several orders of magnitude above the load that I was testing with.  The OS will start refusing to accept connections as it reaches its file descriptor limits before you run out of memory.  So I don't think limiting connections is necessary here.  Play is designed to handle massively high numbers of concurrent connections, being a framework with first class support for websockets and comet.

But yes, there are always limits, in the example above we hit the thread pool limit in Java.  The point I want to make is not that Play lets you avoid resource limits, it gives you greater control over them.  In a servlet based framework, you have one thread pool.  You want this thread pool to be big so that you can handle blocking IO, but you also want it to be small to give your server a chance to finish some requests by blocking subsequent requests when it's under high load, because adding more load to an already overloaded system generally slows it down.

What Scala with Play and Akka makes very easy is having different resources allocated for different requests, you can have a small thread pool for a few high CPU tasks, a big thread pool for making blocking calls on a local database, and another small thread pool for making async calls on remote services, and use these accordingly.  When lots of requests for the high CPU tasks come in, they queue up, but other types of requests continue unhindered.

Avatar: badyl

Re: Scaling Scala vs Java

 Yes, I agree that in your example you will first hit problems with number of connections (and related to it limits for file descriptors, ephemeral ports on single network interface, network buffers etc.).

But what in case your requests, responses and other objects allocated during request processing is much bigger and your heap is your limit? I am just curious if there is anything built in in Play so I can just set it up easily and limit number of concurrent requests that actually go into my system and occupy heap.

Avatar: Clay

Re: Scaling Scala vs Java

Come on, you can use a java future/promise class or some type of shim that implements iterable and allows you to use for loop semantics rather than flat map just like your Scala example.

Avatar: James Roper

Re: Scaling Scala vs Java

That's not a for loop, it's a for comprehension, which is completely different from a for loop. The following code:

for {
 a <- getA()
 b <- getB(a)
} yield b

Actually gets compiled to something that looks like this:

getA().flatMap { a => 
  getB(a).map(b =$gt; (a, b))
}.map(r => r._2)

As you can see it's not a loop at all, it's syntactic sugar for doing many flatmaps and maps over and over. The Scala code is actually doing exactly the same as the Java code, it's just that the Scala language is built for doing these types of things, where Java isn't.

Avatar: Clay

Re: Scaling Scala vs Java

 You are being ridiculous. The following Java syntax would be easy to accommodate:

<div> </div> <div>for (User user : getUserById(id))</div> <div>for (List<Order> orders : getOrdersForUser(id))</div> <div>for (List<Product> products : getProductsForOrders(orders))</div> <div>for (List<Stock> stock : getStockForProducts(products)) {</div> <div><span class="Apple-tab-span" style="white-space:pre"> </span>// Do something</div> <div>}</div> <div> </div> <div>"That's not a for loop, it's a for comprehension, which is completely different from a for loop."</div> <div> </div> <div>The only technical difference is that Scala's for loops can return a value with yield, which is a great design. It's still a for loop though. No snobbish flowery synonyms are required :)</div> <div> </div>
Avatar: James Roper

Re: Scaling Scala vs Java

For comprehensions can be used to loop, but they are more than loops.  With for comprehensions, you are passing closures to the flatmap and map methods.  With Java for each loops, you are not passing a closure, it compiles to a loop in bytecode around an ordinary block.  Because in Scala for comprehensions you are passing closures, the execution of those closures can be deferred to later.  Hence Scala for comprehensions can be used to compose asynchronous code, because the execution of those closures dosen't have to happen until the future/iteratee has completed.  In Java, since it is just wrapping a block with a loop, the execution cannot be deferred to later, hence Java for each loops cannot be used to compose asynchronous code, since the code has to either be executed now or never. 

Avatar: Clay

Re: Scaling Scala vs Java

Sorry, I was wrong and you are right :) A Java "for" can not defer execution as needed for async processing. I didn't know Scala could do that. I'll be reading into that more today. thanks for the explanation.

Re: Scaling Scala vs Java

You have an error I think in the code snippet about using Future in Java. flatMap's should be called respectively on orders and products. And I think that the second variable in the snippet should be stock.

 

Avatar: James Roper

Re: Scaling Scala vs Java

Thankyou, you are correct.  This is what happens when you rush to finish a blog post at 2am.  At least I proved my point of the code making it easy to miss things :)

Avatar: Kai Wähner

Re: Scaling Scala vs Java

Hi James,

nice article.

However, I would be one of the guys you mentioned who says that you are comparing apples and oranges :-)

Especially, I wonder why you did not use Play for Scala and Play for Java as the Play framework offers APIs for both languages. This would be a real comparison - however, probably with the same results?

Best regards,

Kai Wähner (Twitter: @KaiWaehner)

Avatar: James Roper

Re: Scaling Scala vs Java

I started using Play framework using the Java API.  I embraced the async APIs.  But it was frustrating, it's not how I like writing Java, and the developers I was working with didn't see the point in doing everything async.  I've given presentations at user groups on doing async IO in Java using Play framework, and the Java developers are always sceptical over the number of anonymous classes and how complex it all looks.  They don't want to write code like that, because it doesn't feel natural.  So my reasoning behind choosing Tomcat with commons HTTP client was because these are natural technology choices for Java developers.

Avatar: Kai Wähner

Re: Scaling Scala vs Java

Thanks for your explanation.

Btw: I do not disagree that Scala scales better. However, as you said, many Java develerops are scared of learning new concepts (and languages), unfortunately. Let's hope that more people will use Play Scala or at least Scala's concepts in Play Java API in the future.

Kai

Avatar: James Roper

Re: Scaling Scala vs Java

 Perhaps we agree more than you think than.  I don't think Scala scales better, at the end of the day, Scala and Java are just different ways of expressing the same byte code, they both scale the same.  And look at Facebook, it's written in PHP.  If PHP can work at Facebook scale, then anything can made to scale.  But, when I'm writing Scala, I feel like the language is working with me to help me achieve this, whereas I'm sick to death of writing anonymous classes, private final fields, always making sure I wrap lists in Guava ImmutableList.copyOf and everything else I need to do to be confident that my Java systems will scale.

Avatar: Javin

Re: Scaling Scala vs Java

I don't have much experience on Scala but in terms of Scalability, I stil think Java scores better.

Avatar: James Roper

Re: Scaling Scala vs Java

On what do you base this?  If you're refering to raw performance, read jazzy.id.au/default/2012/10/16/benchmarking_scala_against_java.html.  The fact is, from a scoring perspective, Java and Scala are basically identical.

Avatar: pjriot

Re: Scaling Scala vs Java

Hi Roger,

Have you been watching development of the new JAX-RS 2.0 spec? It seems to make async request handling a good deal simpler.

Avatar: James Roper

Re: Scaling Scala vs Java

 I just had a look then, I think I like promises a lot better, they compose, they make it clear what a particular method call is returning, and there's no magic.

Re: Scaling Scala vs Java

 Apologies for calling you Roger. I was just speaking with a colleague of mine with that name when composing the post.

Avatar: James Roper

Re: Scaling Scala vs Java

 No worries :)

Re: Scaling Scala vs Java

Well written article and I agree with everything said.

People seem to be taking issue with the fact that, yes, a masochist could conceivably write an async java solution.  Your point is simply that they don't.

Maybe a follow up article could compare how a disgusting java implementation would look compared to the very simple scala one.  I know this becasue I've written an async framework for production use in java, and then later in scala, and the latter was easier to program, debug, and maintain.  

 

 

Avatar: James Roper

Re: Scaling Scala vs Java

I think the difficulty here is presenting it.  A trivial app will always look simple, so it needs to be a big app, but if it's big, then no one will take a look at it, it will be impossible to present concisely in a blog post that anyone would read, and the critiques will still criticise.

Besides, I'm not trying to change anyones opinions here, the motivation behind writing this blog post was that people were asking about benchmarking Scala against Java.  In jazzy.id.au/default/2012/10/16/benchmarking_scala_against_java.html I explained why this was the wrong question, this post is a follow up to that.  I'm just answering a question.

Re: Scaling Scala vs Java

This article makes a few (valid) points:

* Async IO has better fault tolerance than synchronous IO.

* Scala has better syntax and semantics for async programming/constructs.

* Java is verbose.

Though these are fine, and pretty well explained, there's nothing about scalabilty here. Sorry.

Avatar: James Roper

Re: Scaling Scala vs Java

Fault tolerance is a big part of scalability.  For a small system it's likely that at any one point in time, everything will be working.  As you scale up, that becomes the opposite, the chance of something breaking increases to the point where something being down is not an exceptional situation, it's a normal situation.  If your system isn't fault tolerant, then it won't scale to that point, hence a scalable system must be a fault tolerant system.

That aside, I chose fault tolerance as an example because it's easy to simulate a fault in a way that can be clearly explained and comprehended by readers of a blog post.  Through that I could show some meaningful numbers, and having understood that, it's not hard to then make the jump to see how the same concepts can be applied to running many tasks in parrallel and distributing load across multiple systems, which are both directly related to scalability.

Re: Scaling Scala vs Java

 It would be interesting to compare Async Play! Java with Apache Mina and Glassfish Grizzly. 

However, personally I think the larger impediment to Async development in Javaland is the lack of support in the Servlet API. The inability to smoothly migrate existing code (however unlikely) is often a killer for developing new code in a better way.

Re: Scaling Scala vs Java

Hello,

I guess the slump in peformance in the Java solution is caused by depleation of Tomcat's thread pool (which is of size 200) and waiting for threads to be available again. I'm not sure if I understand it but simply calling the services asynchronously would not help since the thread handling a connection is still in use, even if it is idle.

Does the try-yield block in Scala work as asynchronous servlets in Java, or would Scala suffer the same problem if there was a thread pool for handling connections?

Thanks,Libor

Avatar: James Roper

Re: Scaling Scala vs Java

 Yes, it is the thread pool that causes the issues.

For the Scala solution I used Play framework, which allows you to return a future as a result, so the framework takes care of what happens when the result is ready.  If you were using something like the Servlet 3 API with asynchronous support, what you would do would be register an onComplete callback on the returned future, and it would handle sending the result to the response asynchronously.  This is cumbersome, however I suspect noone will actually ever use this, rather there will be frameworks built on top of the async servlet API that allow you to just return futures.

Re: Scaling Scala vs Java

Great post!

I've learned and used Scala for the exactly same reason you mentioned. But, I failed to encourage my colleagues to program with Scala.

Now I believe your post will help. :)

Good job, James.

Justin.

PS:

The following is my post on the same subject, but in Korean.

http://ppassa.wordpress.com/2012/05/23/scala_for_java_programmer/

 

Avatar: pieroxy

Re: Scaling Scala vs Java

 James,

While I agree with most of what you wrote, Java also provides asynchronous servlets which, while made for long http requests, could also be made to serve any request susceptible to be calling anything outside the VM that may be slow. With a tiny tiny framework of a few dozen lines, all your "servlets" would be asynchonous, and you then could do  anything synchronously from there - avoiding that servlet A impacts Servlet B. So your synchronous example would actually work better than its Scala counterpart ;-)

Having every single call asynchronous as in your example makes also things more complicated to A) unit test properly and B) debug. 

I don't have firsthand experience with Scala or with massive parallelization / asynchronous programming. Can you tell us if really the overhead in unit testing and debugging is bad?

Avatar: James Roper

Re: Scaling Scala vs Java

Of course you can handle requests asynchronously using asynchronous servlets, but the code overhead is still massive, the asynchronous HTTP libraries available don't make things easy either from a code readability perspective, and there's no standard way of doing promises in Java - Java provides futures, but you can't even attach callbacks to them when they are finished.  The code to implement it, apart from the boiler plate of Java anonymous classes, would be mostly just setting up runnables and futures, instead of focussing on the business logic.

As far as debugging goes, it's not as nice as synchronous code.  Stack traces are often meaningless, and stepping through code with a debugger requires putting break points everywhere.  The debuggers I think will get smarter, but it will never be as nice as debugging synchronous code.  But it's not impossible.  The Typesafe console uses compile time weaving on code to be able to follow asynchronous call flows between actors in Akka, we should see similar things for futures in the future.

From a unit testing perspective, usually in order to unit test you need to bring up your thread pools, so unit testing gets a little bit more heavy weight, but it's not too bad.  Of course, if you want to unit test your the concurrency side of your code, that's another story, but then that's no better with synchronous solutions, at least with a functional asynchronous solution you can better reason about your code.


Add a comment Send a TrackBack