Skip to content

Scala library for easy concurrency. Will be something in between Akka and FRP in the near future. :)

Notifications You must be signed in to change notification settings

ReactiveMutator/duna

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Codacy Badge Codacy Badge Build Status BCH compliance Known Vulnerabilities

DUNA

A very raw library for concurrency in scala.

It consists of two main components:

  • val s = Var(smth)
  • val rx = Rx{ s() + d() }

Semantics was borrowed from Li Haoyi's scala.rx. So it has some connections with FRP. But only a little. Internally, the library is mainly mutable, nevertheless, it is still thread safe.

// stateManager distribute threads between Vars
implicit val stateManager = StateManager()

def mutator() = {
  val s = Var(0, 7)   // first number - initial value
                      // second number - a volume of an internal queue. Var's performans heavy depends on this number.

  for(i <- 1 to 5){

    s := i // Mutates Var value. Mutations of every Var happen sequentially.

  }

  s.now // Returns the last value.
}

mutator()

stateManager.stop() // Stops threadpool which works under the hood

Fibonacci example

Multithreading is not a cure-all for performance problems. But in case of long lasting tasks it can improve a situation significantly. Below are simple examples based on Fibonacci sequence. Measures were taken on 4 core AMD A8-4500M APU, 16GB DDR3, Arch Linux 1.4, 64-bit. As expected, the most performant code is the most straitforward: a mutable approach. But when time comes to latency, multithreading thrives. So that, a thread pool consisted of 3 Vars outperforms mutable variables and the fourth example is three times faster than third.

Examples

No latency

1 Example
// Naive mutable approach

  def fib(n: Int): Int = {

    var first = 0
    var second = 1
    var count = 0

    while(count < n){
      
        val sum = first + second
        first =  second
        second = sum
        count = count + 1
    }

    first
  }

  fib(8)
Results:
  • Elapsed time: 5.561E-5s
  • Memory increased: 0 Mb
2 Example
// Concurrent approach
  import duna.api.{ Var, StateManager }

  
  implicit val stateManager = StateManager()

  def fib(n: Int): Int = {

    val first = Var(0)
    val second = Var(1)
    val count = Var(0)

    while(count.now < n){
        val secondGet = second.now
        val countGet = count.now
        val sum = first.now + secondGet
        first := secondGet
        second := sum
        count := countGet + 1
    }

    first.now
  }

  println(fib(8))
  
Results:
  • Elapsed time: 0.05673288s
  • Memory increased: 4 Mb

Latancy

3 Example
// Naive mutable approach

  def fib(n: Int): Int = {

    var first = 0
    var second = 1
    var count = 0

    while(count < n){
      
        val sum = first + second
        first = {Thread.sleep(1000); second}
        second = {Thread.sleep(1000); sum}
        count = {Thread.sleep(1000); count + 1}
    }

    first
  }

  println(fib(8))
Results:
  • Elapsed time: 24.005672s
  • Memory increased: 0 Mb
4 Example
// Concurrent approach
  import duna.api.{ Var, StateManager }

  implicit val stateManager = StateManager()

  def fib(n: Int): Int = {

    val first = Var(0)
    val second = Var(1)
    val count = Var(0)

    while(count.now < n){
        val secondGet = second.now
        val countGet = count.now
        val sum = first.now + secondGet
        first := {Thread.sleep(1000); secondGet}
        second := {Thread.sleep(1000); sum}
        count := {Thread.sleep(1000); countGet + 1}
    }

    first.now
  }


  println(fib(8))

  stateManager.stop()
Results:
  • Elapsed time: 8.06258s
  • Memory increased: 4 Mb

Fibonacchi with Rx

import duna.api.{ Rx, Var, StateManager }

implicit val stateManager = StateManager()

    val first = Var(0)
    val second = Var(1)
    val counter = Var(0)

    val rx = Rx[Int]{implicit rx => 
    
      val c = counter.now
      if(c < 20){
        counter := { Thread.sleep(1000); c + 1 }
        val s = second.now
        first := { Thread.sleep(1000); s }
        second := { Thread.sleep(1000); first() + s }
      } 
    second.now
    }  

    first := 1
  stateManager.stop()
Results:
  • Elapsed time: 18.091383s
  • Memory increased: 5 Mb
  21
  34
  55
  89
  144
  233
  377
  610
  987
  1597
  2584
  4181
  6765
  10946
## A power of two example
import duna.api.{ Rx, Var, StateManager }
  
  implicit val stateManager = StateManager()

    val first = Var(0)
    val second = Var(1)
    var counter = 0

    second.onChange{value =>
      if(counter < 20){
        counter += 1 
        first := value
      } 
    }
    first.onChange{value =>
      val sec = second.now
      second := value + sec
    }
    first.onChange(println)
    first := 1

  stateManager.stop()
Results:
 1
 2
 4
 8
 16
 32
 64
 128
 256
 512
 1024
 2048
 4096
 8192
 16384
 32768
 65536
 131072
 262144
 524288
 1048576

About

Scala library for easy concurrency. Will be something in between Akka and FRP in the near future. :)

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages