Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Akkaによるスレッドの使い方

 Akkaによるスレッドの使い方

リチャード 伊真岡

April 02, 2018
Tweet

Transcript

  1. "LLBʹΑΔ
    εϨουͷ࢖͍ํ
    ϦνϟʔυɹҏਅԬ

    View full-size slide

  2. "LLBͱ͍͑͹

    View full-size slide

  3. https://akka.io/

    View full-size slide

  4. https://akka.io/

    View full-size slide

  5. > Akka is a toolkit for building
    highly concurrent, distributed, and
    resilient message-driven
    applications for Java and Scala

    View full-size slide

  6. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling

    View full-size slide

  7. શ෦ؾʹ͠ͳ͕Β
    ίʔυΛॻ͍͍ͯͩ͘͞

    View full-size slide

  8. ͕ॿ͚ͯ͘Ε·͢

    View full-size slide

  9. "DUPSʹΑΔ
    ϝοηʔδύογϯά
    "LLB

    View full-size slide

  10. import scala.collection
    class MyActor extends Actor {
    //mutable state
    val state1: mutable.Map[String, String] = …
    val state2: mutable.ListBuffer[String] = …
    def receive = {
    //immutable message
    case MyMessage(msg)
    => procedure(msg)
    }
    def procedure(msg: String) {
    //࣍ͷϝοηʔδ͔ΒׂΓࠐ·Εͳ͍
    }
    }

    View full-size slide

  11. import scala.collection
    class MyActor extends Actor {
    //mutable state
    val state1: mutable.Map[String, String] = …
    val state2: mutable.ListBuffer[String] = …
    def receive = {
    //immutable message
    case MyMessage(msg)
    => procedure(msg)
    }
    def procedure(msg: String) {
    //࣍ͷϝοηʔδ͔ΒׂΓࠐ·Εͳ͍
    }
    }

    View full-size slide

  12. import scala.collection
    class MyActor extends Actor {
    //mutable state
    val state1: mutable.Map[String, String] = …
    val state2: mutable.ListBuffer[String] = …
    def receive = {
    //immutable message
    case MyMessage(msg)
    => procedure(msg)
    }
    def procedure(msg: String) {
    //࣍ͷϝοηʔδ͔ΒׂΓࠐ·Εͳ͍
    }
    }

    View full-size slide

  13. import scala.collection
    class MyActor extends Actor {
    //mutable state
    val state1: mutable.Map[String, String] = …
    val state2: mutable.ListBuffer[String] = …
    def receive = {
    //immutable message
    case MyMessage(msg)
    => procedure(msg)
    }
    def procedure(msg: String) {
    //࣍ͷϝοηʔδ͔ΒׂΓࠐ·Εͳ͍
    }
    }

    View full-size slide

  14. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling
    ๨Ε͍͍ͯ

    View full-size slide

  15. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling
    ๨Ε͍͍ͯ
    $PODVSSFODZಛ༗ͷ໰୊͸Ͳ͏ͯ͠΋
    ى͜Γ·͢

    View full-size slide

  16. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling
    ๨Ε͍͍ͯ
    Ұ෦ͷ௿Ϩϕϧͳॲཧ͔Β͸
    ղ์͞ΕΔ

    View full-size slide

  17. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling
    "LLB͕ड͚࣋ͬͯ͘ΕΔ
    Ұ෦ͷ௿Ϩϕϧͳॲཧ͔Β͸
    ղ์͞ΕΔ

    View full-size slide

  18. •Thread
    •join
    •Runnable/Callable
    •Lock
    •synchronized
    •Atomic variables
    •volatile
    •ThreadLocal
    •DynamicVariable
    •ConcurrentHashMap
    •ConcurrentLinkedQueue
    •ForkJoin
    •ThreadPool
    •Executor/ExecutorService
    •ExecutionContext
    •Future
    •Thread intereference
    •Memory Consistency error
    •Dead lock
    •Live lock
    •Starvation
    •InterruptedException
    •Scheduling
    ͦͷ෦෼Λݟ͍͖ͯ·͠ΐ͏
    "LLB͕ड͚࣋ͬͯ͘ΕΔ

    View full-size slide

  19. Կ͔஌ݟ͕͋Δ͔΋͠Εͳ͍

    View full-size slide

  20. ͱ͍͏ͷ͕ࠓ೔ͷτʔΫ

    View full-size slide

  21. ! ϝιουΛݺͿͱ
    ͭ·Γ
    Կ͕ى͜Δͷ͔

    View full-size slide

  22. ·ͣ͸TFOEFSଆͷ࿩

    View full-size slide

  23. ͳΔ΄ͲΘ͔ΒΜ

    View full-size slide

  24. ҰาͣͭίʔυΛ௥͍͖ͬͯ·͢

    View full-size slide

  25. class LocalActorRef
    override def !(message: Any)
    (implicit sender: ActorRef = Actor.noSender): Unit =
    actorCell.sendMessage(message, sender)

    View full-size slide

  26. class LocalActorRef
    override def !(message: Any)
    (implicit sender: ActorRef = Actor.noSender): Unit =
    actorCell.sendMessage(message, sender)

    View full-size slide

  27. trait Dispatch
    def sendMessage(msg: Envelope): Unit =
    try {
    val msgToDispatch =
    if (system.settings.SerializeAllMessages)
    serializeAndDeserialize(msg)
    else
    msg
    dispatcher.dispatch(this, msgToDispatch)
    } catch handleException

    View full-size slide

  28. trait Dispatch
    def sendMessage(msg: Envelope): Unit =
    try {
    val msgToDispatch =
    if (system.settings.SerializeAllMessages)
    serializeAndDeserialize(msg)
    else
    msg
    dispatcher.dispatch(this, msgToDispatch)
    } catch handleException

    View full-size slide

  29. EJTQBUDIʤॻྨɾՙ෺ͳͲΛʥૹΔɺ
    ૹΓग़͢ɺൃૹ͢Δɺٸૹ͢Δ
    https://eow.alc.co.jp/search?q=dispatch
    εϖʔεΞϧΫ

    View full-size slide

  30. EJTQBUDIFS㲈TFOEFS
    https://eow.alc.co.jp/search?q=dispatch
    εϖʔεΞϧΫ

    View full-size slide

  31. ͪΐͬͱ͕͍ͪ·͢

    View full-size slide

  32. TFOEFS ૹ৴ݩ
    ͱ͍͏ΑΓ͸
    %JTQBUDIFSΛ௨ա

    View full-size slide

  33. ΋͏Ұͭେࣄͳಛ௃

    View full-size slide

  34. trait Dispatch
    def sendMessage(msg: Envelope): Unit =
    try {
    val msgToDispatch =
    if (system.settings.SerializeAllMessages)
    serializeAndDeserialize(msg)
    else
    msg
    dispatcher.dispatch(this, msgToDispatch)
    } catch handleException

    View full-size slide

  35. class Dispatcher
    def dispatch(
    receiver: ActorCell,
    invocation: Envelope
    ): Unit = {
    val mbox = receiver.mailbox
    mbox.enqueue(receiver.self, invocation)
    registerForExecution(mbox, true, false)
    }

    View full-size slide

  36. class Dispatcher
    def dispatch(
    receiver: ActorCell,
    invocation: Envelope
    ): Unit = {
    val mbox = receiver.mailbox
    mbox.enqueue(receiver.self, invocation)
    registerForExecution(mbox, true, false)
    }

    View full-size slide

  37. abstract class Mailbox
    def enqueue(
    receiver: ActorRef,
    msg : Envelope
    ): Unit =
    messageQueue.enqueue(receiver, msg)

    View full-size slide

  38. abstract class Mailbox
    def enqueue(
    receiver: ActorRef,
    msg : Envelope
    ): Unit =
    messageQueue.enqueue(receiver, msg)

    View full-size slide

  39. MessageQueue
    object UnboundedMailbox {
    class MessageQueue
    extends ConcurrentLinkedQueue[Envelope]
    with UnboundedQueueBasedMessageQueue {
    final def queue: Queue[Envelope] = this
    }
    }

    View full-size slide

  40. MessageQueue
    object UnboundedMailbox {
    class MessageQueue
    extends ConcurrentLinkedQueue[Envelope]
    with UnboundedQueueBasedMessageQueue {
    final def queue: Queue[Envelope] = this
    }
    }

    View full-size slide

  41. Class ConcurrentLinkedQueue

    View full-size slide

  42. Class ConcurrentLinkedQueue

    View full-size slide

  43. http://www.cs.rochester.edu/~scott/papers/
    1996_PODC_queues.pdf

    View full-size slide

  44. http://www.cs.rochester.edu/~scott/papers/
    1996_PODC_queues.pdf

    View full-size slide

  45. -PPQ$"4 $PNQBSFBOE4XBQ

    View full-size slide

  46. $"4DPNQBSFBOETXBQ
    BUPNJDͳૢ࡞

    View full-size slide

  47. ૢ࡞͕੒ޭ͢Δ·Ͱ$"4ϦτϥΠ

    View full-size slide

  48. ͳΔ΄Ͳ
    /PO#MPDLJOH

    View full-size slide

  49. sender/receiver͔Β
    concurrentʹΞΫηε

    View full-size slide

  50. ଟ਺ͷsender͔Β
    concurrentʹΞΫηε

    View full-size slide

  51. https://doc.akka.io/docs/akka/2.5/mailboxes.html
    SingleConsumerOnlyUnboundedMailbox
    This queue may or may not be faster than the default one depending on your use-case—
    be sure to benchmark properly!
    NonBlockingBoundedMailbox
    Backed by a very efficient Multiple-Producer Single-Consumer queue
    …etc
    ଞʹ΋MessageQueue৭ʑ͋Γ·͢

    View full-size slide

  52. MessageQueue
    ʹೖΕͨ͋ͱͷ࿩

    View full-size slide

  53. class Dispatcher
    def dispatch(
    receiver: ActorCell,
    invocation: Envelope
    ): Unit = {
    val mbox = receiver.mailbox
    mbox.enqueue(receiver.self, invocation)
    registerForExecution(mbox, true, false)
    }

    View full-size slide

  54. class Dispatcher
    def dispatch(
    receiver: ActorCell,
    invocation: Envelope
    ): Unit = {
    val mbox = receiver.mailbox
    mbox.enqueue(receiver.self, invocation)
    registerForExecution(mbox, true, false)
    }

    View full-size slide

  55. class Dispatcher
    override def registerForExecution(
    mbox: Mailbox,
    hasMessageHint: Boolean,
    hasSystemMessageHint: Boolean
    ): Boolean = {
    if (mbox.canBeScheduledForExecution(
    hasMessageHint, hasSystemMessageHint)) {
    if (mbox.setAsScheduled()) {

    executorService execute mbox


    }

    View full-size slide

  56. class Dispatcher
    override def registerForExecution(
    mbox: Mailbox,
    hasMessageHint: Boolean,
    hasSystemMessageHint: Boolean
    ): Boolean = {
    if (mbox.canBeScheduledForExecution(
    hasMessageHint, hasSystemMessageHint)) {
    if (mbox.setAsScheduled()) {

    executorService execute mbox


    }

    View full-size slide

  57. ͜͜Ͱ;Γ͔͑Γ

    View full-size slide

  58. ExecutorService

    View full-size slide

  59. Java͔Β
    ThreadΑΓந৅౓ͷߴ͍ඇಉظ༻JOUFSGBDF
    ExecutorService

    View full-size slide

  60. &YFDVUPS4FSWJDF

    View full-size slide

  61. class Dispatcher
    override def registerForExecution(
    mbox: Mailbox,
    hasMessageHint: Boolean,
    hasSystemMessageHint: Boolean
    ): Boolean = {
    if (mbox.canBeScheduledForExecution(
    hasMessageHint, hasSystemMessageHint)) {
    if (mbox.setAsScheduled()) {

    executorService execute mbox


    }

    View full-size slide

  62. abstract class Mailbox
    abstract class Mailbox(
    val messageQueue: MessageQueue
    ) extends ForkJoinTask[Unit]
    with SystemMessageQueue
    with Runnable {
    ...
    }

    View full-size slide

  63. ͜͜·Ͱ͸senderଆ

    View full-size slide

  64. ͔͜͜Β͸receiverଆ

    View full-size slide

  65. class Dispatcher
    override def registerForExecution(
    mbox: Mailbox,
    hasMessageHint: Boolean,
    hasSystemMessageHint: Boolean
    ): Boolean = {
    if (mbox.canBeScheduledForExecution(
    hasMessageHint, hasSystemMessageHint)) {
    if (mbox.setAsScheduled()) {

    executorService execute mbox


    }

    View full-size slide

  66. abstract class Mailbox
    abstract class Mailbox(
    val messageQueue: MessageQueue
    ) extends ForkJoinTask[Unit]
    with SystemMessageQueue
    with Runnable {
    ...
    }

    View full-size slide

  67. ForkJoinTask

    View full-size slide

  68. ForkJoinTask
    join()
    join()
    fork()
    fork()

    View full-size slide

  69. ForkJoinTask
    join()
    join()
    fork()
    fork()
    Α͘ݟΔਤ

    View full-size slide

  70. ForkJoinTask
    join()
    join()
    fork()
    fork()

    View full-size slide

  71. Fork΋Join΋͠ͳ͍
    ForkJoinTask

    View full-size slide

  72. Fork΋Join΋͠ͳ͍ͳΒ
    ͳΜͰForkJoinTaskʁ

    View full-size slide

  73. ౴͑ύϑΥʔϚϯε

    View full-size slide

  74. Class ForkJoinTask

    View full-size slide

  75. Class ForkJoinTask

    View full-size slide

  76. Class ForkJoinPool

    View full-size slide

  77. Class ForkJoinPool

    View full-size slide

  78. AkkaͷچΦϑΟγϟϧϒϩά
    LET IT CRASH blog

    View full-size slide

  79. Scalability of Fork Join Pool
    LET IT CRASH blog 2012

    View full-size slide

  80. LET IT CRASH blog 2012

    View full-size slide

  81. ʮAkkaͷϕϯνϚʔΫऔΖ͏ͥʯ
    LET IT CRASH blog 2012

    View full-size slide

  82. ʮ΋͏Ϛγϯങͬͨʯ
    LET IT CRASH blog 2012

    View full-size slide

  83. LET IT CRASH blog 2012

    View full-size slide

  84. LET IT CRASH blog 2012
    ʮͰ͔ͬʂ$16ίΞ͍ͭ͋͘Δͷʁʯ

    View full-size slide

  85. ʮʯ
    LET IT CRASH blog 2012

    View full-size slide

  86. ʮ",#͔ΑXXXʯ
    LET IT CRASH blog 2012

    View full-size slide

  87. ʮϕϯν૸ΒͤΔΑʔʂʂʯ
    LET IT CRASH blog 2012
    ·Ͱݟࣄʹεέʔϧ͢ΔͰ͠ΐ

    View full-size slide

  88. LET IT CRASH blog 2012

    View full-size slide

  89. LET IT CRASH blog 2012
    ʂʁʁʁ

    View full-size slide

  90. LET IT CRASH blog 2012
    ·Ͱεέʔϧ͠ͳ͍ͷʂʁʁ

    View full-size slide

  91. LET IT CRASH blog 2012

    View full-size slide

  92. LET IT CRASH blog 2012

    View full-size slide

  93. LET IT CRASH blog 2012

    View full-size slide

  94. LET IT CRASH blog 2012
    7JLUPSݱ%FQVUZ ෭ʁ
    $50BU-JHIUCFOE

    View full-size slide

  95. LET IT CRASH blog 2012

    View full-size slide

  96. LET IT CRASH blog 2012
    %PVH-FB

    View full-size slide

  97. https://en.wikipedia.org/wiki/Doug_Lea

    View full-size slide

  98. https://en.wikipedia.org/wiki/Doug_Lea

    View full-size slide

  99. +BWBͷGPSLKPJO
    ࡞ͬͨਓ

    View full-size slide

  100. LET IT CRASH blog 2012
    … resulted in improved implementation
    of fork join pool
    … randomized queing and stealing

    View full-size slide

  101. LET IT CRASH blog 2012

    View full-size slide

  102. LET IT CRASH blog 2012
    ۙ͘·Ͱ
    ΄ͲΑ͘εέʔϧ

    View full-size slide

  103. ͔ͩΒForkJoinPool͕
    "LLBDispatcherͷσϑΥϧτ

    View full-size slide

  104. receiverଆͷ
    ࿩͠ʹ໭Γ·͢

    View full-size slide

  105. abstract class Mailbox
    abstract class Mailbox(
    val messageQueue: MessageQueue
    ) extends ForkJoinTask[Unit]
    with SystemMessageQueue
    with Runnable {
    ...
    }
    ExecutorServiceͷ
    executeϝιουΛ࢖͏ͱ
    Runnableͷrunϝιου͕ݺ͹ΕΔ

    View full-size slide

  106. abstract class Mailbox
    override final def run(): Unit = {
    try {
    if (!isClosed) { //Volatile read, needed here
    processAllSystemMessages() //First, deal with any system messages
    processMailbox() //Then deal with messages
    }
    } finally {
    setAsIdle() //Volatile write, needed here
    dispatcher.registerForExecution(this, false, false)
    }
    }

    View full-size slide

  107. abstract class Mailbox
    override final def run(): Unit = {
    try {
    if (!isClosed) { //Volatile read, needed here
    processAllSystemMessages() //First, deal with any system messages
    processMailbox() //Then deal with messages
    }
    } finally {
    setAsIdle() //Volatile write, needed here
    dispatcher.registerForExecution(this, false, false)
    }
    }

    View full-size slide

  108. abstract class Mailbox
    @tailrec private final def processMailbox(
    left: Int = java.lang.Math.max(dispatcher.throughput, 1),
    deadlineNs: Long = …): Unit =
    if (shouldProcessMessage) {
    val next = dequeue()
    if (next ne null) {

    actor invoke next

    processMailbox(left - 1, deadlineNs)
    }
    }

    View full-size slide

  109. abstract class Mailbox
    @tailrec private final def processMailbox(
    left: Int = java.lang.Math.max(dispatcher.throughput, 1),
    deadlineNs: Long = …): Unit =
    if (shouldProcessMessage) {
    val next = dequeue()
    if (next ne null) {

    actor invoke next

    processMailbox(left - 1, deadlineNs)
    }
    }

    View full-size slide

  110. abstract class Mailbox
    @tailrec private final def processMailbox(
    left: Int = java.lang.Math.max(dispatcher.throughput, 1),
    deadlineNs: Long = …): Unit =
    if (shouldProcessMessage) {
    val next = dequeue()
    if (next ne null) {

    actor invoke next

    processMailbox(left - 1, deadlineNs)
    }
    }
    //receiveϝιουΛݺͿ
    class MyActor extends Actor {
    def receive = {

    }
    }

    View full-size slide

  111. abstract class Mailbox
    @tailrec private final def processMailbox(
    left: Int = java.lang.Math.max(dispatcher.throughput, 1),
    deadlineNs: Long = …): Unit =
    if (shouldProcessMessage) {
    val next = dequeue()
    if (next ne null) {

    actor invoke next

    processMailbox(left - 1, deadlineNs)
    }
    }

    View full-size slide

  112. recursive
    processMailbox()
    ͳͥʁʁ

    View full-size slide

  113. ෆཁͳεϨου੾Γସ͑Λ๷͙

    View full-size slide


  114. ճͷrunͰͭͷϝοηʔδΛϓϩηε

    View full-size slide

  115. MessageQueueʹϝοηʔδ͋ͬͨΒ
    ಉ͡εϨου͕ԆʑͱprocessMailbox

    View full-size slide

  116. ͦ͏͡Όͳ͍

    View full-size slide

  117. rerence.conf
    # Throughput defines the number of messages
    # that are processed in a batch
    # before the thread is returned to the pool.
    # Set to 1 for as fair as possible.
    throughput = 5

    View full-size slide

  118. abstract class Mailbox
    @tailrec private final def processMailbox(
    left: Int = java.lang.Math.max(dispatcher.throughput, 1),
    deadlineNs: Long = …): Unit =
    if (shouldProcessMessage) {
    val next = dequeue()
    if (next ne null) {

    actor invoke next

    processMailbox(left - 1, deadlineNs)
    }
    }

    View full-size slide

  119. σϑΥϧτͰͭ·Ͱ͔͠
    ࿈ଓͰϝοηʔδΛॲཧ͠ͳ͍

    View full-size slide

  120. receiverଆ΋ऴΘͬͨ

    View full-size slide

  121. શମͷ͓͞Β͍

    View full-size slide

  122. "DUPSʹΑΔ
    ϝοηʔδύογϯά
    "LLB

    View full-size slide

  123. ௿Ϩϕϧ͔ΒݟΔͱ

    View full-size slide

  124. ͞Βʹ௿Ϩϕϧ͔ΒݟΔͱ

    View full-size slide

  125. +BWBͷ'PSL+PJO5BTLΛ
    ܁Γฦ͠FYFDVUF͢Δ
    ΞϓϦέʔγϣϯ
    "LLB

    View full-size slide