Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Replace OPTIMIZE_FOR_SIZE with feature switch#111743

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
MichalStrehovsky merged 10 commits intodotnet:mainfromMichalStrehovsky:sizeoptswitch
Jan 30, 2025

Conversation

@MichalStrehovsky
Copy link
Member

When I was looking at this last time, I noticed the virtual method overrides and though it's not solvable with feature switches. But looks like the virtual methods are not actually called outside!OPTIMIZE_FOR_SIZE code so we might still be able to trim things correctly if it's a feature switch (we can remove unused virtual methods).

The only problem is maintainability - how do we remember that we should only call the virtuals under a!IsSizeOptimized check. The ifdef was a nice forcing function enforced by the compiler.

@dotnet-policy-service
Copy link
Contributor

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

@MichalStrehovsky
Copy link
MemberAuthor

Oh nice:

Size statistics

Pull request#111743

ProjectSize beforeSize afterDifference
avalonia.app-windows 19096064 18085888-1010176
hello-minimal-windows 857600 8576000
hello-windows 1102848 11028480
kestrel-minimal-windows 4898816 4804096-94720
reflection-windows 1748992 17489920
webapiaot-windows 9154048 8944640-209408
winrt-component-full-windows 5728768 5728256-512
winrt-component-minimal-windows 1760768 17607680
PaulusParssinen, neon-sunset, and slang25 reacted with hooray emojiPaulusParssinen reacted with rocket emoji

@stephentoub
Copy link
Member

I would love it if we could remove the compilation constant, have a single build, and just achieve desired size reduction in certain environments via the feature switch.

@MichalStrehovsky
Copy link
MemberAuthor

I would love it if we could remove the compilation constant, have a single build, and just achieve desired size reduction in certain environments via the feature switch.

Do you have any opinion on how to achieve the "The only problem is maintainability - how do we remember that we should only call the virtuals under a !IsSizeOptimized check." part? I was thinking about leaving the .SpeedOpt.cs files around to keep the virtuals separated at least in files. It won't help much, but it's at least something.

@MichalStrehovsky
Copy link
MemberAuthor

Do you have any opinion on how to achieve the "The only problem is maintainability - how do we remember that we should only call the virtuals under a !IsSizeOptimized check."

Hmm, I guess this is the spot where we could use the generalized feature guards.@sbomer - did we implement that part? (I'm not able to find it right now, so my guess is no, but wanted to check.)

@sbomer
Copy link
Member

@sbomer - did we implement that part? (I'm not able to find it right now, so my guess is no, but wanted to check.)

Nope, only for RequiresUnreferencedCode/RequiresDynamicCode/RequiresAssemblyFiles.

@MichalStrehovsky
Copy link
MemberAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovskyMichalStrehovsky marked this pull request as ready for reviewJanuary 24, 2025 13:21
@MichalStrehovskyMichalStrehovsky changed the titleSee if we can replace OPTIMIZE_FOR_SIZE with feature switchReplace OPTIMIZE_FOR_SIZE with feature switchJan 24, 2025
@MichalStrehovsky
Copy link
MemberAuthor

I marked this ready for review. Not all tests pass. It turns out we cannot fully replace this with a feature switch.

This part is the problem:

privatesealedpartialclassRangeIterator:IList<int>,IReadOnlyList<int>

We cannot express "this class only implements the interface if a feature switch is defined". And this is a popular interface.

I'll try to measure how much that matters in a separate PR (#111794). The extra interface will only really matter for AOT.

We can adjusts the test to expect this to pass, that's the least problem.

@ivanpovazan is it easy enough to measure the size impact of this on iOS? This is replacing the special build of System.Linq with a common assembly that is same across platforms. There's now a feature switch to enable size savings.

To enable the feature switch, one currently needs to add:

  <ItemGroup>    <RuntimeHostConfigurationOptionInclude="System.Linq.Enumerable.IsSizeOptimized"Value="true"Trim="true" />  </ItemGroup>

The expectation is that we would introduce a property to wrap it, and default the property on iOS/Android/etc. totrue.

@stephentoub
Copy link
Member

Do you have any opinion on how to achieve the "The only problem is maintainability - how do we remember that we should only call the virtuals under a !IsSizeOptimized check." part? I was thinking about leaving the .SpeedOpt.cs files around to keep the virtuals separated at least in files. It won't help much, but it's at least something.

We could have an analyzer just for that library. Better would be to build out the unimplemented parts of feature guards and then use it here. We could explore having a separate build of the library that we test but don't ship and that implements the guarded functionality to throw. But probably most simply, we could rely on size regression tests to point out any place we make a mistake and then fix it, as we do with other performance-focused issues.

@ivanpovazan
Copy link
Member

@ivanpovazan is it easy enough to measure the size impact of this on iOS? This is replacing the special build of System.Linq with a common assembly that is same across platforms. There's now a feature switch to enable size savings.

Unfortunately it is tricky. Especially since we would like to measure the size impact on MAUI iOS apps and net10 builds are currently unstable.

Would it be possible to apply these changes on top of net9 branch (not sure if there are any dependencies from the point we branched to net10) ? I could then use the official net9 workloads with local build of your changes to see the impact.

@MichalStrehovsky
Copy link
MemberAuthor

Would it be possible to apply these changes on top of net9 branch (not sure if there are any dependencies from the point we branched to net10) ? I could then use the official net9 workloads with local build of your changes to see the impact.

Yeah, this applies pretty cleanly to 9.0 and I don't think there's prerequisites. Here's a branch:https://github.com/MichalStrehovsky/runtime/pull/new/sizeoptswitch-net9

The important bit when measuring is that we need to set the feature switch, or this will be a regression for sure.

Here are the numbers for the couple test apps with native AOT using OPTIMIZE_FOR_SIZE. It is better with the ifdef, but not by much. I'd expect a similar picture for Mono AOT.

Size statistics

Pull request#111794

ProjectSize beforeSize afterDifference
avalonia.app-windows 19096064 18072576-1023488
hello-minimal-windows 857600 8576000
hello-windows 1102848 11028480
kestrel-minimal-windows 4898816 4804096-94720
reflection-windows 1748992 17489920
webapiaot-windows 9154048 8943104-210944
winrt-component-full-windows 5728256 57282560
winrt-component-minimal-windows 1760256 17602560

@MichalStrehovsky
Copy link
MemberAuthor

Here are the numbers for the couple test apps with native AOT using OPTIMIZE_FOR_SIZE. It is better with the ifdef, but not by much.

(Need to compare with the table in my previous comment, not the "size before". The "size before" is main branch.)

@MichalStrehovsky
Copy link
MemberAuthor

But probably most simply, we could rely on size regression tests to point out any place we make a mistake and then fix it, as we do with other performance-focused issues.

Yeah, I guess that would work. It will require some skill to root cause but if enough people remember that some virtuals are special (and we should probably keep them special in the .SpeedOpt.cs files), it should be workable.

@MichalStrehovsky
Copy link
MemberAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky
Copy link
MemberAuthor

@MichalStrehovsky It seems the optimization only cuts-off the regression introduced, is that expected?

Yep, this just replaces ifdef with a configurable feature switch. There were valid questions in#109978 (that introduces a feature switch for LINQ) why we should have both ifdefs and feature switches. So this is a preparatory change for that.

@MichalStrehovsky
Copy link
MemberAuthor

@MichalStrehovsky
Copy link
MemberAuthor

/azp run runtime-nativeaot-outerloop

@MichalStrehovsky
Copy link
MemberAuthor

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

1 similar comment
@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group.-->
<PropertyGroup>
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
<OptimizeForSizeCondition="'$(TargetPlatformIdentifier)' == 'browser' or '$(TargetPlatformIdentifier)' == 'android' or '$(TargetPlatformIdentifier)' == 'ios' or '$(TargetPlatformIdentifier)' == 'tvos'">true</OptimizeForSize>
Copy link
Member

@pavelsavarapavelsavaraJan 29, 2025
edited
Loading

Choose a reason for hiding this comment

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

OptimizeForSize was set true for some targets but it's not anymore.
WasmFeatures.props set the default for wasm workload, but default runtime pack also needs to be optimized for size - when people don't use workload in Blazor.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

OptimizeForSize was set true for some targets but it's not anymore.

Yes, that is the purpose of this PR. To only have one build of this library (#111743 (comment))

WasmFeatures.props set the default for wasm workload, but default runtime pack also needs to be optimized for size - when people don't use workload in Blazor.

Could you please point me to which .targets we need to update? Is it the Microsoft.NET.Sdk.BlazorWebAssembly.6_0.targets linked from#111743 (comment)?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

(To be clear, the OptimizeForSize property controls whether we build System.Linq assembly in a not-fully-compatible manner (see the tests I'm touching where it behaves differently) that has better size characteristics. This PR deletes that build and changes it to always build the compatible Linq implementation. It introduces a feature switch that allows switching to the not-fully-compatible mode. The default for the feature switch is disabled. It can be enabled where the tradeoff is worth it (I have PRs out enabling it in places, linked above). The advantage is that now if a customer runs into the incompatibility, they can just set a property and unblock themselves.)

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Thank you! Folded the BlazorWebAssembly.targets change intodotnet/sdk#46375.

WasmFeatures.props change is already part of the PR here.

MichalStrehovsky added a commit to dotnet/sdk that referenced this pull requestJan 29, 2025
@MichalStrehovskyMichalStrehovsky merged commitadf123c intodotnet:mainJan 30, 2025
149 of 157 checks passed
@MichalStrehovskyMichalStrehovsky deleted the sizeoptswitch branchJanuary 30, 2025 08:36
grendello added a commit to grendello/runtime that referenced this pull requestJan 30, 2025
* main: (31 commits)  More native AOT Pri-1 test tree bring up (dotnet#111994)  Fix BigInteger outerloop test (dotnet#111841)  JIT: Run 3-opt once across all regions (dotnet#111989)  JIT: Check for profile consistency throughout JIT backend (dotnet#111684)  [JIT] Add legacy extended EVEX encoding and EVEX.ND/NF feature to x64 emitter backend (dotnet#108796)  [iOS][globalization] Fix IndexOf on empty strings on iOS to return -1 (dotnet#111898)  System.Speech: Use intellisense xml from dotnet-api-docs (dotnet#111983)  [mono][mini] Disable inlining if we encounter class initialization failure (dotnet#111754)  [main] Update dependencies from dotnet/roslyn (dotnet#111946)  Update dependencies fromhttps://github.com/dotnet/arcade build 20250129.2 (dotnet#111996)  Try changing the ICustomQueryInterface implementation to always return NotHandled instead of Failed to defer back to the ComWrappers impl. (dotnet#111978)  Combined dependency update (dotnet#111852)  Replace OPTIMIZE_FOR_SIZE with feature switch (dotnet#111743)  Fix failed assertion 'FPbased == FPbased2' (dotnet#111787)  Add remark to `ConditionalSelect` (dotnet#111945)  JIT: fix try region cloning when try is nested in a handler (dotnet#111975)  Use IRootFunctions in Tensor.StdDev (dotnet#110641)  Remove zlib dependencies from Docker containers (dotnet#111939)  Avoid `Unsafe.As` for `Memory<T>` and `ReadOnlyMemory<T>` conversion (dotnet#111023)  Cleanup membarrier portability (dotnet#111943)  ...
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsMar 1, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@pavelsavarapavelsavarapavelsavara left review comments

@stephentoubstephentoubstephentoub approved these changes

@eerhardteerhardteerhardt left review comments

@lewinglewingAwaiting requested review from lewinglewing is a code owner

@akoeplingerakoeplingerAwaiting requested review from akoeplingerakoeplinger is a code owner

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

6 participants

@MichalStrehovsky@stephentoub@sbomer@ivanpovazan@pavelsavara@eerhardt

[8]ページ先頭

©2009-2025 Movatter.jp