在Scala Native的区域(Zone)分配过程中,如何避免对Tag$CStruct1的频繁GC分配?

编程语言 2026-07-09

我在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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章