@@ -4,40 +4,46 @@ import com.intellij.openapi.components.Service
44import com.intellij.openapi.project.Project
55import org.digma.intellij.plugin.common.FrequencyDetector
66import org.digma.intellij.plugin.posthog.ActivityMonitor
7- import java.util.concurrent.ConcurrentHashMap
7+ import java.util.Collections
88import kotlin.math.max
99import kotlin.time.Duration.Companion.minutes
1010import kotlin.time.toJavaDuration
1111
1212
1313@Service(Service .Level .PROJECT )
14- class ApiPerformanceMonitor (private val project : Project ) {
14+ class ApiPerformanceMonitor (private val project : Project ) {
1515
1616 private val frequencyDetector = FrequencyDetector (10 .minutes.toJavaDuration())
1717
18- private val durations = ConcurrentHashMap (mutableMapOf<String ,Long >())
18+ private val durations = Collections .synchronizedMap (mutableMapOf<String , Long >())
1919
20+ // this method is not thread safe. max duration for apiName may not be the real max if two threads for
21+ // the same apiName run concurrently, and they have different durations.
22+ // it's not a bug just not completely accurate reporting.
23+ // the only way to make it accurate is to lock the code that computes max and puts it in the durations map.
24+ // but locking means that threads will wait for each other.
25+ // it's possible to execute this code in a coroutine, and then It's ok to lock, but the error is minor and doesn't
26+ // worth the complexity of a coroutine.
2027 fun addPerformance (apiName : String , duration : Long ) {
2128 if (duration < 2000 ) {
2229 return
2330 }
2431
25- durations[apiName] = max(duration, durations[apiName] ? : 0L )
32+ val max = max(duration, durations[apiName] ? : 0L )
33+ durations[apiName] = max
2634
27- durations[apiName]?.let {
28- report(apiName, it)
29- }
35+ report(apiName, max)
3036 }
3137
3238 private fun report (apiName : String , duration : Long ) {
33- if (frequencyDetector.isTooFrequentMessage(apiName)){
39+ if (frequencyDetector.isTooFrequentMessage(apiName)) {
3440 return
3541 }
3642
3743 // reset the max duration before reporting, new one will be collected
3844 durations[apiName] = 0L
3945
40- val details = mutableMapOf<String ,Any >(
46+ val details = mutableMapOf<String , Any >(
4147 " api name" to apiName,
4248 " duration" to duration
4349 )
0 commit comments