From 3eb03a9b3ac2debc12a1642f73962d3f8fce23c5 Mon Sep 17 00:00:00 2001 From: "kirill.skrygan" Date: Fri, 12 Jun 2020 00:20:54 +0300 Subject: [PATCH] improve writeLock monitor to track write action themselves warn for all main thread actions under foreign cientId intern paths and other strings in solution model GitOrigin-RevId: 80d124e17e835e47af23183f98961c5e5e7bff18 --- .../src/com/intellij/codeWithMe/ClientId.kt | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/platform/core-api/src/com/intellij/codeWithMe/ClientId.kt b/platform/core-api/src/com/intellij/codeWithMe/ClientId.kt index 024df89be1d6..eb719d0da63b 100644 --- a/platform/core-api/src/com/intellij/codeWithMe/ClientId.kt +++ b/platform/core-api/src/com/intellij/codeWithMe/ClientId.kt @@ -1,6 +1,8 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeWithMe +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.diagnostic.Logger import com.intellij.util.Processor import java.util.concurrent.Callable import java.util.function.BiConsumer @@ -26,6 +28,8 @@ data class ClientId(val value: String) { } companion object { + + val logger = Logger.getInstance(ClientId::class.java) /** * Default client id for local application */ @@ -116,10 +120,21 @@ data class ClientId(val value: String) { @JvmStatic inline fun withClientId(clientId: ClientId?, action: () -> T): T { val clientIdStore = ClientIdValueStoreService.tryGetInstance() ?: return action() + + val foreignMainThreadActivity = ApplicationManager.getApplication().isDispatchThread && !clientId.isLocal val old = clientIdStore.value try { clientIdStore.value = clientId?.value - return action() + if (foreignMainThreadActivity) { + val beforeActionTime = System.currentTimeMillis() + val result = action() + val delta = System.currentTimeMillis() - beforeActionTime + if (delta > 300) { + logger.warn("LONG MAIN THREAD ACTIVITY by ${clientId?.value}. Stack trace:\n${getStackTrace()}") + } + return result + } else + return action() } finally { clientIdStore.value = old } @@ -160,4 +175,14 @@ data class ClientId(val value: String) { return Processor { withClientId(currentId) { processor.process(it) } } } } +} + +fun getStackTrace(): String { + val builder = StringBuilder() + val trace = Thread.currentThread().stackTrace + for (element in trace) { + with(builder) { append("\tat $element\n") } + } + + return builder.toString() } \ No newline at end of file