How to configure a fine tuned thread pool for futures?
Asked Answered
A

4

80

How large is Scala's thread pool for futures?

My Scala application makes many millions of future {}s and I wonder if there is anything I can do to optimize them by configuring a thread pool.

Thank you.

Anticathode answered 8/3, 2013 at 1:41 Comment(2)
Slick 3.0 uses own connection and threadpool so why do we need to provide implicit executioncontext to slick when it manages own thread poolCodd
@RahulGulabani, from "essential slick" book : The reason is that map, flatMap methods of Action allows you to call arbitrary code when joining the actions together. Slick cannot allow that code to be run on its own execution context, because it has no way to know if you are going to tie up Slicks threads for a long time.Hoick
V
90

You can specify your own ExecutionContext that your futures will run in, instead of importing the global implicit ExecutionContext.

import java.util.concurrent.Executors
import scala.concurrent._

implicit val ec = new ExecutionContext {
    val threadPool = Executors.newFixedThreadPool(1000)

    def execute(runnable: Runnable) {
        threadPool.submit(runnable)
    }

    def reportFailure(t: Throwable) {}
}
Vendue answered 8/3, 2013 at 2:0 Comment(5)
Great answer, you can reduce the boilerplate a bit by using the helper methods on ExecutionContext that let you instantiate directly from a given Executor. Eg implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))Ossy
Granted this all is nice, but is there a real limit in threads on implicits.global ? If so is this configurable like akka via application.conf?Ammeter
@Ammeter yes, implicits.global is only 1 thread per CPU core. Optimal for cpu-bound tasks. But for classic blocking IO (eg jdbc) it's a performance disaster.Beghard
I needed to add a call to shut down the thread pool after using this, or the program never terminates ... def shutdown() = threadPool.shutdown()Tow
Why does it shutdown in the "normal" case, but not when we set the implicit to something else?Asiaasian
K
159

This answer is from monkjack, a comment from the accepted answer. However, one can miss this great answer so I'm reposting it here.

implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))

If you just need to change the thread pool count, just use the global executor and pass the following system properties.

-Dscala.concurrent.context.numThreads=8 -Dscala.concurrent.context.maxThreads=8
Karyokinesis answered 11/6, 2014 at 23:4 Comment(3)
I tried both of these with the value as 5, and I'm still seeing up to 8 threads running concurrently.Oviform
@Oviform (or others with the same problem): are you sure that the code you're looking at does not start additional threads under the hood, maybe from a library it's using? The thread names can give you a hint.Concessionaire
also note that there's a scala.concurrent.context.maxExtraThreads setting with a default of 256 in the global executor. These threads are used by blocking code for instance when you call Await.ready on a Future.Concessionaire
V
90

You can specify your own ExecutionContext that your futures will run in, instead of importing the global implicit ExecutionContext.

import java.util.concurrent.Executors
import scala.concurrent._

implicit val ec = new ExecutionContext {
    val threadPool = Executors.newFixedThreadPool(1000)

    def execute(runnable: Runnable) {
        threadPool.submit(runnable)
    }

    def reportFailure(t: Throwable) {}
}
Vendue answered 8/3, 2013 at 2:0 Comment(5)
Great answer, you can reduce the boilerplate a bit by using the helper methods on ExecutionContext that let you instantiate directly from a given Executor. Eg implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))Ossy
Granted this all is nice, but is there a real limit in threads on implicits.global ? If so is this configurable like akka via application.conf?Ammeter
@Ammeter yes, implicits.global is only 1 thread per CPU core. Optimal for cpu-bound tasks. But for classic blocking IO (eg jdbc) it's a performance disaster.Beghard
I needed to add a call to shut down the thread pool after using this, or the program never terminates ... def shutdown() = threadPool.shutdown()Tow
Why does it shutdown in the "normal" case, but not when we set the implicit to something else?Asiaasian
T
3

best way to specify threadpool in scala futures:

implicit val ec = new ExecutionContext {
      val threadPool = Executors.newFixedThreadPool(conf.getInt("5"));
      override def reportFailure(cause: Throwable): Unit = {};
      override def execute(runnable: Runnable): Unit = threadPool.submit(runnable);
      def shutdown() = threadPool.shutdown();
    }
Trinhtrini answered 24/8, 2015 at 5:32 Comment(0)
W
-1
class ThreadPoolExecutionContext(val executionContext: ExecutionContext)

object ThreadPoolExecutionContext {

  val executionContextProvider: ThreadPoolExecutionContext = {
    try {
      val executionContextExecutor: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(25))
      new ThreadPoolExecutionContext(executionContextExecutor)
    } catch {
      case exception: Exception => {
        Log.error("Failed to create thread pool", exception)
        throw exception
      }
    }
  }
}
Wheatworm answered 29/5, 2020 at 10:57 Comment(1)
There's no description as to what you are trying to accomplish here.Bullfighter

© 2022 - 2024 — McMap. All rights reserved.