Show / Hide Table of Contents

    Dispatchers

    What Do Dispatchers Do?

    Dispatchers are responsible for scheduling all code that run inside the ActorSystem. Dispatchers are one of the most important parts of Akka.NET, as they control the throughput and time share for each of the actors, giving each one a fair share of resources.

    By default, all actors share a single Global Dispatcher. Unless you change the configuration, this dispatcher uses the .NET Thread Pool behind the scenes, which is optimized for most common scenarios. That means the default configuration should be good enough for most cases.

    Why should I use different dispatchers?

    When messages arrive in the actor's mailbox, the dispatcher schedules the delivery of messages in batches, and tries to deliver the entire batch before releasing the thread to another actor. While the default configuration is good enough for most scenarios, you may want to change (through configuration) how much time the scheduler should spend running each actor.

    There are some other common reasons to select a different dispatcher. These reasons include (but are not limited to):

    • isolating one or more actors to specific threads in order to:
      • ensure high-load actors don't starve the system by consuming too much cpu-time;
      • ensure important actors always have a dedicated thread to do their job;
      • create bulkheads, ensuring problems created in one part of the system do not leak to others;
    • allow actors to execute in a specific SyncrhonizationContext;
    Note

    Consider using custom dispatchers for special cases only. Correctly configuring dispatchers requires some understanding of how the framework works. Custom dispatchers should not be considered the default solution for performance problems. It's considered normal for complex applications to have one or a few custom dispatchers, it's not usual for most or all actors in a system to require a custom dispatcher configuration.

    Dispatchers vs. Dispatcher Configurations

    Throughout this documentation and most Akka literature available, the term dispatcher is used to refer to dispatcher configurations, but they are in fact different things.

    • Dispatchers are low level components that are responsible for scheduling code execution in the system. These components are built into Akka.NET, there is a fixed number of them and you don't need to create or change them.

    • Dispatcher Configurations are custom settings you can create to make use of dispatchers in specific ways. There are some built-in dispatcher configurations, and you can create as many as you need for your applications.

    Therefore, when you read about "creating a custom dispatcher" it usually means "using a custom configuration for one of the built-in dispatchers".

    Configuring Dispatchers

    You can define a custom dispatcher configuration using a HOCON configuration section.

    The example below creates a custom dispatcher called my-dispatcher that can be set in one or more actors during deployment:

    my-dispatcher {
        type = Dispatcher
        throughput = 100
        throughput-deadline-time = 0ms
    }
    

    You can then set actor's dispatcher using the deployment configuration:

    akka.actor.deployment {
        /my-actor {
            dispatcher = my-dispatcher
        }
    }
    

    Or you can also set it up in code:

    system.ActorOf(Props.Create<MyActor>().WithDispatcher("my-dispatcher"), "my-actor");
    

    Built-in Dispatcher Configurations

    Some dispatcher configurations are available out-of-the-box for convenience. You can use them during actor deployment, as described above.

    • default-dispatcher - A configuration that uses the ThreadPoolDispatcher. As the name says, this is the default dispatcher configuration used by the global dispatcher, and you don't need to define anything during deployment to use it.
    • task-dispatcher - A configuration that uses the TaskDispatcher.
    • default-fork-join-dispatcher - A configuration that uses the [ForkJoinDispatcher].
    • synchronized-dispatcher - A configuration that uses the SynchronizedDispatcher.

    Built-in Dispatchers

    These are the underlying dispatchers built-in to Akka.NET:

    • ThreadPoolDispatcher

      It schedules code to run in the .NET Thread Pool, which is good enough for most cases.

      The type used in the HOCON configuration for this dispatcher is just Dispatcher.

      custom-dispatcher {
        type = Dispatcher
        throughput = 100
      }
      
    Note

    While each configuration can have it's own throughput settings, all dispatchers using this type will run in the same default .NET Thread Pool.

    • TaskDispatcher

      The TaskDispatcher uses the TPL infrastructure to schedule code execution. This dispatcher is very similar to the Thread PoolDispatcher, but may be used in some rare scenarios where the thread pool isn't available.

      custom-task-dispatcher {
          type = TaskDispatcher
          throughput = 100
      }
      
    • PinnedDispatcher

      The PinnedDispatcher uses a single dedicated thread to schedule code executions. Ideally, this dispatcher should be using sparingly.

      custom-dedicated-dispatcher {
          type = PinnedDispatcher
      }
      
    • ForkJoinDispatcher

      The ForkJoinDispatcher uses a dedicated threadpool to schedule code execution. You can use this scheduler isolate some actors from the rest of the system. Each dispatcher configuration will have it's own thread pool.

      This is the configuration for the default-fork-join-dispatcher. You may use this as example for custom fork-join dispatchers.

      default-fork-join-dispatcher {
          type = ForkJoinDispatcher
          throughput = 100
          dedicated-thread-pool {
              thread-count = 3
              deadlock-timeout = 3s
              threadtype = background
          }
      }
      
      • thread-count - The number of threads dedicated to this dispatcher.
      • deadlock-timeout - The amount of time to wait before considering the thread as deadlocked. By default no timeout is set, meaning code can run in the threads for as long as they need. If you set a value, once the timeout is reached the thread will be aborted and a new threads will take it's place. Set this value carefully, as very low values may cause loss of work.
      • threadtype - Must be background or foreground. This setting helps define how .NET handles the thread.
    • SynchronizedDispatcher

      The SynchronizedDispatcher uses the current SynchronizationContext to schedule executions.

      You may use this dispatcher to create actors that update UIs in a reactive manner. An application that displays real-time updates of stock prices may have a dedicated actor to update the UI controls directly for example.

    Note

    As a general rule, actors running in this dispatcher shouldn't do much work. Avoid doing any extra work that may be done by actors running in other pools.

    This is the configuration for the synchronized-dispatcher. You may use this as example for custom fork-join dispatchers.

    synchronized-dispatcher {
        type = "SynchronizedDispatcher"
        throughput = 10
    }
    

    In order to use this dispatcher, you must create the actor from the syncrhonization context you want to run-it. For example:

    private void Form1_Load(object sender, System.EventArgs e)
    {
        system.ActorOf(Props.Create<UIWorker>().WithDispatcher("synchronized-dispatcher"), "ui-worker");
    }
    

    Common Dispatcher Configuration

    The following configuration keys are available for any dispatcher configuration:

    • type - (Required) The type of dispatcher to be used: Dispatcher, TaskDispatcher, PinnedDispatcher, ForkJoinDispatcher or SynchronizedDispatcher.
    • throughput - (Required) The maximum # of messages processed each time the actor is activated. Most dispatchers default to 100.
    • throughput-deadline-time - The maximum amount of time to process messages when the actor is activated, or 0 for no limit. The default is 0.
    Note

    The throughput-deadline-time is used as a best effort, not as a hard limit. This means that if a message takes more time than the deadline allows, Akka.NET won't interrupt the process. Instead it will wait for it to finish before giving turn to the next actor.

    • Improve this Doc
    Back to top Copyright © 2013-2017 Akka.NET project
    Generated by DocFX