Skip to content

Allow trimming of TerminalFormatStrings - #132597

Merged
MichalStrehovsky merged 8 commits into
mainfrom
copilot/move-s-terminalformatstringsinstance
Aug 24, 2026
Merged

MichalStrehovsky merged 8 commits into
mainfrom
copilot/move-s-terminalformatstringsinstance

Conversation

Copilot AI commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

8kB size reduction for "Hello world" on Linux

Contributes to #132595

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@jkotas jkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Address feedback

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-console
See info in area-owners.md if you want to be subscribed.

…internal, drop TerminalFormatStringsInstance

Co-authored-by: jkotas <[email protected]>

Copilot AI commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Address feedback

Addressed in a57010b: merged TerminalFormatStrings.Unix.cs into TerminalFormatStrings.cs, made s_instance internal (removed the Instance property), and removed ConsolePal.TerminalFormatStringsInstance in favor of direct TerminalFormatStrings.s_instance usage everywhere.

Copilot AI requested a review from jkotas August 21, 2026 02:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors how Unix console code accesses terminal capability metadata (TerminalFormatStrings) to reduce/centralize instance management, in support of NativeAOT size/rooting investigations referenced by #132595.

Changes:

  • Replaces ConsolePal.TerminalFormatStringsInstance (Lazy-backed) usage with TerminalFormatStrings.Instance across Unix console and stdin handling code.
  • Removes the Lazy-backed TerminalFormatStringsInstance property/field from ConsolePal.Unix.
  • Updates System.Console.Tests.csproj to define UNITTEST so linked source files can exclude production-only static initialization.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Console/tests/System.Console.Tests.csproj Defines UNITTEST to control compilation of linked source files in the test project.
src/libraries/System.Console/src/System/TerminalFormatStrings.cs Adds a cached Instance entry point for terminal format strings (with UNITTEST exclusion).
src/libraries/System.Console/src/System/IO/StdInReader.cs Switches callers to use TerminalFormatStrings.Instance directly.
src/libraries/System.Console/src/System/ConsolePal.Unix.cs Removes the Lazy-backed instance plumbing and updates call sites to TerminalFormatStrings.Instance; tweaks cached-settings invalidation flag type.

@jkotas
jkotas marked this pull request as ready for review August 21, 2026 05:15
Copilot AI review requested due to automatic review settings August 21, 2026 05:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (4)

src/libraries/System.Console/src/System/ConsolePal.Unix.cs:39

  • s_invalidateCachedSettings is typed as bool, but this code uses Interlocked.CompareExchange(ref s_invalidateCachedSettings, ...). In this repo, Interlocked.CompareExchange has overloads for byte, short, etc., but not for bool, so the current code will not compile. Use a byte sentinel (0/1) as requested in the review thread and adjust the initializer accordingly.
        private static bool s_invalidateCachedSettings = true; // Tracks whether we should invalidate the cached settings.

src/libraries/System.Console/src/System/ConsolePal.Unix.cs:1108

  • Interlocked.CompareExchange doesn't support bool in this repo, so this call won't compile once s_invalidateCachedSettings is changed to a byte sentinel. Update the CompareExchange call to use 0/1 and compare the returned previous value.
            bool invalidateSettings = Interlocked.CompareExchange(ref s_invalidateCachedSettings, false, true);

src/libraries/System.Console/src/System/ConsolePal.Unix.cs:1119

  • This write should match the atomic flag type used by CheckTerminalSettingsInvalidated. With a byte sentinel flag, write 1 (true) to trigger invalidation.
            Volatile.Write(ref s_invalidateCachedSettings, true);

src/libraries/System.Console/src/System/ConsolePal.Unix.cs:43

  • s_terminalFormatStringsInstance is initialized via Interlocked.CompareExchange, but the fast-path read in TerminalFormatStringsInstance is a plain field read. For cross-thread publication on weak memory models, use Volatile.Read (this file already follows that pattern for s_stdInReader).
        public static TerminalFormatStrings TerminalFormatStringsInstance => s_terminalFormatStringsInstance ?? Initialize();

Copilot AI review requested due to automatic review settings August 21, 2026 06:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.Console/src/System/ConsolePal.Unix.cs:46

  • TerminalFormatStringsInstance uses the new field backing storage plus an inline Interlocked.CompareExchange(ref field, new TerminalFormatStrings(...), null) pattern. This has two concrete problems:
  1. The new TerminalFormatStrings(...) allocation happens whenever the first field read returns null, even if another thread has already initialized the instance (stale/non-volatile read), causing avoidable allocations.
  2. After initialization, reads are plain (non-Volatile.Read) loads, which doesn’t provide an acquire barrier for safe publication on weaker memory models.

In this file you already use the safer pattern for s_stdInReader (Volatile.Read + CompareExchange). Consider switching this property to the same pattern with an explicit nullable backing field.

        public static TerminalFormatStrings TerminalFormatStringsInstance =>
            field ??
            Interlocked.CompareExchange(ref field, new TerminalFormatStrings(TermInfo.DatabaseFactory.ReadActiveDatabase()), null) ??
            field;

@jkotas jkotas changed the title Refactoring TerminalFormatStrings instance management Allow trimming of TerminalFormatStrings Aug 21, 2026

@MichalStrehovsky MichalStrehovsky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

@MichalStrehovsky
MichalStrehovsky enabled auto-merge (squash) August 24, 2026 01:44

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

8kB size reduction for "Hello world" on Linux

8kB with such a small and simple change? Most impressive! Thank you @jkotas !

@MichalStrehovsky
MichalStrehovsky merged commit e16705d into main Aug 24, 2026
81 checks passed
@MichalStrehovsky
MichalStrehovsky deleted the copilot/move-s-terminalformatstringsinstance branch August 24, 2026 10:44
@adamsitnik adamsitnik added this to the 12.0.0 milestone Aug 24, 2026
@dotnet-milestone-bot dotnet-milestone-bot Bot modified the milestones: 12.0.0, 12.0-preview1 Aug 25, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants