Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

scala - How risky is it to call Await.result on db calls

When using phantom how dangerous is it to be following this pattern in db calls:

Await.result(dbOperationFut, 30.seconds)

This isn't really phantom specific but it is the scala driver being used.

I am weary of this pattern because of the potential GC pause that might last for over x seconds. How many seconds is safe given GC pauses?

I am personally in favor of using for-comp and not blocking like this, but just want to know if this is a REALLY bad practice or it is fine.

Context: This would be for akka based applications (akka, akka http)

Thoughts?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Becareful with Await.result

Note this applies for both Akka and play apps

Await.result should be used very carefully only when it is absolutely necessary.

Await.result blocks the thread in which it is running until the given duration. Blocking the thread will waste the precious computation resource because that thread will not be able to do any useful computation like handling the new request or number crunching in an algorithm etc.

So, Avoid using the Await.result as much as possible.

But, when do we use it (Await.result) ?

Here is one of the typical use case for using Await.result.

Lets say you have written a program containing main thread and all the computation inside the main thread is asynchronous. Now once you start the asynchronous computation inside the main thread. Some one has to stop the main thread from existing till the asynchronous computation finishes, if not the program stops running and you cannot see the result of the asynchronous computation.

When an application begins running, there is one non-daemon thread, whose job is to execute main(). JVM will not exit by itself until and unless non-daemon threads are completed.

object Main {
 def main(args: Array[String]): Unit = {
  import scala.concurrent.Future
  import scala.concurrent.duration._

  val f = Future { //do something }
  //stop main thread till f completes
  Await.result(f, 10 seconds)
 }
}

Future uses daemon threads for running. So daemon threads cannot stop the JVM from shutting down. So JVM shuts down even if non-daemon threads are running.

In the above case there is no other way expect stopping (blocking) the main thread till the computation f completes if not main thread exits and computation stops.

In most of the cases you do not need to use Await.result and simple Future composition using map and flatMap would suffice.

Risks of using Await.result (In general all blocking code)

Running out of threads in event based model

In event based model you will quickly run out of threads if you have blocking code which takes long time to return. In playframework any blocking call could decrease the performance of the application and app will becomes dead slow as it runs out of threads.

Running out of memory in non-event based models

In thread per request models. When you have blocking calls which take long time to exit/return.

case 1: If you have fixed thread pool then application might run out of threads.

case 2: If you have dynamically growing thread pool then your application will suffer from too much context switching overhead and also will run out of memory because of too many blocked threads in memory.

In all of the cases no useful work is done expect for waiting for some IO or some other event.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...