在Scala Native的区域(Zone)分配过程中,如何避免对Tag$CStruct1的频繁GC分配?
我在Scala Native(v0.5.10)尝试在Zones中分配一个结构体数组的数组。对基准进行性能分析时,我发现超过50% 的运行时间耗费在 scalanative_GC_alloc_small 下,调用栈包含:
scalanative_GC_alloc_small
scala.scalanative.unsafe.Tag$CStruct1$.apply
下面是代码:
import scala.scalanative.unsafe.*
object RegionBenchmarkZonesSlow {
type Node = CStruct1[Int]
// I also tried: given Tag[Node] = Tag.materializeCStruct1Tag[Int] (doesn't help)
def makeArrayInZone(
size: Int,
base: Int
)(using Zone): Ptr[Ptr[Node]] = {
val outer = alloc[Ptr[Node]](size)
var i = 0
while (i < size) {
val inner = alloc[Node](size) // never allocates the tag again
var j = 0
while (j < size) {
(!(inner + j))._1 = base + j
j += 1
}
!(outer + i) = inner
i += 1
}
outer
}
def traverse(
arrays: Ptr[Ptr[Node]],
size: Int
): Long = {
var sum = 0L
var i = 0
while (i < size) {
val inner = !(arrays + i)
var j = 0
while (j < size) {
sum += (!(inner + j))._1
j += 1
}
i += 1
}
sum
}
def runExperiment(n: Int): Long = {
val start =
System.nanoTime()
var iteration = 0
while (iteration < 40) {
val z =
Zone.open()
try {
given Zone = z
val arrays =
makeArrayInZone(
n,
iteration * n * n
)
val sum =
traverse(arrays, n)
if (sum == -1L) {
println("Impossible")
}
} finally {
z.close()
}
iteration += 1
}
val end =
System.nanoTime()
end - start
}
def main(args: Array[String]): Unit = {
val sizes =
Array(500, 1000, 1500, 2000, 2500, 3000)
var i = 0
while (i < sizes.length) {
val n = sizes(i)
val totalObjects =
n.toLong * n
val elapsedNs =
runExperiment(n)
val elapsedMs =
elapsedNs / 1000000.0
println(
"n=" + n +
" totalObjects=" + totalObjects +
" time=" + elapsedMs + " ms"
)
i += 1
}
}
}
有没有办法消除这些分配(以及GC)?
现在:
预期结果(将结构体替换为Int):

解决方案
将模式从 debug 改为 releaseFast 就解决了这个问题。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。