Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTML rendering memory allocations optimisation #3800

Merged
merged 5 commits into from
Sep 18, 2024

Conversation

whyoleg
Copy link
Collaborator

@whyoleg whyoleg commented Sep 16, 2024

Overall the main idea of the changes is to reduce usage of createHTML which by default create StringBuilder of 32KB size and in most cases it needs much less, specifically in source-set-dependent content and during resource links embedding.

Those optimisations were found during investigation of stdlib docs build (internal discussion)

@whyoleg whyoleg self-assigned this Sep 16, 2024
Copy link
Member

@vmishenev vmishenev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity: have you measured the overall effect of this pr on memory consumption?

elements.forEach {
buildContentNode(it, pageContext, sourceSet)
}
}.stripDiv()
sourceSet to createHTML(prettyPrint = false).prepareForTemplates()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered an optimal capacity?
In this example, It always takes more than the default 16.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking about it, but failed to think of a good default... Will it be 128 or 1024? It's hard to calculate which value will be best.

But I agree, that probably it would be nice to initialise it with bigger value. Do you have anything in mind?
I can try to check different values if needed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have anything in mind?

I think you can find it out on stdlib.
E.g. for 128 vs 1024 - choose one with the minimal memory allocated in a profiler.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried several values (default, 128, 256, 512, 1024), the difference in memory allocations is ±3% from best to worst. With 1024 it started to behave even worse, though the diff is minimal and not always the same.
I've decided to stick with 256.

@@ -344,14 +347,14 @@ public open class HtmlRenderer(
val distinct =
groupDivergentInstancesWithSourceSet(it.value, it.key, pageContext,
beforeTransformer = { instance, _, sourceSet ->
createHTML(prettyPrint = false).prepareForTemplates().div {
createSmallHTML(prettyPrint = false).prepareForTemplates().div {
instance.before?.let { before ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can extract instance.before?.let from createHTML to avoid the redundant invocation of createHTML

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will take a look, thanks!

@whyoleg
Copy link
Collaborator Author

whyoleg commented Sep 16, 2024

Just out of curiosity: have you measured the overall effect of this pr on memory consumption?

Yes! I've rechecked once more to get numbers. Tested with stdlib 1.5, newer versions will probably have even bigger differences.

  • memory allocated during the full process of Dokka execution:
    • before: 46 GB
    • after: 27 GB
  • max memory used during Dokka execution
    • before: 5.07 GB
    • after: 4.48 GB
  • byte[] allocations (mostly coming from operations on StringBuilder from kotlinx-html, e.g createHTML)
    • before: 21 GB
    • after: 6.5 GB
  • text.lines() allocations (removed in this PR) used 4.5 GB

I can do the same with some other project of your choice if you want to validate if it affects anything else

@whyoleg whyoleg force-pushed the html-rendering-memory-allocations-optimization branch from 7e8d6b8 to fe1fa45 Compare September 17, 2024 12:57
@whyoleg whyoleg merged commit faebb44 into master Sep 18, 2024
14 checks passed
@whyoleg whyoleg deleted the html-rendering-memory-allocations-optimization branch September 18, 2024 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants