Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WindowsAppSDK 1.6 increases the build time drastically. #4810

Open
DierkDroth opened this issue Oct 16, 2024 · 7 comments
Open

WindowsAppSDK 1.6 increases the build time drastically. #4810

DierkDroth opened this issue Oct 16, 2024 · 7 comments
Assignees

Comments

@DierkDroth
Copy link

DierkDroth commented Oct 16, 2024

Describe the bug

With last VS update last week I updated my C# .NET8 solution from WindowsAppSDK 1.5 to WindowsAppSDK 1.6.

Unfortunately this increased the build time drastically: e.g. a project which includes a WindowsAppSDK shared project now takes at least 3 times as long to build as before. Obviously this increased turn around time drastically and slows down the development cycle. I never experienced something like at on any prior WindowsAppSDK update.

How could I go back to the prior building cycle turn arounds?

I also experienced - but this is nothing new though - that building the solution again without something being changed (!) e.g. just by pressing F5 goes through new compiler runs. Why are the building tools (compiler etc.) not aware that nothing was changed?

Please don't ask me for a repo. Demonstrating the issue requires a solution with a substantial number of source files.

Steps to reproduce the bug

Please see above

Expected behavior

No response

Screenshots

No response

NuGet package version

None

Packaging type

No response

Windows version

No response

IDE

No response

Additional context

No response

@DarranRowe
Copy link

DarranRowe commented Oct 16, 2024

Just to ask, since it may be obvious for you but not for me. Is this a C++ project or a C# project?
I think the "VS update last week" implies C#, but it would be nice to have the language explicitly stated.

@DierkDroth
Copy link
Author

Just to ask, since it may be obvious for you but not for me. Is this a C++ project or a C# project? I think the "VS update last week" implies C#, but it would be nice to have the language explicitly stated.

@DarranRowe sorry I forgot to be specific and just amended the case description: this is C# on .NET8

@manodasanW manodasanW self-assigned this Oct 16, 2024
@manodasanW
Copy link
Member

At least for the build time change, this might be related to our source generator / analyzer in the Windows SDK projection having a perf impact on larger projects. We do have an updated Windows SDK projection package coming in next month's .NET SDK update with some performance improvements to the generator that I am hoping may help here. If you want to try out the change manually before it is in the .NET SDK, see here for the WindowsSdkPackageVersion to specify.

@DierkDroth
Copy link
Author

Thanks for your feedback @manodasanW.

Honestly I have no clue why I would need source generators / analyzers or even any "projection" on building (!) a solution.

Isn't there a way to get rid of all that? If so, what exactly would I need to do?

@DierkDroth
Copy link
Author

BTW I have these settings since ever, because I don't need all that stuff

Image

@DarranRowe
Copy link

Thanks for your feedback @manodasanW.

Honestly I have no clue why I would need source generators / analyzers or even any "projection" on building (!) a solution.

Isn't there a way to get rid of all that? If so, what exactly would I need to do?

For the projection, the answer is yes, but you honestly don't want to do that.

The Windows App SDK is a set of Windows Runtime components. Windows Runtime components are an evolution of COM. The projection is to make them much easier to use by mapping them to a more natural construct for the language. Without the projection, the components would have to be accessed via the ABI, which is more akin to accessing COM components.

I have had to do that in a C++ project, there was a need to access some Windows App SDK functionality but I was unable to use C++/WinRT (this is the recommended C++ projection). The equivalent of the following:

auto dispqueuec = winrt::Microsoft::UI::Dispatching::DispatcherQueueController::CreateOnCurrentThread();

ended up being:

template <typename Interface, typename RuntimeClass>
struct interface_traits
{
	static_assert(static_assert_helper<Interface>::value, "interface_traits is not specialised for this interface");
};
template <typename Interface, typename RuntimeClass>
struct factory_interface_traits
{
	static_assert(static_assert_helper<Interface>::value, "factory_interface_traits is not specialised for this interface");
};

template <>
struct interface_traits<ABI::Microsoft::UI::Dispatching::IDispatcherQueueController, ABI::Microsoft::UI::Dispatching::DispatcherQueueController>
{
	using type = ABI::Microsoft::UI::Dispatching::IDispatcherQueueController;
	using base_type = ABI::Microsoft::UI::Dispatching::IDispatcherQueueController;
	using class_type = ABI::Microsoft::UI::Dispatching::DispatcherQueueController;
	inline static constexpr std::wstring_view class_name{ init_stringview(RuntimeClass_Microsoft_UI_Dispatching_DispatcherQueueController) };
	inline static constexpr std::wstring_view interface_name{ init_stringview(InterfaceName_Microsoft_UI_Dispatching_IDispatcherQueueController) };
	inline static constexpr bool activatable = false;
};

template <>
struct factory_interface_traits<ABI::Microsoft::UI::Dispatching::IDispatcherQueueControllerStatics, ABI::Microsoft::UI::Dispatching::DispatcherQueueController>
{
	using type = ABI::Microsoft::UI::Dispatching::IDispatcherQueueControllerStatics;
	using class_type = ABI::Microsoft::UI::Dispatching::DispatcherQueueController;
	inline static constexpr std::wstring_view class_name{ init_stringview(RuntimeClass_Microsoft_UI_Dispatching_DispatcherQueueController) };
	inline static constexpr std::wstring_view interface_name{ init_stringview(InterfaceName_Microsoft_UI_Dispatching_IDispatcherQueueControllerStatics) };
};

inline Microsoft::WRL::Wrappers::HString initialise_hstring(const std::wstring_view &runtime_class)
	{
		HRESULT hr = S_OK;
		Microsoft::WRL::Wrappers::HString hs;
		hr = hs.Set(runtime_class.data());

		RoOriginateErrorW(hr, 0, L"Failed to set the runtime class name");
		THROW_IF_FAILED(hr);

		return hs;
	}

template <typename Interface, typename RuntimeClass>
	inline auto get_activation_factory()
	{
		HRESULT hr = S_OK;
		Microsoft::WRL::ComPtr<Interface> ret;
		auto runtime_class = initialise_hstring(factory_interface_traits<Interface, RuntimeClass>::class_name);
		hr = Windows::Foundation::GetActivationFactory(runtime_class, ret.ReleaseAndGetAddressOf());
		if (FAILED(hr))
		{
#if (__cplusplus >= 202002L || (defined _MSVC_LANG && _MSVC_LANG >= 202002L))
			auto l_fmtstr = application::helper::format_to_string(L"Failed to get activation factory. Interface name: {}, RuntimeClass name: {}", factory_interface_traits<Interface, RuntimeClass>::interface_name, factory_interface_traits<Interface, RuntimeClass>::class_name);
#else
			auto l_fmtstr = application::helper::format_to_string(L"Failed to get activation factory. Interface name: %s, RuntimeClass name: %s", factory_interface_traits<Interface, RuntimeClass>::interface_name.data(), factory_interface_traits<Interface, RuntimeClass>::class_name.data());
#endif
			RoOriginateErrorW(hr, static_cast<UINT>(l_fmtstr.length()), l_fmtstr.c_str());
			THROW_IF_FAILED(hr);
		}

		return ret;
	}

...
//Create dispatcher queue function
...

ComPtr<IDispatcherQueueController> disp_queue_ctrl;
auto dqcs = wrl_helpers::get_activation_factory<IDispatcherQueueControllerStatics, DispatcherQueueController>();

THROW_IF_FAILED(dqcs->CreateOnCurrentThread(disp_queue_ctrl.ReleaseAndGetAddressOf()));
...

I could have made it more compact if it was just using the ABI to access the Windows App SDK DispatcherQueue, but I was using some other Windows Runtime components through the ABI so I just added onto what I had.

This highlights two important things. First, using these components through the ABI requires a lot of code, and a lot of it is shared. Secondly, the components are usable for multiple languages.

@DierkDroth
Copy link
Author

DierkDroth commented Oct 17, 2024

@DarranRowe thanks for your feedback.

Here is my layman's thinking:
What you said is well and fine. Sure, I wanted to have easy-to-use 'wrappers' in my C# environment. But:

  • the WindowsAppSDK XX.YY is 'static' after installation (aka won't change). So, spending the effort once (!) after upgrade should be sufficient. Why would that negatively impact every (!) build run?
  • why would it impact building (!) the project in the first place? I needed those 'wrappers' when coding - e.g. through IntelliSense - and in fact there are there already (apparently). So, why spending the effort again on build?

Also, I'm sure there must have been something to the same effect with <= WindowsAppSDK 1.5. Why would WindowsAppSDK 1.6 performance be worse in that regard?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants