与 Kotlin 中的协程文件集进行比较
Compare to sets of files with coroutines in Kotlin
我写了一个函数,可以从两个列表中扫描文件(图片),并检查一个文件是否在两个列表中。
下面的代码按预期工作,但对于大型集合来说需要一些时间。所以我尝试与协程并行执行此操作。但是在 100 个示例文件的集合中,程序总是比没有协同程序慢。
代码:
private fun doJob() {
val filesToCompare = File("C:\Users\Tobias\Desktop\Test").walk().filter { it.isFile }.toList()
val allFiles = File("\\myserver\Photos\photo").walk().filter { it.isFile }.toList()
println("Files to scan: ${filesToCompare.size}")
filesToCompare.forEach { file ->
var multipleDuplicate = 0
var s = "This file is a duplicate"
s += "\n${file.absolutePath}"
allFiles.forEach { possibleDuplicate ->
if (file != possibleDuplicate) { //only needed when both lists are the same
// Files that have the same name or contains the name, so not every file gets byte comparison
if (possibleDuplicate.nameWithoutExtension.contains(file.nameWithoutExtension)) {
try {
if (Files.mismatch(file.toPath(), possibleDuplicate.toPath()) == -1L) {
s += "\n${possibleDuplicate.absolutePath}"
i++
multipleDuplicate++
println(s)
}
} catch (e: Exception) {
println(e.message)
}
}
}
}
if (multipleDuplicate > 1) {
println("This file has $multipleDuplicate duplicate(s)")
}
}
println("Files scanned: ${filesToCompare.size}")
println("Total number of duplicates found: $i")
}
我是如何尝试添加协程的?
我将代码包装在 launch{...}
中的第一个 forEach 中,想法是为每个文件启动一个协程,并同时完成第二个循环。我预计该程序会 运行 更快,但实际上它是大约相同的时间或更慢。
如何才能更快地将此代码并行 运行?
运行 协程中的每个内部循环似乎都是一种不错的方法。问题可能出在您使用的调度程序上。如果您在没有上下文参数的情况下使用 runBlocking
和 launch
,则您使用的是单个线程 运行 所有协程。
由于这里主要是阻塞 IO,您可以改为使用 Dispatchers.IO
来启动您的协程,这样您的协程就会在多个线程上分派。并行度应自动限制为 64,但如果您的内存无法处理,您也可以使用 Dispatchers.IO.limitedParallelism(n)
来减少线程数。
我写了一个函数,可以从两个列表中扫描文件(图片),并检查一个文件是否在两个列表中。
下面的代码按预期工作,但对于大型集合来说需要一些时间。所以我尝试与协程并行执行此操作。但是在 100 个示例文件的集合中,程序总是比没有协同程序慢。
代码:
private fun doJob() {
val filesToCompare = File("C:\Users\Tobias\Desktop\Test").walk().filter { it.isFile }.toList()
val allFiles = File("\\myserver\Photos\photo").walk().filter { it.isFile }.toList()
println("Files to scan: ${filesToCompare.size}")
filesToCompare.forEach { file ->
var multipleDuplicate = 0
var s = "This file is a duplicate"
s += "\n${file.absolutePath}"
allFiles.forEach { possibleDuplicate ->
if (file != possibleDuplicate) { //only needed when both lists are the same
// Files that have the same name or contains the name, so not every file gets byte comparison
if (possibleDuplicate.nameWithoutExtension.contains(file.nameWithoutExtension)) {
try {
if (Files.mismatch(file.toPath(), possibleDuplicate.toPath()) == -1L) {
s += "\n${possibleDuplicate.absolutePath}"
i++
multipleDuplicate++
println(s)
}
} catch (e: Exception) {
println(e.message)
}
}
}
}
if (multipleDuplicate > 1) {
println("This file has $multipleDuplicate duplicate(s)")
}
}
println("Files scanned: ${filesToCompare.size}")
println("Total number of duplicates found: $i")
}
我是如何尝试添加协程的?
我将代码包装在 launch{...}
中的第一个 forEach 中,想法是为每个文件启动一个协程,并同时完成第二个循环。我预计该程序会 运行 更快,但实际上它是大约相同的时间或更慢。
如何才能更快地将此代码并行 运行?
运行 协程中的每个内部循环似乎都是一种不错的方法。问题可能出在您使用的调度程序上。如果您在没有上下文参数的情况下使用 runBlocking
和 launch
,则您使用的是单个线程 运行 所有协程。
由于这里主要是阻塞 IO,您可以改为使用 Dispatchers.IO
来启动您的协程,这样您的协程就会在多个线程上分派。并行度应自动限制为 64,但如果您的内存无法处理,您也可以使用 Dispatchers.IO.limitedParallelism(n)
来减少线程数。