Reload environment variables only on WM_SETTINGCHANGE #19627

Open
opened 2026-01-31 06:49:10 +00:00 by claunia · 9 comments
Owner

Originally created by @lhecker on GitHub (Apr 4, 2023).

til::env is rather complex, reads a lot of registry keys and requires lots of string operations. Since #14999 we recreate the til::env cache every time we create a new tab, but this isn't necessary, considering that changes to environment variables are exceedingly rare. Most users will run a Windows Terminal instance without it ever seeing a single environment variable change.

👉 Listen to WM_SETTINGCHANGE and only then recreate the globally shared cache. If multi-threading is a concern, just encode the variables back into a \0 separated string, the same way we get it from the OS anyways already. This would reflect how ConEmu does it: https://github.com/Maximus5/ConEmu/issues/468

Originally created by @lhecker on GitHub (Apr 4, 2023). `til::env` is rather complex, reads a lot of registry keys and requires lots of string operations. Since #14999 we recreate the `til::env` cache every time we create a new tab, but this isn't necessary, considering that changes to environment variables are _exceedingly_ rare. Most users will run a Windows Terminal instance without it ever seeing a single environment variable change. 👉 Listen to `WM_SETTINGCHANGE` and only then recreate the globally shared cache. If multi-threading is a concern, just encode the variables back into a `\0` separated string, the same way we get it from the OS anyways already. This would reflect how ConEmu does it: https://github.com/Maximus5/ConEmu/issues/468
claunia added the Issue-TaskProduct-TerminalArea-PerformanceArea-Quality labels 2026-01-31 06:49:10 +00:00
Author
Owner

@voronoipotato commented on GitHub (May 8, 2023):

https://github.com/microsoft/winget-cli/issues/549

@lhecker some people in the winget comments thread seem to think that microsoft/terminal should be responsible for refreshing the environment variables after a program is installed through winget. I'm highly skeptical of this claim, and it sounds backwards to me, but could we emit a WM_SETTINGCHANGE from winget to refresh the env variables after this is merged?

Thanks!

@voronoipotato commented on GitHub (May 8, 2023): https://github.com/microsoft/winget-cli/issues/549 @lhecker some people in the winget comments thread seem to think that microsoft/terminal should be responsible for refreshing the environment variables after a program is installed through winget. I'm highly skeptical of this claim, and it sounds backwards to me, but could we emit a WM_SETTINGCHANGE from winget to refresh the env variables after this is merged? Thanks!
Author
Owner

@lhecker commented on GitHub (May 9, 2023):

Since #14999 we already get the latest environment variables whenever you create a new tab or pane. But
Windows Terminal cannot be responsible for refreshing them the way some people ask for it in that issue.

In short, we cannot refresh the variables of another process, like the shell for instance. While overwriting the environment stored in RTL_USER_PROCESS_PARAMETERS in a foreign process would already be quite difficult in on itself, it wouldn't solve the problem for PowerShell in particular, because it parses the environment on startup and puts it into what's effectively a Map<string, string>. Us updating RTL_USER_PROCESS_PARAMETERS wouldn't update that map - only PowerShell itself can do that.

This issue is just about how #14999 took a large shortcut and burns dozens of millions of cycles during startup (and every time you open a tab), because it reconstructs the environment variables every time without caching. I want it to only do that when we receive a WM_SETTINGCHANGE so that it's faster.

@lhecker commented on GitHub (May 9, 2023): Since #14999 we already get the latest environment variables whenever you create a new tab or pane. But Windows Terminal cannot be responsible for refreshing them the way some people ask for it in that issue. In short, we cannot refresh the variables of another process, like the shell for instance. While overwriting the environment stored in `RTL_USER_PROCESS_PARAMETERS` in a foreign process would already be quite difficult in on itself, it wouldn't solve the problem for PowerShell in particular, because it parses the environment on startup and puts it into what's effectively a `Map<string, string>`. Us updating `RTL_USER_PROCESS_PARAMETERS` wouldn't update that map - only PowerShell itself can do that. This issue is just about how #14999 took a large shortcut and burns dozens of millions of cycles during startup (and every time you open a tab), because it reconstructs the environment variables every time without caching. I want it to only do that when we receive a `WM_SETTINGCHANGE` so that it's faster.
Author
Owner

@voronoipotato commented on GitHub (May 9, 2023):

Thank you for all the information, that was very helpful!

@voronoipotato commented on GitHub (May 9, 2023): Thank you for all the information, that was very helpful!
Author
Owner

@citelao commented on GitHub (May 16, 2023):

@lhecker, if I understand correctly:

  • As of #14999 (which is not built into any released bits as of 16 May 2023), we fetch the latest environment variables when users create a new tab or pane.
    • So if I winget install vim, a new tab/pane of Terminal will have vim.
  • However, that change reloads environment variables every time users open a new tab or pane. This bug tracks a resolution to that:
    • Listen to WM_SETTINGCHANGE in Terminal; only reload environment variables for new tabs/panes after that change is fired.
    • This proposed change will not affect observed behavior: users must still open new tabs/panes to refresh their environment variables variables.

Am I understanding correctly?

@citelao commented on GitHub (May 16, 2023): @lhecker, if I understand correctly: * As of #14999 (which is not built into any released bits as of 16 May 2023), we fetch the latest environment variables when users create a new tab or pane. * So if I `winget install vim`, a new tab/pane of Terminal will have `vim`. * However, that change reloads environment variables every time users open a new tab or pane. This bug tracks a resolution to that: * Listen to `WM_SETTINGCHANGE` in Terminal; only reload environment variables for new tabs/panes after that change is fired. * This proposed change will not affect observed behavior: users must still open new tabs/panes to refresh their environment variables variables. Am I understanding correctly?
Author
Owner

@lhecker commented on GitHub (May 16, 2023):

Yep, that's correct.

@lhecker commented on GitHub (May 16, 2023): Yep, that's correct.
Author
Owner

@sba923 commented on GitHub (May 22, 2023):

What's the order of magnitude of the time added by #14999 when opening a new tab?

@sba923 commented on GitHub (May 22, 2023): What's the order of magnitude of the time added by #14999 when opening a new tab?
Author
Owner

@lhecker commented on GitHub (May 22, 2023):

That heavily depends on whether you have animations enabled in Windows or not (and which ones). WinUI's animations are an extreme resource hog. From what I can tell it's about 1.5-3% if they're enabled and about 5-10% if disabled, edit: relative to the total CPU cost inside WindowsTerminal.exe.

@lhecker commented on GitHub (May 22, 2023): That heavily depends on whether you have animations enabled in Windows or not (and which ones). WinUI's animations are an extreme resource hog. From what I can tell it's about 1.5-3% if they're enabled and about 5-10% if disabled, **edit:** relative to the total CPU cost inside WindowsTerminal.exe.
Author
Owner

@zadjii-msft commented on GitHub (May 22, 2023):

For folks who maybe got confused like I did:

Reloading env vars takes the same number of cycles regardless of whether animations are enabled or not.

Opening tabs with animations enabled takes more CPU cycles than without, so the impact of env vars is relatively less.

@zadjii-msft commented on GitHub (May 22, 2023): For folks who maybe got confused like I did: Reloading env vars takes the same number of cycles regardless of whether animations are enabled or not. Opening tabs with animations enabled takes _more_ CPU cycles than without, so the impact of env vars is _relatively_ less.
Author
Owner

@sba923 commented on GitHub (May 22, 2023):

For folks who maybe got confused like I did:

Reloading env vars takes the same number of cycles regardless of whether animations are enabled or not.

Opening tabs with animations enabled takes more CPU cycles than without, so the impact of env vars is relatively less.

Thanks for the clarification!

@sba923 commented on GitHub (May 22, 2023): > For folks who maybe got confused like I did: > > Reloading env vars takes the same number of cycles regardless of whether animations are enabled or not. > > Opening tabs with animations enabled takes _more_ CPU cycles than without, so the impact of env vars is _relatively_ less. Thanks for the clarification!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#19627