@@ -36,7 +36,7 @@ import java.nio.file.LinkOption
3636import java.nio.file.Paths
3737import java.util.concurrent.CompletableFuture
3838import java.util.concurrent.CompletionException
39- import kotlin.math.ceil
39+ import java.util.concurrent.ConcurrentLinkedQueue
4040
4141class GCCJSONCoverageGenerator (private val myGcov : String , private val myMajorVersion : Int ) : CoverageGenerator {
4242
@@ -391,21 +391,56 @@ class GCCJSONCoverageGenerator(private val myGcov: String, private val myMajorVe
391391
392392 val files = try {
393393 if (! CoverageGeneratorSettings .getInstance().branchCoverageEnabled) {
394- processFiles(filesToProcess, env, project)
394+ filesToProcess.mapNotNull {
395+ processFile(it, env, project)
396+ }
395397 } else {
396- DumbService .getInstance(project).runReadActionInSmartMode<List <CoverageFileData >> {
397- filesToProcess.chunked(ceil(filesToProcess.size / Thread .activeCount().toDouble()).toInt()).map {
398+
399+ val lineAssoc = System .nanoTime()
400+ val functionsToProcess = filesToProcess.flatMap { file ->
401+ val linesOfFunction = file.lines.groupBy { it.functionName }
402+ val list = file.functions.map {
403+ Triple (file, it, linesOfFunction[it.name] ? : emptyList())
404+ }
405+ list
406+ }.sortedByDescending {
407+ it.third.size
408+ }
409+ log.info(" Line assoc took ${System .nanoTime() - lineAssoc} ns" )
410+
411+ val parallelGen = System .nanoTime()
412+ val queue = ConcurrentLinkedQueue (functionsToProcess)
413+ val result = DumbService .getInstance(project).runReadActionInSmartMode<List <CoverageFileData >> {
414+ (0 until Thread .activeCount()).map {
398415 CompletableFuture .supplyAsync {
399416 runReadAction {
400- var list = emptyList< CoverageFileData >()
417+ val map = mutableListOf< Pair < File , CoverageFunctionData > >()
401418 ProgressManager .getInstance().executeProcessUnderProgress({
402- list = processFiles(it, env, project)
419+ generateSequence { queue.poll() }.forEach {
420+ map.add(
421+ it.first
422+ to
423+ processFunction(
424+ it.first,
425+ it.second,
426+ it.third,
427+ env,
428+ project
429+ )
430+ )
431+ }
403432 }, indicator)
404- list
433+ map
405434 }
406435 }
407- }.flatMap { it.join() }
436+ }.flatMap { it.get() }.groupBy { it.first }.map { entry ->
437+ CoverageFileData (
438+ env.toLocalPath(entry.key.file).replace(' \\ ' , ' /' ),
439+ entry.value.map { it.second }.associateBy { it.functionName })
440+ }
408441 }
442+ log.info(" Parallel branch gen took ${System .nanoTime() - parallelGen} ns" )
443+ result
409444 }.associateBy { it.filePath }
410445 } catch (e: CompletionException ) {
411446 val cause = e.cause
@@ -424,29 +459,39 @@ class GCCJSONCoverageGenerator(private val myGcov: String, private val myMajorVe
424459 )
425460 }
426461
427- private fun processFiles (
428- files : List <File >,
462+ private fun processFunction (
463+ file : File ,
464+ function : Function ,
465+ lines : List <Line >,
429466 env : CPPEnvironment ,
430467 project : Project
431- ) = files.filter { it.lines.isNotEmpty() || it.functions.isNotEmpty() }.map { file ->
468+ ) = CoverageFunctionData (
469+ function.startLine.toInt() toCP 0 ,
470+ function.endLine.toInt() toCP 0 ,
471+ function.demangledName,
472+ FunctionLineData (lines.associate { it.lineNumber.toInt() to it.count.toLong() }),
473+ if (CoverageGeneratorSettings .getInstance().branchCoverageEnabled)
474+ findStatementsForBranches(
475+ lines,
476+ env.toLocalPath(file.file),
477+ project
478+ ) else emptyList()
479+ )
480+
481+ private fun processFile (
482+ file : File ,
483+ env : CPPEnvironment ,
484+ project : Project
485+ ): CoverageFileData ? {
486+ if (file.lines.isEmpty() && file.functions.isEmpty()) {
487+ return null
488+ }
432489 val linesOfFunction = file.lines.groupBy { it.functionName }
433490 val functions = file.functions.map { function ->
434- ProgressManager .checkCanceled()
435491 val lines = linesOfFunction[function.name] ? : emptyList()
436- CoverageFunctionData (
437- function.startLine.toInt() toCP 0 ,
438- function.endLine.toInt() toCP 0 ,
439- function.demangledName,
440- FunctionLineData (lines.associate { it.lineNumber.toInt() to it.count.toLong() }),
441- if (CoverageGeneratorSettings .getInstance().branchCoverageEnabled)
442- findStatementsForBranches(
443- lines,
444- env.toLocalPath(file.file),
445- project
446- ) else emptyList()
447- )
492+ processFunction(file, function, lines, env, project)
448493 }.associateBy { it.functionName }
449- CoverageFileData (env.toLocalPath(file.file).replace(' \\ ' , ' /' ), functions)
494+ return CoverageFileData (env.toLocalPath(file.file).replace(' \\ ' , ' /' ), functions)
450495 }
451496
452497 private data class Root (
0 commit comments