Skip to content

Commit

Permalink
fixup! Improvements for 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
bjhham committed Nov 29, 2023
1 parent 8a09cea commit c511f95
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 69 deletions.
20 changes: 20 additions & 0 deletions allocation-benchmark/allocations/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,24 @@ export function displaySite(sites, item) {
li.append("span").attr("class", "file").text(file)
li.append("span").attr("class", "fun").text(fun)
})
}

export function setupRenderControls(drawAllocations) {
const render = () => {
const engineName = document.querySelector("input[name='engine']:checked").value
const snapshotDir = document.querySelector("input[name='snapshot']:checked").value
const reportPath = `${snapshotDir}/testMemoryConsumptionIsSame[${engineName}].json`;
d3.json(reportPath).then(result => {
drawAllocations(result.data)
document.getElementById("info").innerText = ""
}, () => {
drawAllocations({})
document.getElementById("info").innerText = `Nothing found for ${reportPath}`
})
}
document.querySelectorAll("input[type='radio']").forEach(elem => {
elem.onchange = render
})

render()
}
41 changes: 21 additions & 20 deletions allocation-benchmark/allocations/previewClasses.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,25 @@
</head>
<body>
<header>
<div class="dropdown">
Select Engine:
<button class="engine">Netty</button>
<button class="engine">Jetty</button>
<button class="engine">Tomcat</button>
<button class="engine">CIO</button>
<div>
<h3>Select Engine:</h3>
<div>
<input type="radio" name="engine" id="netty" value="Netty" checked />
<label for="netty">Netty</label>
<input type="radio" name="engine" id="jetty" value="Jetty" />
<label for="jetty">Jetty</label>
<input type="radio" name="engine" id="tomcat" value="Tomcat" />
<label for="tomcat">Tomcat</label>
<input type="radio" name="engine" id="cio" value="CIO" />
<label for="cio">CIO</label>
</div>
</div>
<div>
<h3>Select Snapshot:</h3>
<input type="radio" name="snapshot" id="current-snapshot" value="" checked />
<label for="current-snapshot">Current</label>
<input type="radio" name="snapshot" id="test-snapshot" value="test_output" />
<label for="test-snapshot">Test</label>
</div>
</header>
<main>
Expand All @@ -27,7 +40,7 @@
<script src="d3.v5.js"></script>
<script src="common.js" type="module"></script>
<script type="module">
import { displaySite } from "./common.js";
import { displaySite, setupRenderControls } from "./common.js";

const width = 800
const height = 900
Expand Down Expand Up @@ -140,19 +153,7 @@
chart(source)
}

d3.json("testMemoryConsumptionIsSame[Netty].json")
.then(result => {
drawAllocations(result.data)
})

for (let button of document.getElementsByClassName("engine")) {
button.onclick = (e) => {
const engineName = e.target.innerText
d3.json(`testMemoryConsumptionIsSame[${engineName}].json`).then(result => {
drawAllocations(result.data)
})
};
}
setupRenderControls(drawAllocations)

</script>

Expand Down
40 changes: 21 additions & 19 deletions allocation-benchmark/allocations/previewSites.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,25 @@
</head>
<body>
<header>
<div class="dropdown">
Select Engine:
<button class="engine">Netty</button>
<button class="engine">Jetty</button>
<button class="engine">Tomcat</button>
<button class="engine">CIO</button>
<div>
<h3>Select Engine:</h3>
<div>
<input type="radio" name="engine" id="netty" value="Netty" checked />
<label for="netty">Netty</label>
<input type="radio" name="engine" id="jetty" value="Jetty" />
<label for="jetty">Jetty</label>
<input type="radio" name="engine" id="tomcat" value="Tomcat" />
<label for="tomcat">Tomcat</label>
<input type="radio" name="engine" id="cio" value="CIO" />
<label for="cio">CIO</label>
</div>
</div>
<div>
<h3>Select Snapshot:</h3>
<input type="radio" name="snapshot" id="current-snapshot" value="" checked />
<label for="current-snapshot">Current</label>
<input type="radio" name="snapshot" id="test-snapshot" value="test_output" />
<label for="test-snapshot">Test</label>
</div>
</header>
<main>
Expand All @@ -27,7 +40,7 @@
<script src="d3.v5.js"></script>
<script src="common.js" type="module"></script>
<script type="module">
import { displaySite } from "./common.js";
import { displaySite, setupRenderControls } from "./common.js";

const width = 800
const height = 900
Expand Down Expand Up @@ -123,19 +136,8 @@
chart(values)
}

d3.json("testMemoryConsumptionIsSame[Netty].json")
.then(result => {
drawAllocations(result.data)
})
setupRenderControls(drawAllocations)

for (let button of document.getElementsByClassName("engine")) {
button.onclick = (e) => {
const engineName = e.target.innerText
d3.json(`testMemoryConsumptionIsSame[${engineName}].json`).then(result => {
drawAllocations(result.data)
})
};
}
</script>

</body>
Expand Down
6 changes: 6 additions & 0 deletions allocation-benchmark/allocations/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ body {
font-family: 'JetBrains Mono', monospace;
font-size: 11pt;
}
header {
display: flex;
gap: 1rem;
justify-content: space-evenly;
padding: 0 1rem 2rem 1rem;
}
main {
display: grid;
grid-template-columns: 55% 45%;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package benchmarks

import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.cio.*
import io.ktor.server.engine.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ class LocationInfo(val name: String) {
}

override fun toString(): String = buildString {
val instances = instanceIndex.values.sortedByDescending { it.totalSize }

appendLine("Location: $name. Size: ${locationSize.formatSize()}")
// instances.forEach {
// appendLine(it)
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fun main() {
embeddedServer(Netty, port = port) {
routing {
staticFiles("/", File("allocations"))
staticFiles("/test_output", File("build/allocations"))
}

println("""
Expand Down
54 changes: 37 additions & 17 deletions allocation-benchmark/src/test/kotlin/ServerCallAllocationTest.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package benchmarks

import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import kotlin.math.absoluteValue

const val TEST_SIZE = 1000
const val WARMUP_SIZE = 10

const val ALLOWED_MEMORY_DIFFERENCE = 100
const val ALLOWED_MEMORY_DIFFERENCE = 250L

class ServerCallAllocationTest {

Expand All @@ -16,35 +17,54 @@ class ServerCallAllocationTest {
fun testMemoryConsumptionIsSame(engine: String) {
val reportName = "testMemoryConsumptionIsSame[$engine]"

val memory = measureMemory(engine) {
val snapshot = measureMemory(engine) {
repeat(TEST_SIZE) {
makeRequest()
}
}

if (SAVE_REPORT) {
saveReport(reportName, memory)
saveSiteStatistics(reportName, memory)
println("Report updated: $reportName")
val consumedMemory = memory.totalSize() / TEST_SIZE
println("Request consumes ${consumedMemory.kb}")
return
}
saveReport(reportName, snapshot, replace = SAVE_REPORT)
saveSiteStatistics(reportName, snapshot, replace = SAVE_REPORT)

val consumedMemory = memory.totalSize() / TEST_SIZE
val expectedMemory = loadReport(reportName).totalSize() / TEST_SIZE
val previousSnapshot = loadReport(reportName)
val consumedMemory = snapshot.totalSize() / TEST_SIZE
val expectedMemory = previousSnapshot.totalSize() / TEST_SIZE

val difference = consumedMemory - expectedMemory
val message = """
Request consumes ${consumedMemory.kb}, expected ${expectedMemory.kb}. Difference: ${(consumedMemory - expectedMemory).kb}
Consumed ${consumedMemory.kb} on request
Expected ${expectedMemory.kb} on request
Extra consumed ${(consumedMemory - expectedMemory).kb} on request
Consumed ${consumedMemory.kb} on request
Expected ${expectedMemory.kb} on request
${if (difference > 0L) "Extra " else "Saved "} ${difference.absoluteValue.kb} on request
(See stdout + build/allocations/* files for details)
""".trimIndent().also(::println)

assertTrue(difference - ALLOWED_MEMORY_DIFFERENCE <= 0, message)
if (SAVE_REPORT) {
println("Report updated: $reportName")
return
}

println("\nIncreased locations:")
snapshot.packages.mapNotNull { location ->
LocationDifference(previousSnapshot[location.name], location).takeIf {
it.difference() > 0
}
}.sortedByDescending { it.difference() }.forEach { diff ->
val (previous, current) = diff
println("\t" + current.name.padEnd(40) + diff.difference().kb.padStart(10) + " (${(previous?.locationSize?.kb ?: "0").padEnd(12)} --> ${current.locationSize.kb.padStart(12)})")
}

val increase = maxOf(difference - ALLOWED_MEMORY_DIFFERENCE, 0)
assertEquals(0L, increase, message)
}

private val Long.kb get() = "%.2f KB".format(toDouble() / 1024.0)

data class LocationDifference(
val previous: LocationInfo?,
val current: LocationInfo
) {
fun difference() = previous?.let { current.locationSize - it.locationSize } ?: current.locationSize
}

}
23 changes: 16 additions & 7 deletions allocation-benchmark/src/test/kotlin/utils/ReportUtils.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package benchmarks

import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.File
Expand All @@ -10,11 +9,17 @@ private val serializer = Json {
prettyPrint = true
}

fun saveReport(name: String, report: AllocationData) {
val file = File("allocations/$name.json")
if (!file.exists()) {
fun saveReport(name: String, report: AllocationData, replace: Boolean = true) {
val file = if (replace)
File("allocations/$name.json")
else
File("build/allocations/$name.json")

if (!file.parentFile.exists())
file.parentFile.mkdirs()

if (!file.exists())
file.createNewFile()
}

val content = serializer.encodeToString(report)
file.bufferedWriter().use {
Expand All @@ -30,8 +35,12 @@ data class SiteWithName(
var totalSize: Long
)

fun saveSiteStatistics(name: String, report: AllocationData) {
val file = File("allocations/sites_$name.json")
fun saveSiteStatistics(name: String, report: AllocationData, replace: Boolean) {
val file = if (replace)
File("allocations/sites_$name.json")
else
File("build/allocations/sites_$name.json")

if (!file.exists()) {
file.createNewFile()
}
Expand Down

0 comments on commit c511f95

Please sign in to comment.