mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 00:17:11 -07:00
Thread report for parallel builds.
This commit is contained in:
parent
2b4fcb4cec
commit
89d2239209
6 changed files with 127 additions and 8 deletions
|
@ -117,3 +117,47 @@ class AsciiArt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AsciiTable {
|
||||||
|
class Builder {
|
||||||
|
private val headers = arrayListOf<String>()
|
||||||
|
fun header(name: String) = headers.add(name)
|
||||||
|
fun headers(vararg names: String) = headers.addAll(names)
|
||||||
|
|
||||||
|
private val widths = arrayListOf<Int>()
|
||||||
|
fun width(w: Int) : Builder {
|
||||||
|
widths.add(w)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private val rows = arrayListOf<List<String>>()
|
||||||
|
fun addRow(row: List<String>) = rows.add(row)
|
||||||
|
|
||||||
|
private fun col(width: Int, s: String) : String {
|
||||||
|
val format = " %1\$-${width.toString()}s"
|
||||||
|
val result = String.format(format, s)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
val vb = AsciiArt.verticalBar
|
||||||
|
fun build() : String {
|
||||||
|
val formattedHeaders =
|
||||||
|
headers.mapIndexed { index, s ->
|
||||||
|
val s2 = col(widths[index], s)
|
||||||
|
s2
|
||||||
|
}.joinToString(vb)
|
||||||
|
val result = buildString {
|
||||||
|
append(AsciiArt.logBox(formattedHeaders, AsciiArt.bottomLeft2, AsciiArt.bottomRight2))
|
||||||
|
}
|
||||||
|
var lineLength = 0
|
||||||
|
rows.forEachIndexed { index, row ->
|
||||||
|
val formattedRow = row.mapIndexed { i, s -> col(widths[i], s) }.joinToString(vb)
|
||||||
|
val line = vb + " " + formattedRow + " " + vb
|
||||||
|
AsciiArt.defaultLog(line)
|
||||||
|
lineLength = line.length
|
||||||
|
}
|
||||||
|
AsciiArt.defaultLog(AsciiArt.lowerBox(lineLength - 4))
|
||||||
|
return result.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ResolveDependency @Inject constructor(
|
||||||
val seen = hashSetOf(dep.id)
|
val seen = hashSetOf(dep.id)
|
||||||
root.addChildren(findChildren(root, seen))
|
root.addChildren(findChildren(root, seen))
|
||||||
|
|
||||||
AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" }, print = {s -> println(s) })
|
AsciiArt.logBox(listOf(dep.id, url, dep.jarFile.get()).map { " $it" })
|
||||||
|
|
||||||
display(root.children)
|
display(root.children)
|
||||||
println("")
|
println("")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.beust.kobalt.internal
|
package com.beust.kobalt.internal
|
||||||
|
|
||||||
|
import com.beust.kobalt.AsciiTable
|
||||||
import com.beust.kobalt.KobaltException
|
import com.beust.kobalt.KobaltException
|
||||||
import com.beust.kobalt.TaskResult
|
import com.beust.kobalt.TaskResult
|
||||||
import com.beust.kobalt.misc.NamedThreadFactory
|
import com.beust.kobalt.misc.NamedThreadFactory
|
||||||
|
@ -162,6 +163,8 @@ interface IWorker<T> : Callable<TaskResult2<T>> {
|
||||||
*/
|
*/
|
||||||
// val tasks : List<T>
|
// val tasks : List<T>
|
||||||
|
|
||||||
|
val name: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the priority of this task.
|
* @return the priority of this task.
|
||||||
*/
|
*/
|
||||||
|
@ -181,11 +184,16 @@ interface IThreadWorkerFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadWorkerFactory<T>,
|
class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadWorkerFactory<T>,
|
||||||
threadCount: Int = 1) {
|
val threadCount: Int = 1) {
|
||||||
val executor : ExecutorService
|
val executor : ExecutorService
|
||||||
= Executors.newFixedThreadPool(threadCount, NamedThreadFactory("DynamicGraphExecutor"))
|
= Executors.newFixedThreadPool(threadCount, NamedThreadFactory("DynamicGraphExecutor"))
|
||||||
val completion = ExecutorCompletionService<TaskResult2<T>>(executor)
|
val completion = ExecutorCompletionService<TaskResult2<T>>(executor)
|
||||||
|
|
||||||
|
class HistoryLog(val name: String, val timestamp: Long, val threadId: Long, val start: Boolean)
|
||||||
|
|
||||||
|
val historyLog = arrayListOf<HistoryLog>()
|
||||||
|
val threadIds = ConcurrentHashMap<Long, Long>()
|
||||||
|
|
||||||
fun run() : TaskResult {
|
fun run() : TaskResult {
|
||||||
try {
|
try {
|
||||||
return run2()
|
return run2()
|
||||||
|
@ -201,7 +209,24 @@ class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadW
|
||||||
val newFreeNodes = HashSet<T>(graph.freeNodes)
|
val newFreeNodes = HashSet<T>(graph.freeNodes)
|
||||||
while (failedResult == null && (running > 0 || newFreeNodes.size > 0)) {
|
while (failedResult == null && (running > 0 || newFreeNodes.size > 0)) {
|
||||||
nodesRun.addAll(newFreeNodes)
|
nodesRun.addAll(newFreeNodes)
|
||||||
val callables : List<IWorker<T>> = factory.createWorkers(newFreeNodes)
|
val callables : List<IWorker<T>> = factory.createWorkers(newFreeNodes).map {
|
||||||
|
it -> object: IWorker<T> {
|
||||||
|
override val priority: Int
|
||||||
|
get() = it.priority
|
||||||
|
|
||||||
|
override val name: String get() = it.name
|
||||||
|
override fun call(): TaskResult2<T> {
|
||||||
|
val threadId = Thread.currentThread().id
|
||||||
|
historyLog.add(HistoryLog(it.name, System.currentTimeMillis(), threadId,
|
||||||
|
start = true))
|
||||||
|
threadIds.put(threadId, threadId)
|
||||||
|
val result = it.call()
|
||||||
|
historyLog.add(HistoryLog(it.name, System.currentTimeMillis(), Thread.currentThread().id,
|
||||||
|
start = false))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
callables.forEach { completion.submit(it) }
|
callables.forEach { completion.submit(it) }
|
||||||
running += callables.size
|
running += callables.size
|
||||||
|
|
||||||
|
@ -241,6 +266,51 @@ class DynamicGraphExecutor<T>(val graph : DynamicGraph<T>, val factory: IThreadW
|
||||||
}
|
}
|
||||||
return if (failedResult != null) failedResult else TaskResult()
|
return if (failedResult != null) failedResult else TaskResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dumpHistory() {
|
||||||
|
log(1, "Thread report")
|
||||||
|
|
||||||
|
fun col1(s: String) = String.format(" %1\$-8s", s)
|
||||||
|
fun col2(s: String) = String.format(" %1\$-25s", s)
|
||||||
|
|
||||||
|
val table = AsciiTable.Builder()
|
||||||
|
.width(11)
|
||||||
|
threadIds.keys.forEach {
|
||||||
|
table.width(20)
|
||||||
|
}
|
||||||
|
table.header("Time (sec)")
|
||||||
|
val header = StringBuffer().apply {
|
||||||
|
threadIds.keys.forEach {
|
||||||
|
table.header("Thread " + it.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toSeconds(millis: Long) = (millis / 1000).toInt().toString()
|
||||||
|
|
||||||
|
val start = historyLog[0].timestamp
|
||||||
|
val projectStart = ConcurrentHashMap<String, Long>()
|
||||||
|
historyLog.forEach { line ->
|
||||||
|
val row = arrayListOf<String>()
|
||||||
|
row.add(toSeconds(line.timestamp - start))
|
||||||
|
threadIds.keys.forEach {
|
||||||
|
if (line.threadId == it) {
|
||||||
|
var duration = ""
|
||||||
|
if (line.start) {
|
||||||
|
projectStart[line.name] = line.timestamp
|
||||||
|
} else {
|
||||||
|
duration = " (" + ((line.timestamp - projectStart[line.name]!!) / 1000)
|
||||||
|
.toInt().toString() + ")"
|
||||||
|
}
|
||||||
|
row.add((line.name + duration))
|
||||||
|
} else {
|
||||||
|
row.add("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.addRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
println(table.build())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(argv: Array<String>) {
|
fun main(argv: Array<String>) {
|
||||||
|
@ -263,6 +333,7 @@ fun main(argv: Array<String>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override val priority: Int get() = 0
|
override val priority: Int get() = 0
|
||||||
|
override val name: String = "workerName"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,8 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
|
||||||
override fun createWorkers(nodes: Collection<ProjectTask>): List<IWorker<ProjectTask>> {
|
override fun createWorkers(nodes: Collection<ProjectTask>): List<IWorker<ProjectTask>> {
|
||||||
val result = nodes.map { it ->
|
val result = nodes.map { it ->
|
||||||
object: IWorker<ProjectTask> {
|
object: IWorker<ProjectTask> {
|
||||||
override val priority: Int
|
override val priority: Int get() = 0
|
||||||
get() = 0
|
override val name: String get() = it.project.name
|
||||||
|
|
||||||
override fun call(): TaskResult2<ProjectTask> {
|
override fun call(): TaskResult2<ProjectTask> {
|
||||||
val tr = it.call()
|
val tr = it.call()
|
||||||
return tr
|
return tr
|
||||||
|
@ -94,8 +93,12 @@ class ParallelProjectRunner(val tasksByNames: (Project) -> ListMultimap<String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val taskResult = DynamicGraphExecutor(projectGraph, factory, 5).run()
|
val executor = DynamicGraphExecutor(projectGraph, factory, 5)
|
||||||
|
val taskResult = executor.run()
|
||||||
|
|
||||||
|
if (args.parallel) {
|
||||||
|
executor.dumpHistory()
|
||||||
|
}
|
||||||
return TaskManager.RunTargetResult(taskResult, emptyList())
|
return TaskManager.RunTargetResult(taskResult, emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,4 +323,5 @@ class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val pluginInfo: Pl
|
||||||
// override val timeOut : Long = 10000
|
// override val timeOut : Long = 10000
|
||||||
|
|
||||||
override val priority: Int = 0
|
override val priority: Int = 0
|
||||||
|
override val name: String get() = "[Taskworker " + tasks.map { it.toString() }.joinToString(",") + "]"
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class DynamicGraphTest {
|
||||||
|
|
||||||
class Worker<T>(val runNodes: ArrayList<T>, val n: T, val errorFunction: (T) -> Boolean) : IWorker<T> {
|
class Worker<T>(val runNodes: ArrayList<T>, val n: T, val errorFunction: (T) -> Boolean) : IWorker<T> {
|
||||||
override val priority = 0
|
override val priority = 0
|
||||||
|
override val name: String get() = "[Worker " + runNodes.map { it.toString() }.joinToString(",") + "]"
|
||||||
override fun call() : TaskResult2<T> {
|
override fun call() : TaskResult2<T> {
|
||||||
log(2, "Running node $n")
|
log(2, "Running node $n")
|
||||||
runNodes.add(n)
|
runNodes.add(n)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue