Skip to content

Cache the indentation strings of the output lines (google-java-format #1466) - #105

Closed
abashev wants to merge 1 commit into
mainfrom
gjf-1466-cached-indent-spaces
Closed

abashev wants to merge 1 commit into
mainfrom
gjf-1466-cached-indent-spaces

Conversation

@abashev

@abashev abashev commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator

Port of google/google-java-format#1466 (Liam Miller-Cushon, author kept). Every output line's indentation was a fresh " ".repeat(indent); JavaOutput.spaces(int) now hands out one String per width up to 100 spaces, built on first use. Wider widths are built as before, zero or less gives the empty string. Upstream's second half, Style.indentString delegating to the cache, has no counterpart here: the fork's Style knows no tabs, and JavaOutput.indent is the only caller.

TDD

JavaOutputTest was written first and did not compile: the same instance for the same width, the empty string at zero and below, and a width beyond the cache.

What it buys

Measured with a small harness (ThreadMXBean.getThreadAllocatedBytes on one thread, the 135 java.util files of JDK 21, six warm-up and six measured passes, three JVMs each):

allocated per pass per output line time per pass
main 1,980–1,981 MB 17,761–17,772 B 828–878 ms
this branch 1,976–1,978 MB 17,728–17,746 B 821–843 ms

About 30 bytes per output line, 0.2 % of what formatting allocates, and the time does not move. It is upstream alignment more than a measurable win; merging decides whether that is worth the twenty lines.

Checks

  • :open-java-format:test on JDK 21: 1600 tests, 0 failures.
  • The JDK 21 sources (15,747 files), formatted with main's jar and this branch's jar, are identical.

Every output line's indentation was a fresh `" ".repeat(indent)`.
JavaOutput.spaces(int) now hands out one String per width up to 100
spaces, built on first use; wider widths are built as before, and zero
or less gives the empty string. Taken from
google/google-java-format#1466 (Liam Miller-Cushon), minus its
Style.indentString half, which has no counterpart here: the fork's
Style knows no tabs, and JavaOutput.indent is the only caller.

JavaOutputTest asks for the same instance twice, for the empty string
at zero and below, and for a width beyond the cache.

Measured on the 135 files of java.util from JDK 21, six passes on one
thread, bytes from ThreadMXBean.getThreadAllocatedBytes: 1,980 MB per
pass before, 1,977 MB after, about 30 bytes per output line out of
17,770. The time per pass does not move, and the JDK 21 sources format
exactly as before.
@abashev

abashev commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator Author

Closed unmerged: the measured gain is 0.2 % of what formatting allocates, which does not pay for the extra code. The regex port, #104, stays.

@abashev abashev closed this Oct 3, 2026
@abashev
abashev deleted the gjf-1466-cached-indent-spaces branch October 3, 2026 18:52
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