Slow Scala assert

懵懂的女人 提交于 2019-12-08 16:16:38

问题


We've been profiling our code recently and we've come across a few annoying hotspots. They're in the form

assert(a == b, a + " is not equal to " + b)

Because some of these asserts can be in code called a huge amount of times the string concat starts to add up. assert is defined as:

def assert(assumption : Boolean, message : Any) = ....

why isn't it defined as:

def assert(assumption : Boolean, message : => Any) = ....

That way it would evaluate lazily. Given that it's not defined that way is there an inline way of calling assert with a message param that is evaluated lazily?

Thanks


回答1:


Lazy evaluation has also some overhead for the function object created. If your message object is already fully constructed (a static message) this overhead is unnecessary.

The appropriate method for your use case would be sprintf-style:

assert(a == b,  "%s is not equal to %s", a, b)

As long as there is a speciaized function

assert(Boolean, String, Any, Any)

this implementation has no overhead or the cost of the var args array

assert(Boolean, String, Any*)

for the general case.

Implementing toString would be evaluated lazily, but is not readable:

assert(a == b, new { override def toString =  a + " is not equal to " + b })



回答2:


It is by-name, I changed it over a year ago.

http://www.scala-lang.org/node/825

Current Predef:

@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
  if (!assertion)
    throw new java.lang.AssertionError("assertion failed: "+ message)
}



回答3:


Thomas' answer is great, but just in case you like the idea of the last answer but dislike the unreadability, you can get around it:

object LazyS {
  def apply(f: => String): AnyRef = new {
    override def toString = f
  }
}

Example:

object KnightSpeak {
  override def toString = { println("Turned into a string") ; "Ni" }
}

scala> assert(true != false , LazyS("I say " + KnightSpeak))

scala> println( LazyS("I say " + KnightSpeak) )
Turned into a string
I say Ni



回答4:


Try: assert( a==b, "%s is not equals to %s".format(a,b)) The format should only be called when the assert needs the string. Format is added to RichString via implicit.



来源:https://stackoverflow.com/questions/2425091/slow-scala-assert

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!