Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何在scala中正确而简单地评测函数?_Performance_Scala_Profiling_Sbt_Jmh - Fatal编程技术网

Performance 如何在scala中正确而简单地评测函数?

Performance 如何在scala中正确而简单地评测函数?,performance,scala,profiling,sbt,jmh,Performance,Scala,Profiling,Sbt,Jmh,我试图在Scala中反转包含unicode字符的字符串。 我想找到最快的方法。 到目前为止,我有以下代码: import scala.runtime.RichChar def reverseInPlace(s: String): String = { val reverse = new Array[RichChar](s.length) for (i <- (0 to (s.length >> 1))) { reverse(i) = s(s.len

我试图在Scala中反转包含unicode字符的字符串。 我想找到最快的方法。 到目前为止,我有以下代码:

import scala.runtime.RichChar

def reverseInPlace(s: String): String = {
   val reverse = new Array[RichChar](s.length)   
   for (i <- (0 to (s.length >> 1))) {
     reverse(i) = s(s.length -i -1)
     reverse(s.length -i -1) = s(i)
   }
   return reverse.mkString
}

def reverseLeft(s: String): String = s.foldLeft("") ( (a,b) => 
    b + a
)

def reverseRight(s: String): String = s.foldRight("") ( (a,b) => 
    b + a
)


def time[R](iterations:Int, block: => R) = {
    val t0 = System.nanoTime()
    for ( i <- 0 to iterations){
       block    // call-by-name
    }
    val t1 = System.nanoTime()
    println("Elapsed time: " + (t1 - t0) + "ns")
}


time(1000, {
    reverseRight("Hello\u0041")
})

time(1000, {
    reverseInPlace("Hello\u0041")
})

time(1000, {
    reverseLeft("Hello\u0041")
})

time(1000, {
    "Hello\u0041".reverse
})
但我觉得这些数字是假的。 我该如何使用scala、sbt和JMH库对函数进行适当的基准测试

注意:正如评论中指出的,Java中的微观基准测试是一项严肃的业务
见()和。为什么你不应该在不使用外部库的情况下尝试微基准标记。

这里有一个解决方案,使用的不是没有框架,而是百里香。我之所以这样写,是因为我希望微基准标记框架感觉微型,而不是象大象一样

scala -cp /jvm/Thyme.jar
这是在REPL中运行它所需的全部操作

现在我们需要一个实际可行的实现。我写两封

第一次尝试:

def revStr(s: String): String = {
  val points = for (i <- s.indices if !s(i).isLowSurrogate) yield s.codePointAt(i)
  new String(points.toArray.reverse,0,points.length)
}
def revStr(s:String):String={
val点数=用于(i val th=新的一台台式机百里香
th:ichi.bench.Thyme=ichi.bench。Thyme@174580e6
scala>val testString=“这是一个\ud800\udc00测试!”

TestString:String =这是一个如果你不想使用一个外部库,你的问题实际上是一个副本。如果你接受一个外部库,考虑BTW对于<代码> RetriSePix< /代码>:考虑改写为使用<代码>而<代码> >而不是<代码> < <代码> >(这是理解的一种方法,是Scala库函数的语法糖)还有一个顺便说一句:看看你的源代码,它似乎并不太虚假:
foldRight
被实现为
reverse+foldLeft
。你的内置函数不使用
,而
foldLeft
使用
while
和头/尾遍历。
StringOps。reverse
使用带有大小提示的生成器。因此你的n数字可能是有效的,但这应该通过JMH等进行检查。为什么不使用外部库呢?如果您不喜欢重量级的替代方案,我为类似这样的情况编写了一个轻量级的替代方案:您可能还可以找到其他库(例如
scala.testing.Benchmark
trait).@铍是一个重要的旁注,尽管卡尺在该问题中被提及,并且它是一个公认的行业标准工具。是的,JMH是首选的替代工具。REPL应该有一个命令来调用您选择的基准工具。或者sbt,就像
测试
一样简单。它在sbt提示符或REPL处会变得模糊,但是也许是雷普的。
def revStr(s: String): String = {
  val points = for (i <- s.indices if !s(i).isLowSurrogate) yield s.codePointAt(i)
  new String(points.toArray.reverse,0,points.length)
}
def reverseString(s: String): String = if (s.length < 2) s else {
  import java.lang.Character.{isLowSurrogate => lo, isHighSurrogate => hi}
  val chars = s.toCharArray
  var i = 0
  var j = s.length - 1
  var swapped = false
  while (i < j) {
    swapped = false
    val a = chars(i)
    val b = chars(j)
    if (lo(a) && j+1 < s.length && hi(chars(j+1))) {
      chars(j) = chars(j+1)
      chars(j+1) = a
      swapped = true
    }
    else chars(j) = a
    if (hi(b) && i > 0 && lo(chars(i-1))) {
      chars(i) = chars(i-1)
      chars(i-1) = b
      swapped = true
    }
    else chars(i) = b
    i += 1
    j -= 1
  }
  if (i==j) {
    val c = chars(i)
    if (lo(c) && j+1 < s.length && hi(chars(j+1))) {
      chars(j) = chars(j+1)
      chars(j+1) = c
    }
    else if (hi(c) && i > 0 && lo(chars(i-1))) {
      chars(i) = chars(i-1)
      chars(i-1) = c
    }
  }
  else if (!swapped && hi(chars(i)) && lo(chars(j))) {
    val temp = chars(i)
    chars(i) = chars(j)
    chars(j) = temp
  }
  new String(chars)
}