Skip to content

Commit

Permalink
HTML rendering memory allocations optimisation (#3800)
Browse files Browse the repository at this point in the history
* Don't parse text to lines during writing in FileWriter
* Don't create HTML pages of 32kb size for embedded html contents
* Don't create HTML pages of 32kb size during embedding resources links
* Don't create HTML if the content node is nullable
  • Loading branch information
whyoleg committed Sep 18, 2024
1 parent 5e85c86 commit faebb44
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class FileWriter(
val dir = Paths.get(root.absolutePath, path.dropLastWhile { it != '/' }).toFile()
withContext(Dispatchers.IO) {
dir.mkdirsOrFail()
Files.write(Paths.get(root.absolutePath, "$path$ext"), text.lines())
Paths.get(root.absolutePath, "$path$ext").toFile().writeText(text)
}
} catch (e: Throwable) {
context.logger.error("Failed to write $this. ${e.message}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
package org.jetbrains.dokka.base.renderers.html

import kotlinx.html.*
import kotlinx.html.consumers.delayed
import kotlinx.html.consumers.onFinalizeMap
import kotlinx.html.stream.HTMLStreamBuilder
import kotlinx.html.stream.createHTML
import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.dokka.Platform
Expand Down Expand Up @@ -315,12 +318,12 @@ public open class HtmlRenderer(
): List<Pair<DisplaySourceSet, String>> {
var counter = 0
return nodes.toList().map { (sourceSet, elements) ->
val htmlContent = createHTML(prettyPrint = false).prepareForTemplates().div {
val htmlContent = createSmallHTML(prettyPrint = false).prepareForTemplates().div {
elements.forEach {
buildContentNode(it, pageContext, sourceSet)
}
}.stripDiv()
sourceSet to createHTML(prettyPrint = false).prepareForTemplates()
sourceSet to createSmallHTML(prettyPrint = false).prepareForTemplates()
.div(classes = "content sourceset-dependent-content") {
if (counter++ == 0) attributes["data-active"] = ""
attributes["data-togglable"] = sourceSet.sourceSetIDs.merged.toString()
Expand All @@ -344,18 +347,18 @@ public open class HtmlRenderer(
val distinct =
groupDivergentInstancesWithSourceSet(it.value, it.key, pageContext,
beforeTransformer = { instance, _, sourceSet ->
createHTML(prettyPrint = false).prepareForTemplates().div {
instance.before?.let { before ->
instance.before?.let { before ->
createSmallHTML(prettyPrint = false).prepareForTemplates().div {
buildContentNode(before, pageContext, sourceSet)
}
}.stripDiv()
}.stripDiv()
} ?: ""
},
afterTransformer = { instance, _, sourceSet ->
createHTML(prettyPrint = false).prepareForTemplates().div {
instance.after?.let { after ->
instance.after?.let { after ->
createSmallHTML(prettyPrint = false).prepareForTemplates().div {
buildContentNode(after, pageContext, sourceSet)
}
}.stripDiv()
}.stripDiv()
} ?: ""
})

val isPageWithOverloadedMembers = pageContext is MemberPage && pageContext.documentables().size > 1
Expand Down Expand Up @@ -943,6 +946,14 @@ public open class HtmlRenderer(
else -> null
}

// same as createHTML but creates StringBuilder of default size instead of using StringBuilder with 32kb size (default)
// it's useful for cases with "embedded html" f.e source-set-dependent content.
// capacity of the StringBuilder was selected after experiments based on generating documentation for kotlin-stdlib
private fun createSmallHTML(prettyPrint: Boolean = true, xhtmlCompatible: Boolean = false): TagConsumer<String> =
HTMLStreamBuilder(StringBuilder(256), prettyPrint, xhtmlCompatible)
.onFinalizeMap { sb, _ -> sb.toString() }
.delayed()

public open fun buildHtml(
page: PageNode,
resources: List<String>, content: FlowContent.() -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package org.jetbrains.dokka.base.renderers.html.innerTemplating
import freemarker.core.Environment
import freemarker.template.*
import kotlinx.html.*
import kotlinx.html.stream.appendHTML
import kotlinx.html.stream.createHTML
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.base.DokkaBase
Expand Down Expand Up @@ -102,10 +103,9 @@ public class DefaultTemplateModelFactory(
private val String.isAbsolute: Boolean
get() = URI(this).isAbsolute

private fun Appendable.resourcesForPage(pathToRoot: String, resources: List<String>): Unit =
resources.forEach { resource ->

val resourceHtml = with(createHTML()) {
private fun Appendable.resourcesForPage(pathToRoot: String, resources: List<String>) {
with(appendHTML()) {
resources.forEach { resource ->
when {

resource.URIExtension == "css" ->
Expand All @@ -126,13 +126,10 @@ public class DefaultTemplateModelFactory(
}

resource.isImage() -> link(href = if (resource.isAbsolute) resource else "$pathToRoot$resource")
else -> null
}
}
if (resourceHtml != null) {
append(resourceHtml)
}
}
}

}

Expand Down

0 comments on commit faebb44

Please sign in to comment.