简体   繁体   English

android kotlin - 是 Function 参考因反射而变慢?

[英]android kotlin - are Function References slow due to reflection?

Reflection is suppose to be a bit time consuming on android.反射在 android 上被认为有点耗时。 so i was wondering given a function reference like this:所以我想知道这样的 function 参考:

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd))

is ::isOdd call an unnecessary burden? ::isOdd调用是不必要的负担吗?

would it be more efficient to not use them?不使用它们会更有效吗?

UPDATE : doing some light metrics i did the following:更新:做一些轻量级我做了以下:

    class MainActivity : Activity() {

    val numbers = listOf(1, 2, 3)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        doRegular()
        doReflection()
    }

    fun isOdd(x: Int) = x % 2 != 0

    fun doRegular() {
        val start = System.currentTimeMillis()
        for (i in 0..999999) {
            numbers.filter { it % 2 != 0 }
        }
        Log.v("myTag", "regular: +${System.currentTimeMillis() - start}")
    }

    fun doReflection() {
        val start = System.currentTimeMillis()
        for (i in 0..999999) {
            numbers.filter(::isOdd)
        }
        Log.v("myTag", "reflection: ${System.currentTimeMillis() - start}")
    }
}

and the print statement results are:打印语句结果为:

//*****this was the first attempt before compiler could optimise anything
        regular: +577     
        reflection: 318
  //*********
  
    regular: +376
    reflection: 327
    
    regular: +593
     reflection: 343
    
     regular: +417
     reflection: 251
     
     regular: +243
     reflection: 238
     
     regular: +241
     reflection: 238
     
     regular: +238
     reflection: 237
     
     regular: +235
     reflection: 247
     
     regular: +237
     reflection: 247
     
     regular: +230
     reflection: 268

What would you conclude given these results?鉴于这些结果,你会得出什么结论?

update: some are asking why i think its using reflection.更新:有些人问我为什么认为它使用反射。 its based on this:它基于此:

This stackoverflow answer seems to state its reflection: and the title for the official doc has reflection as the main heading: hence my confusion.这个 stackoverflow 的答案似乎 state 它的反射:官方文档的标题以反射为主要标题:因此我感到困惑。

Function references don't use reflection, they're like accessing a field, but for functions. Function 引用不使用反射,它们就像访问一个字段,但用于函数。

As such, these references are solved during compile time.因此,这些引用在编译时解决。 If you made a mistake like misspelling the function name it won't compile.如果您犯了错误,例如拼错 function 名称,它将无法编译。 Where reflection for finding and calling the same misspelled function would fail at run time.查找和调用相同拼写错误的 function 的反射将在运行时失败。

Surely ::isOdd is used for referencing the function, but unless it is really required to use the "reflection", it (reflection) is not used.当然::isOdd用于引用 function,但除非确实需要使用“反射”,否则不使用它(反射)。 Similar to how Int are changed into int in the bytecode unless we need to store the reference, if we create collections then only it is represented as java.lang.Integer .类似于在字节码中将 Int 更改为int ,除非我们需要存储引用,如果我们创建 collections 则仅表示为java.lang.Integer

The Kotlin compiler is smart and does the trick behind the hood. Kotlin 编译器很聪明,可以在幕后解决问题。

/**
 * Returns a list containing only elements matching the given [predicate].
 * 
 * @sample samples.collections.Collections.Filtering.filter
 */
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}

The filter function is inline function that embeds the lambda/reference directly at the call-site without actually using the reflection.过滤器 function 是内联 function ,它直接在调用站点嵌入 lambda/引用,而不实际使用反射。

If you see the JVM bytecode, you'll see the following decompiled Java code:如果您看到 JVM 字节码,您将看到以下反编译的 Java 代码:

// of numbers.filter { it % 2 != 0 }
while(var6.hasNext()) {
    Object element$iv$iv = var6.next();
    int it = ((Number)element$iv$iv).intValue();
    int var9 = false;
    if (it % 2 != 0) {              // <- check this out
        destination$iv$iv.add(element$iv$iv);
    }
}

// of numbers.filter(::isOdd)
while(var6.hasNext()) {
    Object element$iv$iv = var6.next();
    int p1 = ((Number)element$iv$iv).intValue();
    int var9 = false;
    if (isOdd(p1)) {                  // <- check this out
        destination$iv$iv.add(element$iv$iv);
    }
}

Realistically there is no reflection is involved here.实际上,这里没有涉及反射。

Sidenote: I've had a similar question over the official Kotlinlang slack at here , and I've got much attention but only 1 reply regarding it is only about metafacory as stated here in softwareengineering stackexchange subdomain .旁注:我在这里的官方 Kotlinlang slack 上有一个类似的问题,我得到了很多关注,但只有 1 条关于它的回复只是关于 metafacory,如软件工程 stackexchange 子域中所述。

Here's a ss:这是一个ss: 在此处输入图像描述

I would say that the best way to figure this out is to time it, Although.我想说,解决这个问题的最好方法是计时,虽然。 I would expect that Reflection would be more time consuming.我希望反射会更耗时。

val numbers = listOf(1, 2, 3)

fun isOdd(x: Int) = x % 2 != 0

fun doRegular() {
    val start = System.currentTimeMillis()
    for (i in 0..999999) {
        numbers.filter { it % 2 != 0 }
    }
    println(System.currentTimeMillis() - start)
}

fun doReflection() {
    val start = System.currentTimeMillis()
    for (i in 0..999999) {
        numbers.filter(::isOdd)
    }
    println(System.currentTimeMillis() - start)
}

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

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