Index diagnostic: calculate percentage of total indexing/content loading time (per file type).

GitOrigin-RevId: 37adaab5595e5b556fef3ce25833770c81641ee0
This commit is contained in:
Sergey Patrikeev
2020-05-27 01:00:35 +03:00
committed by intellij-monorepo-bot
parent 0732bbb74e
commit 5621caab84
3 changed files with 55 additions and 21 deletions
@@ -41,6 +41,7 @@ data class JsonTime(val nano: Long) {
@JsonSerialize(using = JsonTimeStats.Companion::class)
data class JsonTimeStats(
val partOfTotal: Int, // Percentages: 0 to 100.
val minTime: JsonTime,
val maxTime: JsonTime,
val meanTime: JsonTime,
@@ -49,6 +50,13 @@ data class JsonTimeStats(
companion object : JsonSerializer<JsonTimeStats>() {
override fun serialize(value: JsonTimeStats, gen: JsonGenerator, serializers: SerializerProvider?) {
val s = buildString {
append("part: ")
if (value.partOfTotal < 1) {
append("< 1%; ")
}
else {
append("${value.partOfTotal}%; ")
}
append("max: ${value.maxTime.presentableDuration()}; ")
append("mean: ${value.meanTime.presentableDuration()}; ")
append("median: ${value.medianTime.presentableDuration()}; ")
@@ -59,11 +67,18 @@ data class JsonTimeStats(
}
}
fun TimeStats.toTimeStats(): JsonTimeStats? {
fun TimeStats.toTimeStats(totalTime: TimeNano): JsonTimeStats? {
if (isEmpty) {
return null
}
val partOfTotal = if (totalTime == 0L) {
100
}
else {
((sumTime.toDouble() / totalTime) * 100).toInt()
}
return JsonTimeStats(
partOfTotal,
JsonTime(minTime),
JsonTime(maxTime),
JsonTime(meanTime.toLong()),
@@ -85,7 +100,6 @@ private fun <N : Number> getMedianOfArray(elements: Collection<N>): Double {
data class JsonFileProviderIndexStatistics(
val providerName: String,
val totalNumberOfFiles: Int,
// <total time> = <content loading time> + <indexing time> + <time spent on waiting for other indexing tasks to complete>
val totalIndexingTime: JsonTime,
val statsPerFileType: List<StatsPerFileType>,
val statsPerIndexer: List<StatsPerIndexer>,
@@ -110,17 +124,35 @@ data class JsonFileProviderIndexStatistics(
}
fun FileProviderIndexStatistics.convertToJson(): JsonFileProviderIndexStatistics {
val statsPerFileType = indexingStatistics.numberOfFilesPerFileType
.mapNotNull { (fileTypeName, numberOfFiles) ->
val indexingTimeStats = indexingStatistics.indexingTimesPerFileType[fileTypeName]?.toTimeStats() ?: return@mapNotNull null
val contentLoadingTimeStats = indexingStatistics.contentLoadingTimesPerFileType[fileTypeName]?.toTimeStats() ?: return@mapNotNull null
JsonFileProviderIndexStatistics.StatsPerFileType(fileTypeName, numberOfFiles, indexingTimeStats, contentLoadingTimeStats)
val totalCpuIndexingTime = indexingStatistics.statsPerFileType.values
.filterNot { it.indexingTime.isEmpty }
.map { it.indexingTime.sumTime }
.sum()
val totalCpuLoadingTime = indexingStatistics.statsPerFileType.values
.filterNot { it.contentLoadingTime.isEmpty }
.map { it.contentLoadingTime.sumTime }
.sum()
val totalCpuIndexingTimePerIndexer = indexingStatistics.timesPerIndexer.values
.filterNot { it.isEmpty }
.map { it.sumTime }
.sum()
val statsPerFileType = indexingStatistics.statsPerFileType
.mapNotNull { (fileTypeName, stats) ->
JsonFileProviderIndexStatistics.StatsPerFileType(
fileTypeName,
stats.numberOfFiles,
stats.indexingTime.toTimeStats(totalCpuIndexingTime) ?: return@mapNotNull null,
stats.contentLoadingTime.toTimeStats(totalCpuLoadingTime) ?: return@mapNotNull null
)
}
val totalNumberOfFiles = statsPerFileType.asSequence().map { it.numberOfFiles }.sum()
val allStatsPerIndexer = indexingStatistics.timesPerIndexer
.mapNotNull {
val timeStats = it.value.toTimeStats() ?: return@mapNotNull null
val timeStats = it.value.toTimeStats(totalCpuIndexingTimePerIndexer) ?: return@mapNotNull null
JsonFileProviderIndexStatistics.StatsPerIndexer(it.key, timeStats)
}
.sortedByDescending { it.indexingTimeStats.maxTime.nano }
@@ -7,19 +7,17 @@ class IndexingJobStatistics {
val timesPerIndexer: Map<String /* ID.name() */, TimeStats>
get() = _timesPerIndexer
val indexingTimesPerFileType: Map<String /* File type name */, TimeStats>
get() = _indexingTimesPerFileType
val statsPerFileType: Map<String /* File type name */, StatsPerFileType>
get() = _statsPerFileType
val contentLoadingTimesPerFileType: Map<String /* File type name */, TimeStats>
get() = _contentLoadingTimesPerFileType
val numberOfFilesPerFileType: Map<String /* File type name */, Int>
get() = _numberOfFilesPerFileType
data class StatsPerFileType(
val indexingTime: TimeStats,
val contentLoadingTime: TimeStats,
var numberOfFiles: Int
)
private val _timesPerIndexer = hashMapOf<String, TimeStats>()
private val _indexingTimesPerFileType = hashMapOf<String, TimeStats>()
private val _contentLoadingTimesPerFileType = hashMapOf<String, TimeStats>()
private val _numberOfFilesPerFileType = hashMapOf<String, Int>()
private val _statsPerFileType = hashMapOf<String, StatsPerFileType>()
@Synchronized
fun addFileStatistics(fileStatistics: FileIndexingStatistics, contentLoadingTime: Long) {
@@ -27,8 +25,11 @@ class IndexingJobStatistics {
_timesPerIndexer.getOrPut(indexId.name) { TimeStats(timeBucketSize) }.addTime(time)
}
val fileTypeName = fileStatistics.fileType.name
_numberOfFilesPerFileType.compute(fileTypeName) { _, currentNumber -> (currentNumber ?: 0) + 1 }
_indexingTimesPerFileType.computeIfAbsent(fileTypeName) { TimeStats(timeBucketSize) }.addTime(fileStatistics.indexingTime)
_contentLoadingTimesPerFileType.computeIfAbsent(fileTypeName) { TimeStats(timeBucketSize) }.addTime(contentLoadingTime)
val stats = _statsPerFileType.computeIfAbsent(fileTypeName) {
StatsPerFileType(TimeStats(timeBucketSize), TimeStats(timeBucketSize), 0)
}
stats.contentLoadingTime.addTime(contentLoadingTime)
stats.indexingTime.addTime(fileStatistics.indexingTime)
stats.numberOfFiles++
}
}
@@ -32,6 +32,7 @@ class TimeStats(private val sizeLimit: Int) {
private fun failEmpty(): Nothing = throw IllegalStateException("No times have been added yet")
val isEmpty: Boolean @Synchronized get() = _maxNTimes.isEmpty()
val sumTime: TimeNano @Synchronized get() = _sum ?: failEmpty()
val minTime: TimeNano @Synchronized get() = _minTime ?: failEmpty()
val maxTime: TimeNano @Synchronized get() = _maxTime ?: failEmpty()
val meanTime: Double @Synchronized get() = (_sum ?: failEmpty()).toDouble() / (_count ?: failEmpty())