kotlin 在内部创建匿名对象的忙碌loop调用函数会产生开销吗?

de90aj5v  于 7个月前  发布在  Kotlin
关注(0)|答案(1)|浏览(95)

我正在使用Android创建一个Kotlin应用。我使用suspendCoroutine将回调API转换为suspend function。目前我有以下代码。

while(true){
   newSuspendFunction().let{ value ->
     //do some simple work
   }

   yield()
}

字符串
我的newSuspendFunction沿着在

suspend fun newSuspendFunction() {
  suspendCoroutine { cont ->
     InterfaceWithCallback { value ->
        cont.resume(value)
     }.let { myInterfaceWithCallback ->
        registerInterfaceWithCallback(myInterfaceWithCallback)
     }
  }
}


问题是,这是否会引入运行时开销并在每次调用函数时重新示例化InterfaceWithCallback,或者它是否会在内存中的某个位置创建一个单例并执行优化?

**编辑:**我需要转换一个多镜头API,所以callbackFlow是一个有效的解决方案。

jq6vz3qz

jq6vz3qz1#

每次调用newSuspendFunction都会创建一个新的InterfaceWithCallback示例,因为lambda捕获了延续cont,这在每次调用suspendCoroutine时都不同。
尽管如此,这并不意味着这个开销会很大。短生存期的对象对垃圾收集器来说可能不是一个大问题。你需要衡量这是否真的对性能有可衡量的影响。
此外,循环中不需要yield(),因为newSuspendFunction已经是一个实际挂起的挂起函数。
最后但并非最不重要的一点是,为什么要调用这些.let?我发现在可能的情况下避免嵌套块更容易阅读。你可以使用变量而不是let:)
编辑:现在,你的用例似乎需要一个Flow而不是一个suspend函数,因为你的回调被重复调用。你可以使用callbackFlow来 Package 你的基于回调的API:

// replace Int with whatever type you're dealing with
fun someUsefulName(): Flow<Int> = callbackFlow {
    val callback = InterfaceWithCallback { value ->
        trySendBlocking(value)
    }
    registerInterfaceWithCallback(callback)

    // suspends until the flow collector is cancelled, and unregisters
    awaitClose {
        // there should be some kind of 'unregister' counterpart
        unregisterInterfaceWithCallback(callback)
    }
}

字符串
作为参考,这里是newSuspendFunction的反编译字节码,你可以在这里看到new MainJvmKt$newSuspendFunction$2$1(cont)

@Nullable
public static final Object newSuspendFunction(@NotNull Continuation $completion) {
    SafeContinuation var2 = new SafeContinuation(IntrinsicsKt.intercepted($completion));
    Continuation cont = (Continuation)var2;
    int var4 = false;
    MainJvmKt$newSuspendFunction$2$1 var5 = new MainJvmKt$newSuspendFunction$2$1(cont);
    InterfaceWithCallback myInterfaceWithCallback = (InterfaceWithCallback)var5;
    int var7 = false;
    registerInterfaceWithCallback(myInterfaceWithCallback);
    Object var10000 = var2.getOrThrow();
    if (var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
        DebugProbesKt.probeCoroutineSuspended($completion);
    }

    return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;
}

@Metadata(
   mv = {1, 9, 0},
   k = 3,
   d1 = {"\u0000\u000e\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\b\n\u0000\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0003H\n¢\u0006\u0002\b\u0004"},
   d2 = {"<anonymous>", "", "value", "", "callback"}
)
final class MainJvmKt$newSuspendFunction$2$1 implements InterfaceWithCallback {
   // $FF: synthetic field
   final Continuation $cont;

   public final void callback(int value) {
      Continuation var2 = this.$cont;
      Integer var3 = value;
      Result.Companion var10001 = Result.Companion;
      var2.resumeWith(Result.constructor-impl(var3));
   }

   MainJvmKt$newSuspendFunction$2$1(Continuation var1) {
      this.$cont = var1;
   }
}


这里假设InterfaceWithCallback声明为:

fun interface InterfaceWithCallback {
    fun callback(value: Int)
}

相关问题