From 4aa9ad6b14863f1d44ffe6e8037cf5807df82b3e Mon Sep 17 00:00:00 2001 From: Minjae Song Date: Sat, 15 Dec 2018 14:43:55 +0900 Subject: [PATCH] blockingthreadpool test done not very effective --- src/net/torvald/terrarum/Terrarum.kt | 4 +- .../terrarum/concurrent/ThreadParallel.kt | 7 +- .../torvald/terrarum/tests/NoiseGenerator.kt | 80 +++++++++++++----- work_files/ThreadPool performance test.xlsx | Bin 0 -> 38166 bytes 4 files changed, 68 insertions(+), 23 deletions(-) create mode 100644 work_files/ThreadPool performance test.xlsx diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index 5398680b7..063b3e12e 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -192,7 +192,7 @@ object Terrarum : Screen { val CONTROLLER_DEADZONE = 0.1f /** Available CPU threads */ - val THREADS = Runtime.getRuntime().availableProcessors() + val THREADS = Runtime.getRuntime().availableProcessors() + 1 /** * If the game is multithreading. @@ -201,7 +201,7 @@ object Terrarum : Screen { * THREADS >= 2 and config "multithread" is true */ val MULTITHREAD: Boolean - get() = THREADS >= 2 && getConfigBoolean("multithread") + get() = THREADS >= 3 && getConfigBoolean("multithread") private lateinit var configDir: String diff --git a/src/net/torvald/terrarum/concurrent/ThreadParallel.kt b/src/net/torvald/terrarum/concurrent/ThreadParallel.kt index f3c11aec0..cab790b0e 100644 --- a/src/net/torvald/terrarum/concurrent/ThreadParallel.kt +++ b/src/net/torvald/terrarum/concurrent/ThreadParallel.kt @@ -71,6 +71,7 @@ object ThreadParallel { * * Tasks are not guaranteed to be done orderly; but the first task in the list will be executed first. */ +@Deprecated("Experimental.", ReplaceWith("ThreadParallel", "net.torvald.terrarum.concurrent.ThreadParallel")) object BlockingThreadPool { val threadCount = Terrarum.THREADS // modify this to your taste private val pool: Array = Array(threadCount, { null }) @@ -115,7 +116,6 @@ object BlockingThreadPool { // then, sleep this very thread, wake if any of the thread in the pool is terminated, // and GOTO loop_start; if we don't sleep, this function will be busy-waiting - } } } @@ -125,7 +125,10 @@ object BlockingThreadPool { return true } - private fun RunnableFun.makeRunnable() = Runnable { this.invoke() } + + private fun RunnableFun.makeRunnable() = Runnable { + this.invoke() + } } object ParallelUtils { diff --git a/src/net/torvald/terrarum/tests/NoiseGenerator.kt b/src/net/torvald/terrarum/tests/NoiseGenerator.kt index a5d1f7323..e39117623 100644 --- a/src/net/torvald/terrarum/tests/NoiseGenerator.kt +++ b/src/net/torvald/terrarum/tests/NoiseGenerator.kt @@ -20,6 +20,7 @@ import com.sudoplay.joise.module.ModuleScaleOffset import net.torvald.random.HQRNG import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader.printdbg +import net.torvald.terrarum.Terrarum import net.torvald.terrarum.concurrent.BlockingThreadPool import net.torvald.terrarum.concurrent.RunnableFun import net.torvald.terrarum.concurrent.ParallelUtils.sliceEvenly @@ -57,6 +58,11 @@ class NoiseGenerator : ScreenAdapter() { pixmap = Pixmap(IMAGE_SIZE, IMAGE_SIZE, Pixmap.Format.RGBA8888) texture = Texture(1, 1, Pixmap.Format.RGBA8888) + + batch.projectionMatrix = camera.combined + + println("Test runs: ${testSets.size * samplingCount}") + println("Warmup runs: $warmupTries") } var regenerate = true @@ -108,16 +114,13 @@ class NoiseGenerator : ScreenAdapter() { // regen if (timerFired && BlockingThreadPool.allFinished()) { - val timeTook = System.currentTimeMillis() - timerStart timerFired = false - printdbg(this, "> $timeTook ms") - rawTimerRecords.add(timeTook) totalTestsDone += 1 } if (regenerate && BlockingThreadPool.allFinished()) { - printdbg(this, "Reticulating splines...") + //printdbg(this, "Reticulating splines...") regenerate = false // don't join while rendering noise @@ -139,47 +142,86 @@ class NoiseGenerator : ScreenAdapter() { batch.inUse { batch.color = Color.WHITE batch.draw(texture, 0f, 0f) + + batch.color = Color.CYAN + Terrarum.fontGame.draw(batch, "Tests: $totalTestsDone / ${testSets.size * samplingCount}", 10f, 10f) } } - private val testSets = listOf(1, 2, 4, 6, 8, 12, 16, 20, 24, 32, 48, 64) - private val samplingCount = 50 + //private val testSets = listOf(1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192)//, 12288, 16384, 24576, 32768, 49152, 65536) + private val testSets = listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) + private val samplingCount = 20 private var totalTestsDone = 0 private val rawTimerRecords = ArrayList() + private var warmupDone = false + private val warmupTries = (testSets.size * samplingCount) / 4 + private var constructOnce = false + + private val timeWhenTestBegun = System.currentTimeMillis() + + private var wholeJobTimer = 0L + private fun updateTestGovernor(delta: Float) { + // cut the warm-up { + if (!warmupDone && totalTestsDone >= warmupTries) { + println("######## WARMUP DONE, THE TEST BEGINS HERE ########") + totalTestsDone = 0 + //rawTimerRecords.clear() + warmupDone = true + } + + // time to end the test if (totalTestsDone == testSets.size * samplingCount) { println("Test completed:") println("Total tests done = $totalTestsDone") // print a table - for (x in 0 until testSets.size) { - // print table header - print("${testSets[x]}\t") - } - println() - - for (y in 0 until totalTestsDone / testSets.size) { - for (x in 0 until testSets.size) { - // print table contents - print("${rawTimerRecords[x * testSets.size + y]}\t") + println("Timer raw:") + rawTimerRecords.forEachIndexed { index, l -> + if (index < rawTimerRecords.size - testSets.size) { + println("* $l") + } + else { + println("$l") } - println() } + // k thx bye + val timeWasted = (System.currentTimeMillis() - timeWhenTestBegun) / 1000 + println("Total testing time: " + + "${timeWasted.div(60).toString().padStart(2, '0')}:" + + "${timeWasted.rem(60).toString().padStart(2, '0')}") + System.exit(0) } // time to construct a new test - if (totalTestsDone % samplingCount == 0) { + if (totalTestsDone % samplingCount == 0 && BlockingThreadPool.allFinished()) { pixelsInSingleJob = (IMAGE_SIZE * IMAGE_SIZE) / testSets[totalTestsDone / samplingCount] - println("Preparing test for ${testSets[totalTestsDone / samplingCount]} task sets") + + + if (!constructOnce) { + if (warmupDone) + println("Preparing test for ${testSets[totalTestsDone / samplingCount]} task sets") + else + println("This is warm-up, task sets: $${testSets[totalTestsDone / samplingCount]}") + + val endTime = System.currentTimeMillis() + rawTimerRecords.add(endTime - wholeJobTimer) + println("> Timer end: $endTime") + wholeJobTimer = endTime + println("> Timer start: $wholeJobTimer") + + constructOnce = true + } } // auto-press SPACE if (BlockingThreadPool.allFinished()) { regenerate = true + constructOnce = false } } diff --git a/work_files/ThreadPool performance test.xlsx b/work_files/ThreadPool performance test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c2502d89471519839fce57d12abb2693f2434dcf GIT binary patch literal 38166 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 z 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