Skip to content

Optimize to_iodata to avoid accumulating components map#4271

Open
preciz wants to merge 1 commit into
phoenixframework:mainfrom
preciz:optimize_to_iodata4
Open

Optimize to_iodata to avoid accumulating components map#4271
preciz wants to merge 1 commit into
phoenixframework:mainfrom
preciz:optimize_to_iodata4

Conversation

@preciz

@preciz preciz commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

The components map accumulator in the to_iodata recursive traversal was completely discarded at the end of the public to_iodata/2 function. Additionally, updating the accumulator to memoize resolved template pointers was redundant because each stateful component instance is visited exactly once per page rendering tree.

By stripping out the unused accumulator logic from to_iodata and simplifying resolve_components_xrefs, we eliminate unneeded tuple allocation and map updates.

Benchmarks show ~40% memory reduction and 10-30% speedup.

The components map accumulator in the to_iodata recursive traversal was completely discarded at the end of the public to_iodata/2 function. Additionally, updating the accumulator to memoize resolved template pointers was redundant because each stateful component instance is visited exactly once per page rendering tree.

By stripping out the unused accumulator logic from to_iodata and simplifying resolve_components_xrefs, we eliminate unneeded tuple allocation and map updates.

Benchmarks show ~40% memory reduction and 10-30% speedup.
@SteffenDE

Copy link
Copy Markdown
Member

Additionally, updating the accumulator to memoize resolved template pointers was redundant because each stateful component instance is visited exactly once per page rendering tree.

Is this correct? What if there's a chain where C->B->A share statics?

@preciz

preciz commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

@SteffenDE I believe there is a test case for this:

:c => %{
1 => %{0 => %{0 => "index_1", :s => ["\nIF ", ""]}, :s => ["", ""]},
2 => %{0 => %{0 => "index_2", :s => ["\nELSE ", ""]}, :s => 1},
3 => %{0 => %{0 => "index_3"}, :s => 2}

From a performance side it seems the version in main had its tradeoffs and this branch is faster in that case too.

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.

3 participants