如何以内存高效的方式使用 Kotlin 的序列和 lambda
How to use Kotlin's sequences and lambdas in a way that's memory efficient
所以我正在编写一些需要既高效又快速的代码。我已经在 java 中有一个工作参考,但正在用 kotlin 重写它。
我基本上需要加载很多csv文件,一次加载到树中,加载完成后重复遍历。
我最初使用序列编写整个程序,但发现它会导致 GC 反复出现尖峰。
我真的不能分享这段代码,但想知道你们是否知道会导致这种情况发生的原因。
我很乐意根据您的需要添加详细信息,但这是我的基本模式。
第一步:inputStream -> csvLines: List<String>
第 2 步:csvLines.drop(x).fold(emptySequence()) -> callOtherFunctionWithFold -> callOtherFunctionWithFold -> Sequence<OutputObjects>
我将 csvLines 保留为单独的列表,因为我根据需要的规则访问特定行。
第 3 步:Sequence<OuputObjects> -> nodes
结果是有效的,但与仅使用数组列表并就地修改它们的 java 等效代码相比,此代码的内存效率和性能要低得多。
查看 visualvm 输出后,我创建了大量的 kotlin.*.ArrayIterators。看起来我每次使用 lamda 都会创建一个。
那么我该怎么做才能提高效率呢?虽然序列应该懒惰地减少对象创建,但看起来我正在做的事情破坏了它这样做的能力。
通常在 GC 运行 或 运行 之后,序列会重新评估吗?如果是这样,那会使它们不适合在启动时加载的对象中使用,对吗?
要使用 Kotlin 序列,您需要从 asSequence()
开始
csvLines.asSequence()
.drop(x)
.fold(...)
...
如果您忽略它,它会使用集合函数,而不是在每个函数之后创建一个新的(中间)集合。
所以我正在编写一些需要既高效又快速的代码。我已经在 java 中有一个工作参考,但正在用 kotlin 重写它。
我基本上需要加载很多csv文件,一次加载到树中,加载完成后重复遍历。
我最初使用序列编写整个程序,但发现它会导致 GC 反复出现尖峰。
我真的不能分享这段代码,但想知道你们是否知道会导致这种情况发生的原因。
我很乐意根据您的需要添加详细信息,但这是我的基本模式。
第一步:inputStream -> csvLines: List<String>
第 2 步:csvLines.drop(x).fold(emptySequence()) -> callOtherFunctionWithFold -> callOtherFunctionWithFold -> Sequence<OutputObjects>
我将 csvLines 保留为单独的列表,因为我根据需要的规则访问特定行。
第 3 步:Sequence<OuputObjects> -> nodes
结果是有效的,但与仅使用数组列表并就地修改它们的 java 等效代码相比,此代码的内存效率和性能要低得多。
查看 visualvm 输出后,我创建了大量的 kotlin.*.ArrayIterators。看起来我每次使用 lamda 都会创建一个。
那么我该怎么做才能提高效率呢?虽然序列应该懒惰地减少对象创建,但看起来我正在做的事情破坏了它这样做的能力。
通常在 GC 运行 或 运行 之后,序列会重新评估吗?如果是这样,那会使它们不适合在启动时加载的对象中使用,对吗?
要使用 Kotlin 序列,您需要从 asSequence()
csvLines.asSequence()
.drop(x)
.fold(...)
...
如果您忽略它,它会使用集合函数,而不是在每个函数之后创建一个新的(中间)集合。