Scalaz中的异步迭代处理

Scalaz中的异步迭代处理,scala,asynchronous,scalaz,iterate,Scala,Asynchronous,Scalaz,Iterate,我一直在使用Scalaz 7迭代器在恒定堆空间中处理大量(即无界)数据流 在代码中,它看起来像这样: type ErrorOrT[M[+_], A] = EitherT[M, Throwable, A] type ErrorOr[A] = ErrorOrT[IO, A] def processChunk(c: Chunk): Result def process(data: EnumeratorT[Chunk, ErrorOr]): IterateeT[Chunk, ErrorOr, Lis

我一直在使用Scalaz 7迭代器在恒定堆空间中处理大量(即无界)数据流

在代码中,它看起来像这样:

type ErrorOrT[M[+_], A] = EitherT[M, Throwable, A]
type ErrorOr[A] = ErrorOrT[IO, A]

def processChunk(c: Chunk): Result

def process(data: EnumeratorT[Chunk, ErrorOr]): IterateeT[Chunk, ErrorOr, List[Result]] =
  Iteratee.fold[Chunk, ErrorOr, List[Result]](Nil) { (rs, c) =>
    processChunk(c) :: rs
  } &= data
现在我想并行地执行处理,一次处理p个数据块。我仍然需要限制堆空间,但是可以合理地假设有足够的堆来存储P个数据块和计算的累积结果

我知道
Task
类,并考虑通过枚举器映射来创建任务流:

data map (c => Task.delay(processChunk(c)))
但我仍然不知道如何管理非决定论在使用流时,如何确保P任务尽可能运行?

第一次尝试:

我的第一个解决方案是折叠流并创建一个Scala
Future
来处理每个块。然而,该程序由于GC开销错误而崩溃(可能是因为它在尝试创建所有
未来
时将所有块都拉入内存)。相反,当已经有P个任务在运行时,迭代对象需要停止使用输入,并在这些任务完成时再次恢复

第二次尝试:

我的下一次尝试是将流分组为p大小的部分,并行处理每个部分,然后在进入下一部分之前加入:

def process(data: EnumeratorT[Chunk, ErrorOr]): IterateeT[Chunk, ErrorOr, Vector[Result]] =
  Iteratee.foldM[Vector[Chunk], ErrorOr, Vector[Result]](Nil) { (rs, cs) =>
    tryIO(IO(rs ++ Await.result(
      Future.traverse(cs) { 
        c => Future(processChunk(c)) 
      }, 
      Duration.Inf)))
  } &= (data mapE Iteratee.group(P))

虽然这不能充分利用可用的处理器(特别是因为处理每个
块所需的时间可能相差很大),但这将是一种改进。但是,仅供参考,play iteratees(基于scala futures)也存在内存泄漏。这种情况@om nom nom内存泄漏似乎与Scala Futures的使用无关。看。实际上我想对这个问题发表评论:-)只是说scalaz期货和scala期货在概念上可能有相同的缺陷