【发布时间】:2021-07-23 01:38:12
【问题描述】:
我有一个包含 6+ 百万条记录的 CSV 文件。我正在读取 CSV 文件并收集数组列表中的每一行(列表)。整个列表需要经过一个分组逻辑,最后将每个分组推送到一个消息队列系统中。
这是我的代码:
var header: Map<String, Int> by Delegates.notNull()
val rows = csv.bufferedReader().useLines { lines ->
lines
.filter {
validate(it)
}
.filterNotNull()
.map { line ->
convert(line)
}
.toList()
}
parse(rows, header)
.forEach {
this.send(it)
}
fun parse(rows: List<List<String>>, header: Map<String, Int>): List<Domain> {
return rows
.asSequence()
.map { row ->
mapToColumn(row)
}
.mapNotNull { it.getOrNull() }
.filter(this::someFilter)
.groupBy { it['xyz'] }
.map { groupedRow ->
mapToDomain(groupedRow)
}
.mapNotNull { it.getOrNull() }
.flatten()
.toList()
}
使用 4GB RAM 和 1 个核心服务器,这会崩溃(耗尽服务器内存,我的应用程序会重新启动)。
这适用于较小的列表(200 万)条记录,但对于 6M 则失败。
我需要帮助来提高性能,也许是处理分组逻辑的更好方法,以减少内存消耗或使用不同类型的变量?
【问题讨论】:
-
您可能必须以一种不会将整个 CSV 文件保留在堆中的方式重写它。
List<Domain>到底有多大?你能负担得起把它留在记忆中吗? 600 万是绝对最大大小吗? -
@Rubydesic 最终的分组对象(
List<Domain>)肯定会有 5+ 百万条记录,有一些过滤逻辑会消除少量记录,但只会消除少数记录。我需要维护完整列表是由于分组逻辑,有没有其他方法可以在不维护内存中这么大的对象的情况下对记录进行分组?
标签: list performance kotlin collections operators