我正在尝试测试Akka Streams
的吞吐量,并了解随着请求数量的增加它的扩展程度。
我目前面临的问题是stream
并发工作。我的stream
由flows
组成,每个人都会睡一秒钟以模拟功能。会发生的是,对于通过流传递的每个元素,流程将同步处理它。我希望这也是异步的,以优化我的表现。
这是我使用的代码:
// Flow that's being used
def processingStage(name: String): Flow[TestObject, TestObject, NotUsed] =
Flow[TestObject].map { s ⇒
println(name + " started processing " + s + " on thread " + Thread.currentThread().getName)
Thread.sleep(1000) // Simulate long processing *don't sleep in your real code!*
println(name + " finished processing " + s)
s
}
// Stream
def startStream() = {
val completion = Source[TestObject](list.toList)
.via(processingStage("A")).async
.via(processingStage("B")).async
.runWith(Sink.foreach(s ⇒ println("Got output " + s)))
}
答案 0 :(得分:0)
不要使用Thread.sleep(1000)来模拟延迟 - 使用基于时间的组合器。
此外,如果要在同一个流中强制执行多个阶段的并发,请使用.async
分界。有关详细信息,请参阅文档。
答案 1 :(得分:0)
Streams默认是串行的。如果您希望并行处理流中的元素,则必须直接请求它。
文档描述了实现此目标的一种方法:http://doc.akka.io/docs/akka/2.4/scala/stream/stream-cookbook.html#Balancing_jobs_to_a_fixed_pool_of_workers
这是它添加到您的代码中:
func addViewToNav()
{
myView = UIView(frame: CGRect(x: 0, y: 20, width: (self.navigationController?.navigationBar.frame.size.width)!-40, height: (self.navigationController?.navigationBar.frame.size.height)!))
imageView.frame = CGRect(x: 5, y: (myView?.frame.size.height)!/2-14, width: 28, height: 28)
let image = UIImage(named: "download")
imageView.contentMode=UIViewContentMode.scaleAspectFill
imageView.image=image
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
imageView.backgroundColor=UIColor.yellow
label = UILabel(frame: CGRect(x: imageView.frame.size.width+15, y: 0, width: 150, height: (myView?.frame.size.height)!))
label?.text="Label"
label?.textColor=UIColor.white
myView?.addSubview(imageView)
myView?.addSubview(label!)
self.navigationController?.view.addSubview(myView!)
//add tap gesturte on imageview & label
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(_:)))
myView?.isUserInteractionEnabled=true
tapGesture.numberOfTapsRequired=1
myView?.addGestureRecognizer(tapGesture)
}
答案 2 :(得分:0)
以下是您的代码的更新版本:
import akka.stream.scaladsl.{Sink, Source}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Test extends App {
// Flow that's being used
def processingStage(name: String): Future[String] = Future {
println(name + " started processing " + name + " on thread " + Thread.currentThread().getName)
Thread.sleep(1000) // Simulate long processing *don't sleep in your real code!*
println(name + " finished processing " + name)
name
}
// Stream
def startStream() = {
val parallelism = 10 //max number of parallel instances
val list = (1 to 1000000).toList.map(_.toString) //sample input
Source[String](list)
.mapAsync(parallelism)(processingStage) //handles the items concurrently
.runWith(Sink.foreach(s ⇒ println("Got output " + s)))
}
startStream()
}
第一点是,您应该将processingStage
函数转换为返回Future
的方法。通过这样做,您可以更好地模拟并发任务。
其次,您应该使用mapAsync
方法分阶段支持并发。据我了解,这是您正在寻找的确切功能。