【发布时间】:2018-10-17 05:46:15
【问题描述】:
在我的 Android 手机应用程序中,有许多大型浮点列表 (100000+)。为了将它们与 OpenGl 一起使用,列表先转换为 FloatArrays,然后再转换为字节缓冲区。我遇到了性能问题,几个小时后,Kotlin .toFloatArray() 函数似乎很慢。
我的三星 Galaxy 手机上的一些测试结果:
elapsed time(msec) time/float(microsec)
max min avg
fillFloatArray 70 39 59,7 6.0
fillFloatList 472 357 444,1 44.4
convertListToArrayLooping 165 101 155,2 15.5
convertWithToFloatArray 388 318 367,3 36.7
Number of floats 10000
runs 10
(the average time / float is the same for a list of 100000 floats)
用值填充浮点数组很快,用浮点数填充列表要慢 7.4 倍。
但是,通过标准函数 List.toFoatArray() 将 List 转换为浮点数组比简单地填充数组慢 6.1 倍,也比简单地填充数组慢 2.4 倍循环列表。它几乎和用浮点数填充一个空列表一样慢!
我预计转换时间更接近于简单填充数组的时间?
.toFloatArray() 的性能有意义吗?将 List 转换为 Bytebuffer 的最快或至少更快的方法是什么?
下面的小测试程序,供参考。
class PlayGround {
private val stopwatch = Timing()
private val arraylist: MutableList<Float> = arrayListOf()
private val fillFloatArray = Results()
private val fillFloatList = Results()
private val convertListToArrayLooping = Results()
private val convertWithToFloatArray = Results()
fun checkSpeed () {
for (i in 0 until 10) { // do the timing ten times to get an average
// filling a floatarray with 10000 floats
stopwatch.start()
var array = FloatArray(10000, { it * 1f })
fillFloatArray.add(stopwatch.stop())
// filling a list with 10000 floats
stopwatch.start()
for (i in 0 until 10000) {
arraylist.add(i * 1f)
}
fillFloatList.add(stopwatch.stop())
// converting the fulllist to a floatarray by looping
stopwatch.start()
for (i in 0 until arraylist.size) {
array[i] = arraylist[i]
}
convertListToArrayLooping.add(stopwatch.stop())
// converting the fullist to a floatarray with toFloatArray
stopwatch.start()
array = arraylist.toFloatArray()
convertWithToFloatArray.add(stopwatch.stop())
arraylist.clear()
}
}
private class Results {
private var max = Long.MIN_VALUE
private var min = Long.MAX_VALUE
private var sum = 0L
private var avg = 0L
var measurePoints: MutableList<Long> = arrayListOf()
fun add (msrp: Long) {
measurePoints.add(msrp)
if (msrp > max) max = msrp
if (msrp < min) min = msrp
sum += msrp
avg = sum / measurePoints.size
}
fun clear() {
measurePoints.clear()
max = Long.MIN_VALUE
min = Long.MAX_VALUE
sum = 0L
avg = 0L
}
fun max(): Long { return max}
fun min(): Long { return min}
fun sum(): Long { return sum}
fun avg(): Long { return avg}
}
}
【问题讨论】:
-
注意
toFloatArray也必须分配一个新数组,所以这不一定是一个公平的比较。 -
您没有指定
arraylist的初始大小。使用arraylist = ArrayList<Float>(10000)。 -
标准函数是
Collection.toFloatArray,但您使用索引迭代将数据从列表传输到数组。 stdlib fun 无法使用索引迭代。 -
@OliverCharlesworth 说得太远了,但是对于 10000 个浮点数,这将花费 60 毫秒,但仍然使 toFloatArray 比循环遍历列表要慢?
-
@miensol,我重新运行它并预先分配,它不会改变结果(我很惊讶)
标签: android arrays list opengl-es kotlin