Stop using Windows.Storage.dll #15894

Closed
opened 2026-01-31 04:51:32 +00:00 by claunia · 9 comments
Owner

Originally created by @miniksa on GitHub (Nov 15, 2021).

It's a 2.2MB ref set and it's very slow. We should try to lose it completely if we can.

Originally created by @miniksa on GitHub (Nov 15, 2021). It's a 2.2MB ref set and it's very slow. We should try to lose it completely if we can.
claunia added the Issue-TaskProduct-TerminalResolution-Won't-FixArea-Performance labels 2026-01-31 04:51:32 +00:00
Author
Owner

@zadjii-msft commented on GitHub (Nov 15, 2021):

ACK. It's terrible, and we should be able to not use it....

That actually might be harder than expected. The IStorageItem interface is the one we use to get files off the drag/drop event, but I'm not sure there's a good legacy alternative for us to use.

@Austin-Lamb any ideas?

@zadjii-msft commented on GitHub (Nov 15, 2021): ACK. It's terrible, and we _should_ be able to not use it.... * [`TerminalPage::NewTerminalByDrop`](https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/TerminalPage.cpp#L333-L361) - drag/drop file onto the new tab button * [`TerminalPage::_PasteFromClipboardHandler`](https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/TerminalPage.cpp#L1809-L1818) - pasting text * [`TermControl::_DragDropHandler`](https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalControl/TermControl.cpp#L2250-L2257) - drag/dropping onto the control * `TabManagement.cpp` also `using namespace winrt::Windows::Storage::Pickers,Provider;`, but that code might be gone now. That actually might be harder than expected. The `IStorageItem` interface is the one we use to get files off the drag/drop event, but I'm not sure there's a good legacy alternative for us to use. @Austin-Lamb any ideas?
Author
Owner

@miniksa commented on GitHub (Nov 15, 2021):

@dmachaj had some ideas here

@miniksa commented on GitHub (Nov 15, 2021): @dmachaj had some ideas here
Author
Owner

@dmachaj commented on GitHub (Nov 15, 2021):

I happened to have a reference set trace of Terminal launch and I think a lot of the usage is not practical to try to avoid. The largest usage is related to destination lists (and the underlying IShellItem/IShellLink/IShellFolder) all of which are in windows.storage.dll. That is just under 1MB of reference set.

About 200KB came from SHGetKnownFolderPath and code beneath it.

400KB came from the AMD graphics driver calling something in shell32.dll that secretly redirects to windows.storage.dll. That is well outside your control and cannot be avoided completely.

@dmachaj commented on GitHub (Nov 15, 2021): I happened to have a reference set trace of Terminal launch and I think a lot of the usage is not practical to try to avoid. The largest usage is related to [destination lists](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-icustomdestinationlist) (and the underlying IShellItem/IShellLink/IShellFolder) all of which are in windows.storage.dll. That is just under 1MB of reference set. About 200KB came from `SHGetKnownFolderPath` and code beneath it. 400KB came from the AMD graphics driver calling something in shell32.dll that secretly redirects to windows.storage.dll. That is well outside your control and cannot be avoided completely.
Author
Owner

@zadjii-msft commented on GitHub (Nov 15, 2021):

(¬_¬ )

well that's certainly frustrating.

@zadjii-msft commented on GitHub (Nov 15, 2021): (¬_¬ ) well that's certainly frustrating.
Author
Owner

@dmachaj commented on GitHub (Nov 15, 2021):

🤷 It is a big OS binary that hosts a large amount of low-level shell data layer components. It is unlikely that any large project like Terminal can avoid it completely. The good news is that I didn't see any of the APIs that you are trying to avoid in the reference set 👍.

As an example here's a stack that referenced 156KB of windows.storage.dll:

 |    |- WindowsTerminal.exe!wWinMain
 |    |    WindowsTerminal.exe!AppHost::AppHost
 |    |    WindowsTerminal.exe!AppHost::_HandleCommandlineArgs
 |    |    Microsoft.Terminal.Remoting.dll!winrt::impl::produce<winrt::Microsoft::Terminal::Remoting::implementation::WindowManager,winrt::Microsoft::Terminal::Remoting::IWindowManager>::ProposeCommandline
 |    |    Microsoft.Terminal.Remoting.dll!winrt::Microsoft::Terminal::Remoting::implementation::WindowManager::ProposeCommandline
 |    |    Microsoft.Terminal.Remoting.dll!winrt::impl::invoke<winrt::Windows::Foundation::TypedEventHandler<winrt::Windows::Foundation::IInspectable,winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs>,winrt::Windows::Foundation::IInspectable,winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs>
 |    |    WindowsTerminal.exe!winrt::impl::delegate<winrt::Windows::Foundation::TypedEventHandler<winrt::Windows::Foundation::IInspectable,winrt::Windows::Foundation::IInspectable>,<lambda_b2e650f82073cf5a32476872fd0183dd> >::Invoke
 |    |    WindowsTerminal.exe!AppHost::_FindTargetWindow
 |    |    TerminalApp.dll!winrt::impl::produce<winrt::TerminalApp::implementation::AppLogic,winrt::TerminalApp::IAppLogic>::FindTargetWindow
 |    |    TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::FindTargetWindow
 |    |    TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::LoadSettings
 |    |    TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::_TryLoadSettings
 |    |    TerminalApp.dll!winrt::impl::factory_cache_entry<winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings,winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::call<winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings (__cdecl*)(winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics const &)>
 |    |    |- TerminalApp.dll!<lambda_bf1cf188e73bc29253cc88d4a3307376>::<lambda_invoker_cdecl>
 |    |    |    TerminalApp.dll!winrt::impl::consume_Microsoft_Terminal_Settings_Model_ICascadiaSettingsStatics<winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::LoadAll
 |    |    |    Microsoft.Terminal.Settings.Model.dll!winrt::impl::produce<winrt::Microsoft::Terminal::Settings::Model::factory_implementation::CascadiaSettings,winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::LoadAll
 |    |    |    Microsoft.Terminal.Settings.Model.dll!winrt::Microsoft::Terminal::Settings::Model::implementation::CascadiaSettings::LoadAll
 |    |    |    Microsoft.Terminal.Settings.Model.dll!winrt::Microsoft::Terminal::Settings::Model::implementation::CascadiaSettings::_SettingsPath
 |    |    |    Microsoft.Terminal.Settings.Model.dll!Microsoft::Terminal::Settings::Model::GetBaseSettingsPath
 |    |    |    Microsoft.Terminal.Settings.Model.dll!<lambda_21a2aceb9107346b7ef7ac15d5506f7c>::operator()
 |    |    |    windows.storage.dll!SHGetKnownFolderPath

That seems totally reasonable to me and not worth effort to avoid. Known folder paths are a useful concept.

@dmachaj commented on GitHub (Nov 15, 2021): 🤷 It is a big OS binary that hosts a large amount of low-level shell data layer components. It is unlikely that any large project like Terminal can avoid it completely. The good news is that I didn't see any of the APIs that you are trying to avoid in the reference set 👍. As an example here's a stack that referenced 156KB of windows.storage.dll: ``` | |- WindowsTerminal.exe!wWinMain | | WindowsTerminal.exe!AppHost::AppHost | | WindowsTerminal.exe!AppHost::_HandleCommandlineArgs | | Microsoft.Terminal.Remoting.dll!winrt::impl::produce<winrt::Microsoft::Terminal::Remoting::implementation::WindowManager,winrt::Microsoft::Terminal::Remoting::IWindowManager>::ProposeCommandline | | Microsoft.Terminal.Remoting.dll!winrt::Microsoft::Terminal::Remoting::implementation::WindowManager::ProposeCommandline | | Microsoft.Terminal.Remoting.dll!winrt::impl::invoke<winrt::Windows::Foundation::TypedEventHandler<winrt::Windows::Foundation::IInspectable,winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs>,winrt::Windows::Foundation::IInspectable,winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs> | | WindowsTerminal.exe!winrt::impl::delegate<winrt::Windows::Foundation::TypedEventHandler<winrt::Windows::Foundation::IInspectable,winrt::Windows::Foundation::IInspectable>,<lambda_b2e650f82073cf5a32476872fd0183dd> >::Invoke | | WindowsTerminal.exe!AppHost::_FindTargetWindow | | TerminalApp.dll!winrt::impl::produce<winrt::TerminalApp::implementation::AppLogic,winrt::TerminalApp::IAppLogic>::FindTargetWindow | | TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::FindTargetWindow | | TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::LoadSettings | | TerminalApp.dll!winrt::TerminalApp::implementation::AppLogic::_TryLoadSettings | | TerminalApp.dll!winrt::impl::factory_cache_entry<winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings,winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::call<winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings (__cdecl*)(winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics const &)> | | |- TerminalApp.dll!<lambda_bf1cf188e73bc29253cc88d4a3307376>::<lambda_invoker_cdecl> | | | TerminalApp.dll!winrt::impl::consume_Microsoft_Terminal_Settings_Model_ICascadiaSettingsStatics<winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::LoadAll | | | Microsoft.Terminal.Settings.Model.dll!winrt::impl::produce<winrt::Microsoft::Terminal::Settings::Model::factory_implementation::CascadiaSettings,winrt::Microsoft::Terminal::Settings::Model::ICascadiaSettingsStatics>::LoadAll | | | Microsoft.Terminal.Settings.Model.dll!winrt::Microsoft::Terminal::Settings::Model::implementation::CascadiaSettings::LoadAll | | | Microsoft.Terminal.Settings.Model.dll!winrt::Microsoft::Terminal::Settings::Model::implementation::CascadiaSettings::_SettingsPath | | | Microsoft.Terminal.Settings.Model.dll!Microsoft::Terminal::Settings::Model::GetBaseSettingsPath | | | Microsoft.Terminal.Settings.Model.dll!<lambda_21a2aceb9107346b7ef7ac15d5506f7c>::operator() | | | windows.storage.dll!SHGetKnownFolderPath ``` That seems totally reasonable to me and not worth effort to avoid. Known folder paths are a useful concept.
Author
Owner

@zadjii-msft commented on GitHub (Nov 15, 2021):

Maybe we should loop back around on the OS side and double-tap on what value we (Windows) gets from having all these common components in one big 'ol dll? IDK I'm not sure I'm totally qualified to say I know what I'm talking about on this topic. I'm just looking for anything we can do to trim out dependencies & other startup perf.

@zadjii-msft commented on GitHub (Nov 15, 2021): Maybe we should loop back around on the OS side and double-tap on what value we (Windows) gets from having all these common components in one big 'ol dll? IDK I'm not sure I'm totally qualified to say I know what I'm talking about on this topic. I'm just looking for anything we can do to trim out dependencies & other startup perf.
Author
Owner

@dmachaj commented on GitHub (Nov 15, 2021):

Bigger DLLs should have better performance, all other things being equal. There are a variety of costs that are paid per-dll so fewer/bigger DLLs will pay less of those costs.

However, things can be really complicated for special cases. Windows.storage.dll is going to be loaded into almost every process so uncommonly used pieces are wasteful to page in everywhere. On the other hand the readonly pages should be easily shared across all processes so the memory hit isn't so bad for them. They'll already be paged in by someone else so there's not really any cost to someone else needing the same page; it is already available.

@dmachaj commented on GitHub (Nov 15, 2021): Bigger DLLs should have _better_ performance, all other things being equal. There are a variety of costs that are paid per-dll so fewer/bigger DLLs will pay less of those costs. However, things can be really complicated for special cases. Windows.storage.dll is going to be loaded into almost every process so uncommonly used pieces are wasteful to page in everywhere. On the other hand the readonly pages should be easily shared across all processes so the memory hit isn't so bad for them. They'll already be paged in by someone else so there's not really any cost to someone else needing the same page; it is already available.
Author
Owner

@zadjii-msft commented on GitHub (Nov 15, 2021):

TIL! Thanks!

@zadjii-msft commented on GitHub (Nov 15, 2021): TIL! Thanks!
Author
Owner

@miniksa commented on GitHub (Nov 15, 2021):

Welp, thanks all for the investigation following the meeting we had earlier today. I guess we just resolve this as "MEH" for now and keep the findings for posterity.

@miniksa commented on GitHub (Nov 15, 2021): Welp, thanks all for the investigation following the meeting we had earlier today. I guess we just resolve this as "MEH" for now and keep the findings for posterity.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#15894