【发布时间】:2020-06-05 05:04:52
【问题描述】:
我正在使用 kotlin 通道来迁移数据库:我有 1 个生产者和多个写入数据库的处理器。生产者只是将批量文档发送到通道:
fun CoroutineScope.produceDocumentBatches(mongoCollection: MongoCollection<Document>) = produce<List<Document>> {
var batch = arrayListOf<Document>()
for ((counter, document) in mongoCollection.find().withIndex()) {
if ((counter + 1) % 100 == 0) {
sendBlocking(batch)
batch = arrayListOf()
}
batch.add(document)
}
if (batch.isNotEmpty()) sendBlocking(batch) }
}
这是我的处理器的样子:
private fun CoroutineScope.processDocumentsAsync(
documentDbCollection: MongoCollection<Document>,
channel: ReceiveChannel<List<Document>>,
numberOfProcessedDocuments: AtomicInteger
) = launch(Dispatchers.IO) {
// do processing
}
这就是我在脚本中使用它们的方式:
fun run() = runBlocking {
val producer = produceDocumentBatches(mongoCollection)
(1..64).map { processDocumentsAsync(documentDbCollection, producer, count) }
}
那么在性能方面使用sendBlocking 可以吗?如果我只使用send,我会在一个协程中创建许多挂起函数,因为写入数据库比读取慢得多,我得到java.lang.OutOfMemoryError: Java heap space。我是否正确理解生产者阻塞Main 线程但它对性能很好,因为所有消费者都在 IO 线程上执行?
【问题讨论】:
-
不是
send导致您的OutOfMemory 问题。这是另外一回事。您不应该在此代码中需要sendBlocking。没有理由。