$30 off During Our Annual Pro Sale. View Details »

Scalaでの並行・並列処理戦略/strategy-for-concurrency-and-parallel-by-scala

fuzyco
November 10, 2018

 Scalaでの並行・並列処理戦略/strategy-for-concurrency-and-parallel-by-scala

Scala関西サミット2018で発表したスライドです。

fuzyco

November 10, 2018
Tweet

More Decks by fuzyco

Other Decks in Technology

Transcript

  1. ScalaͰͷ
    ฒߦɾฒྻॲཧઓུ
    Scalaؔ੢Summit 2018
    ౻໺޺थ

    View Slide

  2. ࣗݾ঺հ

    • ౻໺޺थ
    • αʔόʔαΠυΤϯδχΞ@Fringe81
    • Scalaྺ2೥
    • ਓੜॳͷେࡕ

    View Slide

  3. Ϟνϕʔγϣϯ

    Scala͸ฒߦɾฒྻॲཧΛߦ͏ͨΊͷϥΠϒϥϦ͕๛෋ʁ

    View Slide

  4. Ϟνϕʔγϣϯ

    Scala͸ฒߦɾฒྻॲཧΛߦ͏ͨΊͷϥΠϒϥϦ͕๛෋ʁ
    ‣ ฒߦɾฒྻॲཧΛ࣮ݱ͢ΔϥΠϒϥϦ
    •ඪ४ϥΠϒϥϦ
    •Future
    •ฒྻίϨΫγϣϯ
    •ϥΠϒϥϦ
    •Akka Actor
    •Monix

    View Slide

  5. Ϟνϕʔγϣϯ

    Scala͸ฒߦɾฒྻॲཧΛߦ͏ͨΊͷϥΠϒϥϦ͕๛෋ʁ
    ‣ ฒߦɾฒྻॲཧΛ࣮ݱ͢ΔϥΠϒϥϦ
    •ඪ४ϥΠϒϥϦ
    •Future
    •ฒྻίϨΫγϣϯ
    •ϥΠϒϥϦ
    •Akka Actor
    •Monix
    Ͳ͏࢖͍෼͚Δͷ͔
    Θ͔Βͳ͍

    View Slide

  6. ScalaͷϥΠϒϥϦ͸ศར

    தͷ࢓૊ΈͳͲΛߟ͑ͳͯ͘΋ͱΓ͋͑ͣ؆୯ʹ࢖͑Δ
    Future => Future.apply͢Ε͹ผεϨουͰॲཧ͕૸Δ
    Akka Actor => ඇಉظϝοηʔδύογϯά͕Ͱ͖Δ
    ฒྻίϨΫγϣϯ => .par͢Ε͹ฒྻॲཧ͕Ͱ͖Δ

    View Slide

  7. ى͖Δࣄ৅

    •Future಺ͰThread.sleep͢ΔͱɺεϨουރׇͨ͠
    •͜ͷॲཧAkka ActorͱFutureͲͬͪͰ΍Δ΂͖ͳͷ͔Θ͔Βͳ͍
    •ฒྻίϨΫγϣϯ࢖ͬͨΒٯʹ஗͘ͳͬͨ
    ͱΓ͋͑ͣ࢖͏͚ͩ͸ྑ͘ͳͦ͞͏

    View Slide

  8. ग़ͯ͘Δٙ໰

    w 'VUVSFʹ͸*NQMJDJUTHMPCBMΛ౉͓͚ͯ͠͹͍͍ͷ͔ʁ
    w ͱΓ͋͑ͣ"LLB"DUPS࢖͑͹͍͍ͷ͔ʁ
    w ฒྻίϨΫγϣϯ࢖͏ͱ଎͘ͳΔέʔεͱ͸ʁ
    w ඇಉظॲཧͰΑ͘ग़ͯ͘Δ&YFDVUJPO$POUFYUͬͯԿͳͷʁ
    ࢓૊ΈΛཧղ͢Ε͹ΑΓΑ͍׆༻͕Ͱ͖Δ

    View Slide

  9. ൃද಺༰

    ࿩͢͜ͱ
    ࿩͞ͳ͍͜ͱ
    • ScalaͷฒߦɾฒྻॲཧϥΠϒϥϦ
    •ಛ௃
    •࢓૊Έ
    •Ϣʔεέʔε
    •ϥΠϒϥϦͷࡉ͔͍࢓༷/tips
    •௿ϨΠϠͷ࿩(OSϨϕϧ)
    •ύϑΥʔϚϯενϡʔχϯά

    View Slide

  10. ຊൃදͷΰʔϧ

    FutureɺAkka ActorͳͲͷฒߦɾฒྻϥΠϒϥϦͷಛ௃ɾ࢓૊ΈΛ
    ཧղɺ੔ཧͯ͠ΑΓ҆શͰ଎͍γεςϜ࡞Γͷॿ͚ʹͳΕ͹޾͍Ͱ͢

    View Slide

  11. ͓඼ॻ͖

    • ฒߦɾฒྻॲཧͱ͸
    • ScalaͷฒߦɾฒྻϥΠϒϥϦ
    • ExecutionContextʹ͍ͭͯ
    • ·ͱΊ

    View Slide

  12. ͓඼ॻ͖

    • ฒߦɾฒྻॲཧͱ͸
    • ScalaͷฒߦɾฒྻϥΠϒϥϦ
    • ExecutionContextʹ͍ͭͯ
    • ·ͱΊ

    View Slide

  13. ྺ࢙తഎܠ

    ूੵճ࿏্ͷτϥϯδελ਺͸ʮ18͔݄ʢ=1.5೥ʣ͝ͱʹഒʹͳΔʯ
    Կ΋͠ͳͯ͘΋ϓϩάϥϜ͕଎͘ͳ͍ͬͯ͘
    ϜʔΞͷ๏ଇ
    [Ҿ༻: https://ja.wikipedia.org/wiki/%E3%83%A0%E3%83%BC%E3%82%A2%E3%81%AE%E6%B3%95%E5%89%87]

    View Slide

  14. ྺ࢙తഎܠ

    ๏ଇʹԊͬͯCPUͷॲཧੑೳ্͕͕Βͳ͘ͳͬͨ
    “The Free Lunch Is Over”
    Կ΋͠ͳͯ͘΋ϓϩάϥϜ͕଎͘ͳΒͳ͍
    ϚϧνίΞCPUΛ׆༻ͨ͠ฒߦɾฒྻॲཧ͕ඞཁ
    ϜʔΞͷ๏ଇͷ่յ

    View Slide

  15. ϚϧνίΞCPUΛ׆༻ͨ͠
    ฒߦɾฒྻॲཧ

    CPU
    CPU1
    CPU2
    ҰͭͷCPU͕εϨουΛ੾Γସ͑ͳ͕Βෳ਺ͷλεΫΛ࣮ߦ͢Δ
    εϨουΛCPUͷίΞʹ౰ͯͯɺಉ࣌ʹλεΫΛ࣮ߦ͢Δ
    ฒߦॲཧ(concurrent)
    ฒྻॲཧ(parallel)
    εϨου1
    εϨου2
    ࣌ؒ
    ࣌ؒ
    ※ฒߦ͸ฒྻΛแؚ͢Δ

    View Slide

  16. ฒߦɾฒྻॲཧͷ೉͠͞

    • εϨουηʔϑ͕ٻΊΒΕΔ
    • σʔλڝ߹ʢϨʔείϯσΟγϣϯʣ
    • σουϩοΫ
    • εϨουੜ੒ɺ؅ཧͷίετ

    View Slide

  17. σʔλڝ߹ʢϨʔείϯσΟγϣϯʣ

    ෳ਺ͷεϨου͔ΒಉҰϦιʔεʹΞΫηε͢Δͱɺ
    ༧ظ͠ͳ͍ঢ়ଶ(σʔλڝ߹)ʹͳΔ͜ͱ͕͋Δ
    λΠϛϯάͷ໰୊Ͱى͖ΔͷͰɺ࠶ݱ͢Δͷ͕೉͍͠
    εϨου̍ εϨου2
    ޱ࠲࢒ߴ
    10000
    ࢒ߴ֬ೝ
    -8000
    -5000
    ޱ࠲࢒ߴ
    -3000
    OK
    ࢒ߴ֬ೝ
    OK

    View Slide

  18. ϩοΫػߏ

    σʔλڝ߹Λͳͨ͘͢Ίʹڞ༗Ϧιʔεʹରͯ͠
    ϩοΫΛͯ͠ಉظΛߦ͏
    •ೋͭͷεϨου͕͓ޓ͍ʹϩοΫͷղ์Λ଴ͪଓ͚ΔʢσουϩοΫʣ
    •ϩοΫΛ෇͚๨ΕΔ
    •ա৒ͳϩοΫΛߦ͏͜ͱʹΑΔεϧʔϓοτͷ௿Լ
    ϓϩάϥϚʔ͕৭ʑؤுΒͳ͍ͱ͍͚ͳ͍

    View Slide

  19. Scalaʹ͸
    ฒߦɾฒྻॲཧͷ೉఺Λαϙʔτ͢Δ
    ϥΠϒϥϦ͕͍͔ͭ͘ଘࡏ͠·͢

    View Slide

  20. ͓඼ॻ͖

    • ฒߦɾฒྻॲཧͱ͸
    • ScalaͷฒߦɾฒྻϥΠϒϥϦ
    • ExecutionContextʹ͍ͭͯ
    • ·ͱΊ

    View Slide


  21. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]

    View Slide


  22. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]
    ద༻ൣғ͕૿͍ͯ͘͠

    View Slide


  23. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]
    ద༻ൣғ͕૿͍ͯ͘͠
    ίϨΫγϣϯʹ
    ର͢Δฒྻॲཧ ঢ়ଶΛ࣋ͨͳ͍
    ฒߦॲཧ
    ঢ়ଶΛ࣋ͬͨ
    ฒߦॲཧ

    View Slide


  24. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]
    ίϨΫγϣϯʹ
    ର͢Δฒྻॲཧ

    View Slide

  25. ScalaฒྻίϨΫγϣϯ

    • ฒྻॲཧΛ࣮ݱ͢ΔίϨΫγϣϯϥΠϒϥϦ
    • Scala2.9͔Βಋೖ͞Εͨ

    View Slide

  26. ScalaίϨΫγϣϯ

    ɾList, Array, etc.
    scala> val list = (1 to 10000).toList
    list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, …
    scala> list.map(_ + 42)
    res0: List[Int] = List(43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, …
    scala> list.max
    res1: Int = 10000

    View Slide

  27. ScalaฒྻίϨΫγϣϯ

    ίϨΫγϣϯͷԋࢉΛฒྻʹ࣮ߦ͢Δ͜ͱ͕Ͱ͖Δ
    scala> val parList = list.par
    parList: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3, 4, 5, …)
    scala> parList.seq
    res1: scala.collection.immutable.Seq[Int] = Vector(1, 2, 3, 4, 5, 6, … )
    ม׵͕Մೳ
    scala> parList.foreach(elm => print(s"$elm "))
    376 377 501 813 876 2 …
    ฒྻʹॲཧ͕࣮ߦ͞ΕΔ

    View Slide

  28. ScalaฒྻίϨΫγϣϯ

    import scala.util.Random
    val numbers = Random.shuffle(Vector.tabulate(10000000)(i => i))
    val seqtime = measure { numbers.max }
    log(s"Sequential time ${seqtime.value} ms”)
    val partime = measure { numbers.par.max }
    log(s"Parallel time ${partime.value} ms")
    Sequential time 535.850688 ms
    Parallel time 193.393754 ms
    parϝιουΛ࢖͚ͬͨͩͰ
    ฒྻʹॲཧ͕ߦΘΕΔ
    ϥϯμϜͳ஋ͷཁૉΛ10000000ݸ࣋ͭVectorͷ
    ࠷େͷཁૉΛٻΊΔϓϩάϥϜ

    View Slide

  29. ฒྻॲཧ

    ฒྻԽͰ͖ΔλεΫΛׂΓग़ͯ͠ɺ
    ޮ཰Α͘෼ׂͯ͠ฒྻʹ࣮ߦ͢Δඞཁ͕͋Δ
    ΞϜμʔϧͷ๏ଇ
    ฒྻίϨΫγϣϯ͸಺෦Ͱ෼ׂ౷࣏ͷΞϓϩʔνʹج͍ͮͯίϨΫγϣϯΛ
    ޮ཰Α͘෼ׂͯ͠ฒྻʹԋࢉΛߦ͏

    View Slide

  30. ෼ׂ౷࣏๏

    ໰୊Λ෼ׂͯ͠ɺͦΕͧΕಠཱͯ͠ࢉग़͞ΕͨղΛ
    ౷߹͍ͯ͘͠Ξϓϩʔν(ྫ: Ϛʔδιʔτ)
    ෦෼
    ղ
    ղ
    ෦෼
    ղ
    ෦෼
    ղ
    ෦෼
    ղ
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊

    View Slide

  31. ෼ׂ౷࣏

    ໰୊Λ෼ׂͯ͠ɺͦΕͧΕಠཱͯ͠ࢉग़͞ΕͨղΛ
    ౷߹͍ͯ͘͠Ξϓϩʔν(ྫ: Ϛʔδιʔτ)
    ෦෼
    ղ
    ղ
    ෦෼
    ղ
    ෦෼
    ղ
    ෦෼
    ղ
    ฒྻԽՄೳ
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊
    ෦෼
    ໰୊

    View Slide

  32. ෼ׂ౷࣏

    ߹ܭ஋
    શମͷ
    ߹ܭ஋
    ߹ܭ஋
    ߹ܭ஋
    ߹ܭ஋
    ֤CPUͰฒྻʹ࣮ߦ
    "SSBZ
    ෼ׂ͞Εͨ഑ྻ
    ͷ߹ܭ஋ͷܭࢉ
    sumϝιουݺͼग़͠ʹΑΔίϨΫγϣϯͷ߹ܭ஋ͷܭࢉ
    ArrayΛεϨου
    ͷ਺͚ͩ෼ׂ
    ͦΕͧΕͷ߹ܭ஋
    Λ଍͠߹ΘͤΔ
    ෼ׂ͞Εͨ഑ྻ
    ͷ߹ܭ஋ͷܭࢉ
    ෼ׂ͞Εͨ഑ྻ
    ͷ߹ܭ஋ͷܭࢉ
    ෼ׂ͞Εͨ഑ྻ
    ͷ߹ܭ஋ͷܭࢉ

    View Slide

  33. ෼ׂ౷࣏

    ෼ׂ౷࣏͸ɺ෼ׂ͞ΕͨλεΫ͕ಠཱͯ͠
    ࣮ߦͰ͖Δܭࢉʹ޲͘
    •ݕࡧ/બ୒ => ෼ׂ͞Εͨ୯ҐͰݕࡧ/બ୒Մೳ
    •ιʔτ => ෼ׂ͞ΕͨλεΫ୯ҐͰιʔτՄೳ
    •ूܭ => ෼ׂ͞ΕͨλεΫ୯ҐͰूܭՄೳ

    View Slide

  34. ฒྻίϨΫγϣϯͷ࢓૊Έ

    Splitter
    ෼ׂ౷࣏Λ࣮ݱ͍ͯ͠ΔΦϒδΣΫτ
    trait IterableSplitter[T] extends Iterator[T] {
    def dup: IterableSplitter[T]
    def remaining: Int
    def split: Seq[IterableSplitter[T]]
    }
    ίϨΫγϣϯΛޮ཰Α͘෼ׂ͢Δ
    Combiner
    trait Combiner[-Elem, +To] extends Builder[Elem, To] with Sizing with Parallel {
    def combine[N <: Elem, NewTo >: To](other: Combiner[N, NewTo]): Combiner[N, NewTo]
    }
    ෼ׂ͞ΕͨλεΫͷԋࢉ݁ՌΛ݁߹͢Δ

    View Slide

  35. ฒྻίϨΫγϣϯϋϚΓϙΠϯτ

    • ଎౓͕͕͋Δͱ͸ݶΒͳ͍
    • ૝ఆ͍ͯͨ͠ܭࢉ݁ՌʹͳΒͳ͍
    Ϣʔεέʔε͕ݶఆ͞ΕΔ෼ɺޡͬͨ࢖͍ํ͕ଘࡏ͢Δ

    View Slide

  36. ଎౓͕͕͋Δͱ͸ݶΒͳ͍

    • εϨουؒͷಉظॲཧ(σʔλڝ߹)
    • ฒྻίϨΫγϣϯ΁ͷม׵ίετ

    View Slide

  37. εϨουؒͷಉظॲཧ
    (σʔλڝ߹)

    object ParUid extends App {
    private val uid = new AtomicLong(0L)
    val seqtime = measure {
    for(i <- 0 until 10000000) uid.incrementAndGet()
    }
    println(s"Sequential time ${seqtime.value} ms”)
    val partime = measure {
    for(i <- (0 until 10000000).par) uid.incrementAndGet()
    }
    println(s"Parallel time ${partime.value} ms")
    }
    ※measureؔ਺͸ScalaMeterͷॲཧ࣌ؒΛܭଌ͢Δؔ਺
    uidΛAtomicม਺Ͱ҆શͳಉظΛ
    ߦͬͯΧ΢ϯτΞοϓ͍ͯ͠Δ
    ϧʔϓॲཧͰΧ΢ϯτΞοϓ͢ΔϓϩάϥϜ

    View Slide

  38. εϨουؒͷಉظॲཧ
    (σʔλڝ߹)

    4FRVFOUJBMUJNFNT
    1BSBMMFMUJNFNT
    object ParUid extends App {
    private val uid = new AtomicLong(0L)
    val seqtime = measure {
    for(i <- 0 until 10000000) uid.incrementAndGet()
    }
    println(s"Sequential time ${seqtime.value} ms”)
    val partime = measure {
    for(i <- (0 until 10000000).par) uid.incrementAndGet()
    }
    println(s"Parallel time $partime ms")
    }
    ฒྻίϨΫγϣϯΛ࢖ͬͨ΄͏͕
    ͕͔͔͍࣌ؒͬͯΔ
    εϨουؒͰσʔλΛਖ਼͘͠ڞ༗͢ΔͨΊʹಉظΛߦ͏ͷͰɺ
    ֤εϨουͰॲཧ଴͕ͪൃੜͯ͠εϧʔϓοτ͕௿Լ͢Δ

    View Slide

  39. ฒྻίϨΫγϣϯ΁ͷม׵ίετ

    ListͱVectorΛͦΕͧΕ
    ฒྻίϨΫγϣϯʹม׵͢ΔϓϩάϥϜ
    object ParNonParallelizableCollections extends App with Logger {
    val list = List.fill(1000000)("")
    val vector = Vector.fill(1000000)(“")
    println(s"list conversion time: ${measure(list.par).value} ms")
    println(s"vector conversion time: ${measure(vector.par).value} ms")
    }

    View Slide

  40. ฒྻίϨΫγϣϯ΁ͷม׵ίετ

    MJTUDPOWFSTJPOUJNFNT
    WFDUPSDPOWFSTJPOUJNFNT
    ListͱVectorΛͦΕͧΕ
    ฒྻίϨΫγϣϯʹม׵͢ΔϓϩάϥϜ
    object ParNonParallelizableCollections extends App with Logger {
    val list = List.fill(1000000)("")
    val vector = Vector.fill(1000000)(“")
    println(s"list conversion time: ${measure(list.par).value} ms")
    println(s"vector conversion time: ${measure(vector.par).value} ms")
    } ListͷฒߦίϨΫγϣϯ΁ͷม׵
    ʹ͔ͳΓ͕͔͔͍࣌ؒͬͯΔ

    View Slide

  41. ฒྻίϨΫγϣϯ΁ͷม׵ίετ

    ฒྻίϨΫγϣϯͷ࣮૷
    Λ࣌ͨͳ͍ίϨΫγϣϯ
    ฒྻίϨΫγϣϯͷ࣮૷
    Λ࣋ͭίϨΫγϣϯ
    ฒྻίϨΫγϣϯ
    List Vector ParVector
    scala> (1 to 10000).toList.par
    res2: ParVector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, …

    View Slide

  42. ฒྻίϨΫγϣϯ΁ͷม׵ίετ

    List Vector ParVector
    scala> (1 to 10000).toList.par
    res2: ParVector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, …
    શͯͷཁૉΛίϐʔ͢ΔͷͰܭࢉίετ͕͔͔Δ
    ฒྻίϨΫγϣϯͷ࣮૷
    Λ࣌ͨͳ͍ίϨΫγϣϯ
    ฒྻίϨΫγϣϯͷ࣮૷
    Λ࣋ͭίϨΫγϣϯ
    ฒྻίϨΫγϣϯ

    View Slide

  43. ฒྻίϨΫγϣϯͷ࣮૷Λ࣋ͭ
    ίϨΫγϣϯ

    ্هҎ֎ͷίϨΫγϣϯͷฒྻίϨΫγϣϯ΁ͷ
    ม׵͸͕͔͔࣌ؒΔ
    •Array
    •ArrayBuffer
    •Vector
    •mutable.HashMap
    •immutable.HashMap
    •Range
    •mutable.HashSet
    •immutable.HashSet
    •concurrent.TrieMap

    View Slide

  44. ૝ఆ͍ͯͨ͠ܭࢉ݁ՌʹͳΒͳ͍

    • ঢ়ଶΛѻ͏ԋࢉ
    • ݁߹ଈ͕੒ཱ͠ͳ͍ԋࢉ

    View Slide

  45. ঢ়ଶΛѻ͏ԋࢉ

    scala> var sum = 0
    sum: Int = 0
    scala> val parList = (1 to 1000).toList.par
    parList: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3, 4, 5, …
    scala> var sum = 0
    sum: Int = 0
    scala> parList.foreach(sum += _); sum
    res01: Int = 307792
    scala> parList.foreach(sum += _); sum
    res02: Int = 417753

    View Slide

  46. ঢ়ଶΛѻ͏ԋࢉ

    ద੾ʹಉظΛऔΔͱࠓ౓͸ॲཧ଎౓͕٘ਜ਼ʹͳΔ
    ಺෦Ͱঢ়ଶΛѻ͏ԋࢉ͸ద੾ʹಉظΛऔΒͳ͚Ε͹ͳΒͳ͍ɹ
    ฒྻίϨΫγϣϯ͸֤λεΫͰ७ਮͳܭࢉΛ͢Δ΂͖

    View Slide

  47. ݁߹ଇ͕੒Γཱͨͳ͍ԋࢉ

    ฒྻͰ࣮ߦ͞ΕΔͷͰɺ݁߹཯͕੒Γཱͨͳ͍ԋࢉ͸ႈ౳ͳ஋ʹͳΒͳ͍
    ྫ: (1-2)-3 != 1-(2-3)
    scala> val parList = (1 to 1000).toList.par
    parList: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3, 4, 5, …
    scala> parList.reduce(_ - _)
    res0: Int = -169948
    scala> parList.reduce(_ - _)
    res1: Int = 181648

    View Slide

  48. ฒྻCollection·ͱΊ

    • ฒྻίϨΫγϣϯ͸ιʔτɺݕࡧɺબ୒ɺूܭʹ޲͘
    • ฒྻίϨΫγϣϯ಺ͰಉظॲཧΛߦ͏ͱࢥ͏Α͏ʹ଎͘
    ͳΒͳ͍
    • ฒྻίϨΫγϣϯͷ࣮૷Λ࣋ͨͳ͍ίϨΫγϣϯΛฒྻ
    ίϨΫγϣϯʹม׵͢Δͱࢥ͏Α͏ʹ଎͘ͳΒͳ͍
    • ঢ়ଶΛѻ͏ԋࢉ΍݁߹ଇ͕੒Γཱͨͳ͍ԋࢉͰ͸ඇܾఆ
    ੑʹͭͳ͕ΔՄೳੑ͕͋Δ

    View Slide


  49. ฒྻCollectionͰIOॲཧ
    val userIds: List[String] = List("id")
    def findUser(userId: String): User = {
    database.findUser(userId)
    }
    val users = userIds.par.map { userId =>
    findUser(userId)
    }
    CPU1 IO଴ͪ
    CPU2 IO଴ͪ
    ฒྻίϨΫγϣϯ಺ͰIOό΢ϯυͳॲཧΛߦ͏ͱɺ
    IO଴ͪͷؒશͯͷCPUͷॲཧ͕ఀࢭͯ͠͠·͏
    DB΁ͷ
    ΞΫηε

    View Slide


  50. Future
    IOό΢ϯυͳॲཧʹ͓͍ͯ͸ɺ
    1CPU಺Ͱෳ਺ͷεϨουΛ੾Γସ͑ͯฒߦʹ࣮ߦ͢Δํ͕ޮ཰͕ྑ͍
    ※ਤ͸ཧ૝Ͱ͋Γɺ
    ࣮ࡍ͸OSͷεέδϡʔϥ͕εϨουΛׂΓ౰ͯΔͷͰ
    ͜ͷΑ͏ʹ៉ྷʹׂΓ౰ͯΒΕΔͱ͸ݶΒͳ͍
    CPU1 IO଴ͪ
    CPU2 IO଴ͪ
    CPU1
    εϨου1
    εϨου2
    IO଴ͪ
    CPU2
    εϨου3
    εϨου4
    IO଴ͪ

    View Slide


  51. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]
    ঢ়ଶΛ࣋ͨͳ͍
    ฒߦॲཧ

    View Slide

  52. Future

    ඇಉظॲཧΛ࣮ݱ͢Δඪ४ϥΠϒϥϦ
    •಺෦ͰεϨουϓʔϧΛ༻͍ͨඇಉظॲཧͷ࣮ݱ
    •εϨουͷ؅ཧɺׂΓ౰ͯΛҙࣝ͠ͳ͍
    •ϓϩάϥϚ͸ඇಉظʹ࣮ߦ͍ͨ͠λεΫʹूதͰ͖Δ
    •mapɺflatMapʹΑΔ߹੒Մೳੑ

    View Slide

  53. Future

    import scala.concurrent.Future
    import scala.concurrent.ExecutionContext.Implicits.global
    object FutureSample extends App {
    Future {
    println(s"[ThreadName] In Future: ${Thread.currentThread.getName}")
    println(1)
    }
    println(s"[ThreadName] In Main: ${Thread.currentThread.getName}")
    println(2)
    }
    Future.applyͰғΉͱɺผεϨουͰඇಉظॲཧ͕૸Δ
    [ThreadName] In Main: main
    2
    [ThreadName] In Future: scala-execution-context-global-11
    1
    ͜͜͸
    ผεϨου

    View Slide

  54. Future

    MainεϨου
    ผεϨου
    println(1)
    println(2)
    object FutureSample extends App {
    Future {
    println(s"[ThreadName] In Future: ${Thread.currentThread.getName}")
    println(1)
    }
    println(s"[ThreadName] In Main: ${Thread.currentThread.getName}")
    println(2)
    }
    Future.applyͰғΉͱɺผεϨουͰඇಉظॲཧ͕૸Δ

    View Slide

  55. Future

    ҰͭͷCPUͰIOॲཧͷؒʹεϨουΛ੾Γସ͑ͯଞͷ࡞ۀΛ
    CPUʹׂΓ౰ͯΔ͜ͱʹΑͬͯɺεϧʔϓοτ͕޲্͢Δ
    ※ෳ਺ͷCPU͕͋Δ৔߹͸ɺͦΕͧΕCPUͰฒྻʹ࣮ߦ͞ΕΔ͜ͱ΋͋Δ
    CPU
    CPU
    Future1
    Future2
    IO଴ͪ
    IO଴ͪ

    View Slide

  56. Futureͷ߹੒Մೳੑ

    map, flatMap
    ͋ΔεϨουͰͷඇಉظॲཧ͕੒ޭͨ͠Βɺ
    ͦͷܭࢉ݁ՌΛ࢖ͬͯผͷεϨουͰඇಉظॲཧΛ࣮ߦͰ͖ͯɺ
    ࣦഊͨ͠৔߹ʹ͸Failure(ࣦഊ)͕ฦΔ
    forࣜͰ΋ॻ͚Δ
    def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
    def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S]

    View Slide

  57. Futureͷ߹੒Մೳੑ

    map, flatMap
    def createResponse(user: User, team: Team): String
    val userF = Future { database.findUser("user1") }
    val teamF = Future { database.findTeam("team1") }
    val response = userF.flatMap { user =>
    teamF.map { team =>
    createResponse(user, team)
    }
    }
    response.foreach(println)

    View Slide

  58. Futureͷ߹੒Մೳੑ

    ෳ਺ͷεϨουͰߦΘΕ͍ͯΔ
    ॲཧಉ࢜ͷ଴ͪ߹Θͤɺ
    Τϥʔͷ࣌ͷॲཧΛॻ͘ඞཁ͕ͳ͍
    MainεϨου
    val userF val teamF val response
    Future.apply
    Future.apply
    database.findTeam
    user
    team
    response.onComplete
    flatMap
    map
    database.findUser
    def createResponse(user: User, team: Team): String
    val userF = Future { database.findUser("user1") }
    val teamF = Future { database.findTeam("team1") }
    val response = userF.flatMap { user =>
    teamF.map { team =>
    createResponse(user, team)
    }
    }
    response.foreach(println)

    View Slide

  59. Future಺Ͱͷঢ়ଶ؅ཧ

    def deposit(account: Account, amount: Int): Future[Unit] = Future {
    if(account.money - amount > 0) {
    if(amount == 8000) Thread.sleep(1000)
    account.money -= amount
    } else {
    println(s"Insufficient funds (${account.money} < ${amount})")
    }
    }
    val account = new Account("Jack", 10000)
    val result1 = deposit(account, 8000)
    val result2 = deposit(account, 5000)
    Await.ready(Future.sequence(List(result1, result2)), Duration.Inf)
    println(s"jack's money: ${account.money}")
    jack's money: -3000
    ϒϩοΫॲཧ
    ඇಉظʹAccountΦϒδΣΫτʹΞΫηε͢ΔϓϩάϥϜ

    View Slide

  60. Future಺Ͱͷঢ়ଶ؅ཧ

    jack's money: -3000
    def deposit(account: Account, amount: Int): Future[Unit] = Future {
    if(account.money - amount > 0) {
    if(amount == 8000) Thread.sleep(1000)
    account.money -= amount
    } else {
    println(s"Insufficient funds (${account.money} < ${amount})")
    }
    }
    val account = new Account("Jack", 10000)
    val result1 = deposit(account, 8000)
    val result2 = deposit(account, 5000)
    Await.ready(Future.sequence(List(result1, result2)), Duration.Inf)
    println(s"jack's money: ${account.money}")
    ॲཧ͕ϒϩοΫ͞Ε͍ͯΔؒʹɺ
    ผͷεϨου͔ΒAccountΦϒδΣΫτʹ
    ΞΫηε͞Εͯ͠·͏

    View Slide

  61. Future಺Ͱͷঢ়ଶ؅ཧ

    Insufficient funds (5000 < 8000)
    jack's money: 5000
    def deposit(account: Account, amount: Int): Future[Unit] = Future {
    account.synchronized {
    if (account.money - amount > 0) {
    if (amount == 8000) Thread.sleep(1000)
    account.money -= amount
    } else {
    println(s"Insufficient funds (${account.money} < ${amount})")
    }
    }
    }
    val account = new Account("Jack", 10000)
    val result1 = deposit(account, 8000)
    val result2 = deposit(account, 5000)
    Await.ready(Future.sequence(List(result1, result2)), Duration.Inf)
    println(s"jack's money: ${account.money}")
    ϩοΫΛ༻͍ͯಉظ

    View Slide

  62. Future಺Ͱͷঢ়ଶ؅ཧ

    Insufficient funds (5000 < 8000)
    jack's money: 5000
    def deposit(account: Account, amount: Int): Future[Unit] = Future {
    account.synchronized {
    if (account.money - amount > 0) {
    if (amount == 8000) Thread.sleep(1000)
    account.money -= amount
    } else {
    println(s"Insufficient funds (${account.money} < ${amount})")
    }
    }
    }
    val account = new Account("Jack", 10000)
    val result1 = deposit(account, 8000)
    val result2 = deposit(account, 5000)
    Await.ready(Future.sequence(List(result1, result2)), Duration.Inf)
    println(s"jack's money: ${account.money}")
    ϩοΫΛ༻͍ͯಉظ
    σουϩοΫͷةݥੑ
    ա৒ͳϩοΫʹΑΔύϑΥʔϚϯεͷ௿Լ

    View Slide


  63. ෦෼తʹඇಉظॲཧΛ࣮૷͢Δ͚ͩͳΒɺ
    FutureΛ࢖͑͹࣮ݱͰ͖Δ
    ಺෦ʹঢ়ଶΛ࣋ͭ৔߹͸ɺಉظΛऔΔඞཁ͕ग़ͯདྷͯ͠·͏
    ϩοΫΛ࢖Θͣʹ҆શʹ಺෦ঢ়ଶʹΞΫηε͍ͨ͠
    Akka Actor

    View Slide


  64. ࠓճ঺հ͢ΔϥΠϒϥϦ
    [Ҿ༻: http://spray.io/duse/#/5]
    ঢ়ଶΛ࣋ͬͨ
    ฒߦॲཧ

    View Slide

  65. Akka Actor

    • ScalaͱJavaͷApach2ϥΠηϯεͰఏڙ͞Ε͍ͯΔOSSϥ
    ΠϒϥϦ
    • ΞΫλʔϞσϧΛద༻ͨ͠ϥΠϒϥϦ

    View Slide

  66. ΞΫλʔϞσϧ

    ΞΫλʔϞσϧ͸
    ʮ਺ඦɾ਺ઍͷϚΠΫϩϓϩηοα͔Βߏ੒͞Εɺ
    ݸʑʹϩʔΧϧϝϞϦΛ࣋ͪɺ
    ߴੑೳ௨৴ωοτϫʔΫͰ௨৴Λߦ͏
    ฒྻίϯϐϡʔλ͕͍ۙকདྷొ৔͢Δͱͷ༧ଌʯ
    ͔Β։ൃ͞Εͨ
    [Ҿ༻: https://ja.wikipedia.org/wiki/
    %E3%82%A2%E3%82%AF%E3%82%BF%E3%83%BC%E3%83%A2%E3%83%87%E3%83%AB]

    View Slide

  67. ΞΫλʔϞσϧ

    ΦϒδΣΫτࢦ޲
    ΞΫλʔࢦ޲
    • શͯ͸ΦϒδΣΫτ
    • ঢ়ଶͷΧϓηϧԽ
    • ৼΔ෣͍
    • ΦϒδΣΫτͷੜ੒
    • ΦϒδΣΫτ΁ͷϝοηʔδ
    • શͯ͸ΞΫλʔ
    • ঢ়ଶͷΧϓηϧԽ
    • ৼΔ෣͍
    • ΞΫλʔͷੜ੒
    • ΞΫλʔ΁ͷϝοηʔδ
    ʮશͯͷ΋ͷ͸ΞΫλʔͰ͋Δʯͱ͍͏ࢥ૝
    class AccountActor(val name: String, var money: Int) extends Actor
    class Account private (val name: String, var money: Int)

    View Slide

  68. Akka Actor

    Akka Actorʹ͓͚Δฒߦॲཧͷಛ௃
    • ඇಉظϝοηʔδύογϯά
    • ୯ҰΞΫλʔ಺Ͱͷϝοηʔδॲཧͷஞ࣍ੑ

    View Slide

  69. ΞΫλʔ

    ܰྔϓϩηε
    ※ڞ༗ϝϞϦΛ࣋ͨͳ͍ͨΊɺεϨουͰ͸ͳ͘ϓϩηεͱݺͿ
    ΞΫλʔಉ࢜ͰϝϞϦ͸ڞ༗͠ͳ͍
    AkkaͰ͸1GBͷϝϞϦʔͰɺΞΫλʔΛ270ສݸੜ੒Ͱ͖Δ
    (JVMͷεϨου͸1GBͰ4096ݸੜ੒Ͱ͖Δ)

    View Slide

  70. ඇಉظϝοηʔδύογϯά

    "DUPS̎
    "DUPS̍
    ͦΕͧΕͷΞΫλʔ͸ϝʔϧϘοΫεΛ࣋ͪɺ
    ϝοηʔδΛૹΓ͋ͬͯॲཧΛߦ͏
    ΞΫλʔ̍ ΞΫλʔ̎
    ΞΫλʔ̏ ΞΫλʔ̐

    View Slide

  71. ඇಉظϝοηʔδύογϯά

    ΞΫλʔؒͷϝοηʔδͷ΍ΓͱΓ͸શͯඇಉظʹߦΘΕΔ
    ඇಉظʹϝοηʔδΛड͚औΔ
    ΞΫλʔ

    View Slide

  72. ୯ҰΞΫλʔ಺Ͱͷ
    ϝοηʔδॲཧͷஞ࣍ੑ

    • ୯ҰΞΫλʔʹର͢Δॲཧ͸ஞ࣍తʹͳΔͷͰɺΞΫλʔͷ಺෦ঢ়ଶʹରͯ͠
    εϨουηʔϑʹͳΔ(ϩοΫ΍ಉظ͕ෆཁ)
    • ΞΫλʔಉ࢜͸ผϓϩηεͳͷͰɺଞͷΞΫλʔ͕಺෦ঢ়ଶʹΞΫηε͢Δ͜ͱ΋ͳ͍
    • Dispatcher͕ΞΫλʔʹεϨουΛׂΓ౰ͯΔ͜ͱʹΑͬͯϝοηʔδ͕ॲཧ͞ΕΔ
    "DUPS
    ϝοηʔδͷॲཧ͸ஞ࣍తʹߦ͏
    ΞΫλʔ

    View Slide

  73. Dispatcher

    εϨουϓʔϧΛ͍࣋ͬͯͯɺ
    ΞΫλʔʹεϨουΛׂΓ౰ͯΔ͜ͱʹΑͬͯɺ
    ϝʔϧϘοΫε಺ͷະॲཧͷϝοηʔδΛॲཧ͢Δ
    •Dispatcher͸̐छྨ͋Δ
    •Dispatcher୯ҐͰεϨου਺΍Executorͷछྨ΋ม͑ΒΕΔ
    •ΞΫλʔ୯ҐͰ࢖༻͢ΔDispatcherΛม͑ΒΕΔ

    View Slide

  74. Dispatcher

    IOό΢ϯυͳॲཧΛߦ͏Actor CPUό΢ϯυͳॲཧΛߦ͏Actor
    Actorͷछྨ͝ͱʹDispatcherΛ࢖͍෼͚Δ͜ͱʹΑΔ
    ύϑΥʔϚϯενϡʔχϯά΋Մೳ
    (ྫ: CPUό΢ϯυͳॲཧͷDispatcherͷεϨου਺Λଟ͘͢ΔͳͲ)

    View Slide

  75. Akka Actor

    Dispatcher͕
    ActorʹεϨουΛ
    ׂΓ౰ͯΔ
    ΞΫλʔ
    ͜͜ͷඇಉظॲཧ෦෼͸Akka Actor
    ಺෦ͰΑ͠ͳʹ΍ͬͯ͘ΕΔ
    ϓϩάϥϚʔ͸Actor͕࣮ߦ͢Δॲཧͱɺ
    ϝοηʔδͷૹ৴ͷ࣮૷ʹूதͰ͖Δ
    DispatcherʹׂΓ౰ͯΒΕͨ
    εϨουΛ࢖ͬͯॲཧΛ࣮ߦ
    ΞΫλʔ
    ΞΫλʔ ΞΫλʔ

    View Slide

  76. Akka Actor

    class HelloActor extends Actor {
    def receive = {
    case "Hello" =>
    println(s"World!")
    }
    }
    val actorSystem = ActorSystem("System")
    val helloActor = actorSystem.actorOf(Props[HelloActor])
    helloActor ! "Hello"
    ΞΫλʔͷ࣮ߦ͢Δॲཧͷ࣮૷
    ϝοηʔδͷૹ৴
    ඇಉظϝοηʔδύογϯάͷ࣮૷
    ΞΫλʔͷੜ੒

    View Slide

  77. ୯ҰΞΫλʔ಺Ͱͷ
    ϝοηʔδॲཧͷஞ࣍ੑ

    ಺෦ঢ়ଶ͸อޢ͞ΕΔͨΊɺಉظॲཧΛϓϩάϥϚ͕΍Δඞཁ͕ͳ͍
    money: 2000
    Insufficient funds (2000 < 5000)
    class AccountActor(val name: String, var money: Int) extends Actor {
    override def receive: Receive = {
    case deposit: Deposit => {
    if(money - deposit.amount > 0) {
    if(deposit.amount == 8000) Thread.sleep(1000)
    money -= deposit.amount
    println(s"money: $money")
    } else {
    println(s"Insufficient funds ($money < ${deposit.amount})")
    }
    }
    }
    }
    lazy val ourSystem = ActorSystem("OurSystem")
    val accountActor = ourSystem.actorOf(Props(classOf[AccountActor], "Jack", 10000))
    accountActor ! Deposit(8000)
    accountActor ! Deposit(5000)
    ϝοηʔδ͸ඇಉظʹૹΒΕΔ͕ɺ
    ॲཧ͸ஞ࣍తʹߦΘΕΔ

    View Slide

  78. ิ଍

    ϝοηʔδۦಈʹΑΔϨεϙϯγϒͳγεςϜͷ࣮ݱ
    Akka Actor͸ฒߦॲཧΛ࣮ݱ͢Δ͚ͩͰ͸ͳ͍
    •଱ো֐ੑͳͲ
    •Ґஔಁաੑ
    •εέʔϥϏϦςΟͳͲͳͲɻɻɻ
    Akka͸ߋͳΔػೳΛఏڙ͢Δ(Akka RemoteɺAkka Cluster)

    View Slide

  79. FutureͱActor

    ɾforࣜΛ༻͍ͨ૊Έ߹Θͤɺ݁Ռͷ߹੒
    ɾঢ়ଶΛอ࣋͢ΔΦϒδΣΫτΛѻ͏
    ɾঢ়ଶΛอ࣋͠ͳ͍ؔ਺Λѻ͏
    ɾΞΫλʔϞσϧʹج͍ͮͨ
    ϝοηʔδͰͷ΍ΓͱΓ
    Future
    Akka Actor
    ࢖༻͢Δ
    ͜ͱ΋Մೳ

    View Slide

  80. Actor·ͱΊ

    • Actorͷฒߦॲཧ͸ඇಉظϝοηʔδύογϯάʹΑͬͯ
    ࣮ݱ͞ΕΔ
    • ΞΫλʔϞσϧ͸ঢ়ଶʹରͯ͠εϨουηʔϑ

    View Slide


  81. શͯ಺෦ͰExecutionContextΛ࢖༻͍ͯ͠Δ
    Future
    ฒྻ
    ίϨΫγϣϯ
    Akka Actor

    View Slide

  82. ͓඼ॻ͖

    • ฒߦɾฒྻॲཧͱ͸
    • ScalaͷϥΠϒϥϦʹ͍ͭͯ
    • ExecutionContextʹ͍ͭͯ
    • ·ͱΊ

    View Slide

  83. ExecutionContextʹ͍ͭͯ

    • ExecutionContext.globalΛ࢖͑͹͍͍ͷ͔
    • ࠷దͳεϨουϓʔϧͷαΠζ

    View Slide

  84. ExecutionContext

    object Future {
    def apply[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T]
    }
    applyʹ౉ͯ͠ɺ಺෦ͰExecutionContext͕ඇಉظॲཧΛ࣮ߦ͍ͯ͠Δ
    Future
    Akka Actor
    dispatcher͸ExecutionContextΛ࢖ͬͯɺActorʹϝοηʔδΛૹ͍ͬͯΔ
    trait ActorContext extends ActorRefFactory {
    implicit def dispatcher: ExecutionContextExecutor
    }
    val defaultTaskSupport: TaskSupport = new ExecutionContextTaskSupport
    ฒྻ࣮ߦ͢Δtasksupportͷத਎͸ExecutionContext
    ฒྻίϨΫγϣϯ

    View Slide

  85. ExecutionContext

    ॲཧʢλεΫʣΛ͍͍ײ͡ʹεϨουʹ෼഑ͯ͘͠ΕΔ
    εϨουϓʔϧ
    εϨου1
    εϨου2
    εϨου3
    εϨου4
    λεΫ1
    λεΫ2 λεΫ10
    λεΫ3 λεΫ5 λεΫ8
    λεΫ7
    λεΫ6 λεΫ9
    λεΫ4

    View Slide

  86. ExecutionContextͷར༻ํ๏

    • ExecutionContext.global
    • ࣗ࡞ExecutionContext
    େ͖͘෼͚ͯ2छྨ͋Δ
    Cannot find an implicit ExecutionContext. You might pass
    [error] an (implicit ec: ExecutionContext) parameter to your method
    [error] or import scala.concurrent.ExecutionContext.Implicits.global.

    View Slide

  87. ExecutionContext.global

    • scala.concurrentύοέʔδʹఆٛͯ͋͠ΔExecutionContext
    • ͱΓ͋͑ͣ͜ΕΛ࢖͑͹Future͕ಈ͘
    • σϑΥϧτͰ͸ίΞ਺෼ͷεϨουϓʔϧΛ࡞੒͢Δ
    • ࣮૷͸BlockContextΛܧঝͨ͠ExecutorService
    • ฒྻίϨΫγϣϯͰσϑΥϧτͰ࢖ΘΕΔ
    implicit val ec = scala.concurrent.ExecutionContext.global
    import scala.concurrent.ExecutionContext.Implicits.global

    View Slide

  88. ࣗ࡞ExecutionContext

    val executorService = Executors.newFixedThreadPool(4)
    implicit val ec = ExecutionContext.fromExecutorService(executorService)
    Future {

    }
    ExecutorService͔ΒExecutionContextΛ࡞੒͢Δ͜ͱ͕Ͱ͖Δ
    ExecutorService: java.util.concurrentύοέʔδʹఆٛ͞Ε͍ͯΔ
    εϨουϓʔϧΛѻ͏ΦϒδΣΫτ

    View Slide

  89. ࣗ࡞ExecutionContext

    ฒྻίϨΫγϣϯ
    parVector.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(4))
    Akka Actor
    fork-join—dispatcher {
    type = Dispatcher
    executor = "fork-join-executor"
    fork-join-executor {
    parallelism-min = 8
    parallelism-factor = 3.0
    parallelism-max = 64
    }
    throughput = 100
    }
    thread-pool-dispatcher {
    type = Dispatcher
    executor = "thread-pool-executor"
    thread-pool-executor {
    fixed-pool-size = 32
    }
    throughput = 1
    }
    val helloActor = actorSystem.actorOf(Props[HelloActor].withDispatcher(“fork-join-dispatcher”))
    val greeterActor = actorSystem.actorOf(Props[GreetActor].withDispatcher("thread-pool-dispatcher"))
    application.conf
    application.conf

    View Slide

  90. ExecutionContext.global
    vs
    ࣗ࡞ExecutionContext

    • ExecutionContext.global͸γεςϜશମͷڞ༻εϨου
    ϓʔϧ
    • ϒϩοΩϯάॲཧ࣌ͷৼΔ෣͍

    View Slide

  91. ExecutionContext.global͸
    γεςϜશମͷڞ༻εϨουϓʔϧ

    ॏ͍ͨλεΫͰExecutionContext.globalͷεϨουϓʔϧΛ
    ઎༗ͯ͠͠·͏ͱɺଞͷ෦෼ʹӨڹ͕ग़ͯ͠·͏Մೳੑ͕͋Δ
    εϨου εϨου εϨου εϨου
    ExecutionContext.global
    λεΫ ॏ͍ͨλεΫ
    ×

    View Slide

  92. εϨουϓʔϧͷ෼ׂ

    εϨου εϨου εϨου εϨου
    ExecutionContext.global
    εϨου εϨου
    ࣗ࡞ExecutionContext
    ϒϩοΩϯάॲཧ
    ϊϯϒϩοΩϯάॲཧ
    ϒϩοΩϯάॲཧ͸ͦΕઐ༻ͷExecutionContextΛ࡞੒ͯ͠ɺ
    ڞ༗ͷεϨουϓʔϧΛ઎༗͠ͳ͍Α͏ʹͨ͠΄͏͕Α͍

    View Slide


  93. ExecutionContext.global͸blockingϝιου͕ݺͼग़͞Εͨ࣌ʹɺ
    εϨουΛࣗಈͰ૿΍͢(σϑΥϧτͰ࠷େ256εϨου·Ͱ)
    ϒϩοΩϯάॲཧ࣌ͷৼΔ෣͍
    εϨου1
    εϨου2
    λεΫ1
    λεΫ2
    blocking
    εϨου λεΫ3
    λεΫ4
    blocking
    λεΫ5
    εϨου4 λεΫ6
    εϨουϓʔϧ
    εϨουੜ੒
    εϨουੜ੒

    View Slide

  94. scala.concurrent.blocking

    def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)
    ϒϩοΩϯάॲཧΛϚʔΫ͠ɺ
    εϨου͕ރׇ͢ΔͷΛ๷͙ώϯτΛ༩͑Δϝιου
    ExecutionContext.globalͰ͸ɺ
    blockingϝιουʹΑΔώϯτΛड͚औͬͯ
    εϨουΛ૿΍࣮͢૷͕͞Ε͍ͯΔ(BlockContextΛܧঝ)

    View Slide

  95. ϒϩοΩϯάॲཧ with global

    blockingϝιου͕ݺ͹Εͨ࣌ʹɺ
    εϨουΛࣗಈͰ૿΍ͯ͘͠ΕΔʢॳظεϨου਺: 8ʣ
    implicit val ec = scala.concurrent.ExecutionContext.global
    val time = measure {
    val futures = for(_ <- 0 until 100) yield Future {
    blocking {
    Thread.sleep(1000)
    }
    }
    for (f <- futures) Await.ready(f, Duration.Inf)
    }
    log(s"Total time = ${time.value}")
    ExecutionContext.global

    View Slide

  96. ϒϩοΩϯάॲཧ with global

    Total time = 1048
    implicit val ec = scala.concurrent.ExecutionContext.global
    val time = measure {
    val futures = for(_ <- 0 until 100) yield Future {
    blocking {
    Thread.sleep(1000)
    }
    }
    for (f <- futures) Await.ready(f, Duration.Inf)
    }
    log(s"Total time = ${time.value}")
    blockingϝιου͕ݺ͹ΕΔͱ
    ExecutionContext.global͕
    ࣗಈͰεϨουΛੜ੒͢Δ
    blockingϝιου͕ݺ͹Εͨ࣌ʹɺ
    εϨουΛࣗಈͰ૿΍ͯ͘͠ΕΔʢॳظεϨου਺: 8ʣ

    View Slide

  97. ϒϩοΩϯάॲཧ
    with ࣗ࡞ExecutionContext

    blockingϝιου͕ݺ͹Εͯ΋ɺ
    εϨου͕૿͑ͳ͍ʢεϨου਺: 8ʣ
    val executorService = Executors.newWorkStealingPool(8)
    implicit val ec = ExecutionContext.fromExecutorService(executorService)
    val time = measure {
    val futures = for(_ <- 0 until 100) yield Future {
    blocking {
    Thread.sleep(1000)
    }
    }
    for(f <- futures) Await.ready(f, Duration.Inf)
    }
    println(s"Total time = ${time.value}")
    fromExecutorServiceΛ࢖༻

    View Slide

  98. ϒϩοΩϯάॲཧ
    with ࣗ࡞ExecutionContext

    Total time = 13071
    ExecutionContext.global
    ࢖༻࣌ΑΓ΋
    10ഒͷ࣌ؒΛཁ͢Δ
    blockingϝιου͕ݺ͹Εͯ΋ɺ
    εϨου͕૿͑ͳ͍ʢεϨου਺: 8ʣ
    val executorService = Executors.newWorkStealingPool(8)
    implicit val ec = ExecutionContext.fromExecutorService(executorService)
    val time = measure {
    val futures = for(_ <- 0 until 100) yield Future {
    blocking {
    Thread.sleep(1000)
    }
    }
    for(f <- futures) Await.ready(f, Duration.Inf)
    }
    println(s"Total time = ${time.value}")
    ϒϩοΩϯάॲཧ
    with ࣗ࡞ExecutionContext

    fromExecutorServiceΛ࢖༻

    View Slide

  99. ϒϩοΩϯάॲཧ

    IOͳͲͷϒϩοΩϯάॲཧ͕ExecutionContext಺ͰߦΘΕΔ৔߹͸ɺ
    ͦͷॲཧΛ໌ࣔతʹblockingϝιουͰғΉํ͕ྑ͍
    ͨͩ͠ɺͦͷ৔߹͸BlockContextΛܧঝͨ͠
    ExecutionContextΛ࢖͏ඞཁ͕͋Δ

    View Slide

  100. ࠷దͳεϨουϓʔϧͷαΠζ

    •JVMͩͱ1εϨουͰ2Mཁ͢Δ
    •CPUͷՔಇ͕100%ͷ࣌ʹεϨου਺Λ૿΍ͯ͠΋ɺ
    ແବʹࢿݯΛ৯͍ਚ͚ͩ͘͢
    Ή΍ΈʹεϨουΛ૿΍ͯ͠΋ੑೳ্͕͕Δͱ͸ݶΒͳ͍
    খ͗͢͞ => CPUͷΞΠυϧ͕࣌ؒੜͯ͡ɺεϧʔϓοτ௿ԼΛಋ͘
    େ͖͗͢ => εϨου͕CPU΍ϝϞϦࢿݯΛ૪͏ɻίϯςΩετεΠονʹΑΔεϧʔϓοτ
    ௿ԼɺϝϞϦෆ଍Λಋ͘
    খ͞ա͗ͣɺେ͖ա͗ͣ

    View Slide

  101. ࠷దͳεϨουϓʔϧͷαΠζ

    ࣮֬ͳํ๏͸ͳ͍͕ɺܾΊΔͨΊͷཁૉ͸͋Δ
    •CPUͷ਺
    •CPUՔಇ཰
    •λεΫ଴ͪ࣌ؒͱܭࢉ࣌ؒͷൺ཰
    εϨουͷ਺ = CPUͷ਺ × CPUՔಇ཰ × (1 + λεΫ଴ͪ࣌ؒͱܭࢉ࣌ؒͷൺ཰)
    Ұྫ
    ࢀߟɿJavaฒߦॲཧϓϩάϥϛϯά

    View Slide

  102. ͓඼ॻ͖

    • ฒߦɾฒྻॲཧͱ͸
    • ScalaͷϥΠϒϥϦʹ͍ͭͯ
    • ExecutionContextʹ͍ͭͯ
    • ·ͱΊ

    View Slide

  103. ·ͱΊ

    ϥΠϒϥϦ ಛ௃ Ϣʔεέʔε
    ฒྻίϨΫγϣϯ
    ίϨΫγϣϯʹର͢Δ
    ฒྻॲཧ
    ݕࡧ/બ୒/
    ιʔτ/ूܭ
    'VUVSF
    4DBMBΒ͍͠߹੒Մೳͳ
    ඇಉظॲཧ
    ঢ়ଶΛѻΘͳ͍ॲཧ
    ؔ਺
    "LLB"DUPS
    ΞΫλʔϞσϧʹجͮ͘
    ඇಉظϝοηʔδύογϯά
    ঢ়ଶΛѻ͏ΦϒδΣΫτ
    ϨεϙϯγϒͳγεςϜ

    View Slide

  104. ·ͱΊ

    • ScalaͷϥΠϒϥϦʹ͸ͦΕͧΕಛ௃΍Ϣʔεέʔε͕͋Δ
    • εϨουϓʔϧͷ෼ׂ/αΠζ(ExecutionContext)Λߟྀ͢
    Δ͜ͱ΋ઓུͷҰͭ

    View Slide