简体   繁体   English

Scala 中的方法调用反射会导致性能下降吗?

[英]Will method invocation reflection in Scala cause performance degradation?

I have a method intended to do some simple statistics for data IO, as shown below.我有一个方法打算对数据IO做一些简单的统计,如下图。

def ioStatSink[T <: { def length: Int }](): Sink[T, Future[(Long, Long)]] = Sink.fold((0L, 0L))((acc, bytes) => (acc._1 + 1L, acc._2 + bytes.length))

As I want it to be able to handle different data types that have a { def length: Int } method, I make it generic.因为我希望它能够处理具有{ def length: Int }方法的不同数据类型,所以我使它成为通用的。
The problem is, this method invocation uses reflection.问题是,这个方法调用使用了反射。
As this method is called millions fo times, I don't want it to have performance issue.由于此方法被称为数百万次,因此我不希望它出现性能问题。
I know class instantiation with reflection has performance penalty, but how about this method invocation?我知道使用反射的类实例化有性能损失,但是这个方法调用怎么样?

(another issue about the method is, it cannot adapt to types with a method of { def length: Long } , any suggestion to deal with this?) (关于该方法的另一个问题是,它不能适应具有{ def length: Long }方法的类型,有什么建议可以解决这个问题?)

Since you said you were interested in the typeclass alternative.既然你说你对typeclass替代品感兴趣。
Here is a simple demo.这是一个简单的演示。

import scala.language.higherKinds

trait Sizeable[T] {
  def size(t: T): Long
}

object Sizeable {
  private final val _IterableOnceSizable: Sizeable[IterableOnce[_]] =
    new Sizeable[IterableOnce[_]] {
      override final def size(iter: IterableOnce[_]): Long = {
        val knownSize = iter.knownSize
        if (knownSize == -1) iter.iterator.size.toLong
        else knownSize.toLong
      }
    }

  implicit final def CollectionSizeable[C[_], T](implicit ev: C[T] <:< IterableOnce[T]): Sizeable[C[T]] =
    _IterableOnceSizable.asInstanceOf[Sizeable[C[T]]]
}

object syntax {
  object sizeable {
    implicit class SizeableOps[T](private val sizable: T) extends AnyVal {
      @inline def size(implicit ev: Sizeable[T]): Long =
        ev.size(sizable)

      @inline def length(implicit ev: Sizeable[T]): Long =
        ev.size(sizable)
    }
  }
}

import syntax.sizeable._

def ioStatSink[T : Sizeable](): Sink[T, Future[(Long, Long)]] =
  Sink.fold((0L, 0L))((acc, bytes) => (acc._1 + 1L, acc._2 + bytes.length))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM