Skip to content

Commit

Permalink
Display time / LoC at the end
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Sep 20, 2024
1 parent 5b5814e commit eee60c2
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ package de.fraunhofer.aisec.cpg

import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.frontends.SupportsNewParse
import de.fraunhofer.aisec.cpg.frontends.SupportsParallelParsing
import de.fraunhofer.aisec.cpg.frontends.TranslationException
import de.fraunhofer.aisec.cpg.graph.Component
Expand All @@ -43,7 +44,10 @@ import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException
import java.util.concurrent.ExecutionException
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.io.path.absolute
import kotlin.io.path.readText
import kotlin.reflect.full.findAnnotation
import kotlin.time.DurationUnit
import org.slf4j.LoggerFactory

/** Main entry point for all source code translation for all language front-ends. */
Expand Down Expand Up @@ -116,6 +120,15 @@ private constructor(
}
}

log.info(
"Translated {} LoC in total ({} / LoC)",
result.stats.totalLinesOfCode,
(outerBench.duration / result.stats.totalLinesOfCode).toString(
DurationUnit.MILLISECONDS,
decimals = 3
)
)

return result
}

Expand Down Expand Up @@ -276,7 +289,7 @@ private constructor(
val future =
CompletableFuture.supplyAsync {
try {
return@supplyAsync parse(component, ctx, sourceLocation)
return@supplyAsync parse(component, result, ctx, sourceLocation)
} catch (e: TranslationException) {
throw RuntimeException("Error parsing $sourceLocation", e)
}
Expand Down Expand Up @@ -337,7 +350,7 @@ private constructor(

for (sourceLocation in sourceLocations) {
ctx.currentComponent = component
val f = parse(component, ctx, sourceLocation)
val f = parse(component, result, ctx, sourceLocation)
if (f != null) {
handleCompletion(result, usedFrontends, sourceLocation, f)
}
Expand Down Expand Up @@ -365,6 +378,7 @@ private constructor(
@Throws(TranslationException::class)
private fun parse(
component: Component,
result: TranslationResult,
ctx: TranslationContext,
sourceLocation: File,
): LanguageFrontend<*, *>? {
Expand All @@ -384,7 +398,30 @@ private constructor(
}
return null
}
component.addTranslationUnit(frontend.parse(sourceLocation))

// Check, if the frontend supports the new API
var tu =
if (frontend is SupportsNewParse) {
// Read the file contents and supply it to the frontend. This gives us a chance
// to do some statistics here, for example on the lines of code. For now, we
// just print it, in a future PR we will gather this information and consolidate
// it.
var path = sourceLocation.toPath().absolute()
var content = path.readText()
var linesOfCode = content.linesOfCode

log.info("{} has {} LoC", path, linesOfCode)

var tu = frontend.parse(content, path)

// Add the LoC. This needs to be synchronized on the stats object, because of
// parallel parsing
synchronized(result.stats) { result.stats.totalLinesOfCode += linesOfCode }
tu
} else {
frontend.parse(sourceLocation)
}
component.addTranslationUnit(tu)
} catch (ex: TranslationException) {
log.error("An error occurred during parsing of ${sourceLocation.name}: ${ex.message}")
if (config.failOnError) {
Expand Down Expand Up @@ -462,3 +499,12 @@ private constructor(
}
}
}

/**
* This returns a VERY trivial count of the lines of code (mainly just the line count). This can be
* extended to a real LoC algorithm at some point.
*/
val String.linesOfCode: Int
get() {
return this.count { it == '\n' }
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class TranslationResult(
return finalCtx
}

var stats = TranslationStats()

/**
* Checks if only a single software component has been analyzed and returns its translation
* units. For multiple software components, it aggregates the results.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, Fraunhofer AISEC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $$$$$$\ $$$$$$$\ $$$$$$\
* $$ __$$\ $$ __$$\ $$ __$$\
* $$ / \__|$$ | $$ |$$ / \__|
* $$ | $$$$$$$ |$$ |$$$$\
* $$ | $$ ____/ $$ |\_$$ |
* $$ | $$\ $$ | $$ | $$ |
* \$$$$$ |$$ | \$$$$$ |
* \______/ \__| \______/
*
*/
package de.fraunhofer.aisec.cpg

import de.fraunhofer.aisec.cpg.helpers.MeasurementHolder
import de.fraunhofer.aisec.cpg.helpers.StatisticsHolder

/**
* This class provides some statistics about our translation process. At some point this will fully
* replace [StatisticsHolder] and [MeasurementHolder]
*/
class TranslationStats {

/** The total lines of code that were translated into the CPG. */
var totalLinesOfCode: Int = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import java.nio.file.Path
import java.time.Duration
import java.time.Instant
import java.util.*
import kotlin.time.DurationUnit
import kotlin.time.toDuration
import org.slf4j.Logger
import org.slf4j.LoggerFactory

Expand Down Expand Up @@ -146,6 +148,7 @@ constructor(
) : MeasurementHolder(c, message, debug, holder) {

private val start: Instant
var duration: kotlin.time.Duration = kotlin.time.Duration.ZERO

/** Stops this benchmark and adds its measurement to the its [StatisticsHolder]. */
fun stop() {
Expand All @@ -154,14 +157,17 @@ constructor(

/** Stops the time and computes the difference between */
override fun addMeasurement(measurementKey: String?, measurementValue: String?): Any? {
val duration = Duration.between(start, Instant.now()).toMillis()
var duration = Duration.between(start, Instant.now()).toMillis()
measurements["${caller}: $message"] = "$duration ms"

logDebugMsg("$caller: $message done in $duration ms")

// update our holder, if we have any
holder?.addBenchmark(this)

// update our internal duration so that others can access it
this.duration = duration.toDuration(DurationUnit.MILLISECONDS)

return duration
}

Expand Down

0 comments on commit eee60c2

Please sign in to comment.