mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[threading] IJPL-211115: Do not confine write actions to the limited dispatcher thread
GitOrigin-RevId: c43c94b56fd5970012966bacd90ca08717df2d8b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8bba46ffe1
commit
15ca1be9f9
+3
-4
@@ -21,7 +21,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.io.path.writeText
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.random.Random
|
||||
@@ -82,7 +81,7 @@ internal class PlatformReadWriteActionSupport : ReadWriteActionSupport {
|
||||
executeWriteActionOnEdt(stamp, readResult.action)
|
||||
}
|
||||
else {
|
||||
executeWriteActionOnBackgroundWithAtomicCheck(lock, stamp, undispatched, readResult.action)
|
||||
executeWriteActionOnBackgroundWithAtomicCheck(lock, stamp, readResult.action)
|
||||
}
|
||||
if (writeResult !== retryMarker) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -107,8 +106,8 @@ internal class PlatformReadWriteActionSupport : ReadWriteActionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <T> executeWriteActionOnBackgroundWithAtomicCheck(lock: ThreadingSupport, originalStamp: Long, undispatched: Boolean, action: () -> T): /*T or retryMarker */ Any? {
|
||||
val dispatcher = if (undispatched) EmptyCoroutineContext else Dispatchers.Default
|
||||
private suspend fun <T> executeWriteActionOnBackgroundWithAtomicCheck(lock: ThreadingSupport, originalStamp: Long, action: () -> T): /*T or retryMarker */ Any? {
|
||||
val dispatcher = Dispatchers.Default
|
||||
val ref = withContext(dispatcher + InternalThreading.RunInBackgroundWriteActionMarker) {
|
||||
lock.runWriteActionWithCheckInWriteIntent(
|
||||
{
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl
|
||||
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAndBackgroundWriteActionUndispatched
|
||||
import com.intellij.openapi.progress.Cancellation
|
||||
import com.intellij.openapi.progress.runBlockingMaybeCancellable
|
||||
import com.intellij.testFramework.junit5.StressTestApplication
|
||||
import com.intellij.tools.ide.metrics.benchmark.Benchmark
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
@StressTestApplication
|
||||
class ReadWriteActionPerformanceTest {
|
||||
|
||||
@Test
|
||||
fun readWriteActionBenchmark() {
|
||||
val dispatcher = Dispatchers.Default.limitedParallelism(1, "test limited dispatcher")
|
||||
Benchmark.newBenchmark("undispatched readAndWriteAction") {
|
||||
runBlockingMaybeCancellable {
|
||||
val canEnd = AtomicBoolean(false)
|
||||
launch(Dispatchers.Default) {
|
||||
while (!canEnd.get()) {
|
||||
launch(Dispatchers.EDT) {
|
||||
} // constant spam with write-intents
|
||||
}
|
||||
}
|
||||
repeat(100) { globalCounter ->
|
||||
launch(dispatcher) {
|
||||
val localCounter = AtomicInteger(0)
|
||||
readAndBackgroundWriteActionUndispatched {
|
||||
localCounter.incrementAndGet()
|
||||
val currentTime = System.currentTimeMillis()
|
||||
while (System.currentTimeMillis() - currentTime < 3) {
|
||||
Cancellation.checkCancelled()
|
||||
}
|
||||
writeAction {
|
||||
}
|
||||
}
|
||||
println("RA $globalCounter: $localCounter restarts")
|
||||
}
|
||||
}
|
||||
canEnd.set(true)
|
||||
}
|
||||
}
|
||||
.attempts(3)
|
||||
.start()
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -14,6 +14,7 @@ import org.junit.jupiter.api.RepeatedTest
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.assertContains
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
private const val REPETITIONS: Int = 100
|
||||
@@ -231,7 +232,8 @@ class SuspendingReadAndWriteActionTest {
|
||||
// contains because in debug mode coroutines append coroutine id
|
||||
assertContains(Thread.currentThread().name, name)
|
||||
writeAction {
|
||||
assertContains(Thread.currentThread().name, name)
|
||||
// DO NOT run write action in the inherited dispatcher; causes issues like `com.intellij.openapi.application.impl.ReadWriteActionPerformanceTest.readWriteActionBenchmark`
|
||||
assertFalse { Thread.currentThread().name.contains(name) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user