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
Merged
Show file tree
Hide file tree
Changes from7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -143,7 +143,12 @@ public static int SlowRuntimeTimeoutModifier
public static bool IsStartingProcessesSupported => !IsiOS && !IstvOS;

public static bool IsSpeedOptimized => !IsSizeOptimized;
public static bool IsSizeOptimized => IsBrowser || IsWasi || IsAndroid || IsAppleMobile;
public static bool IsSizeOptimized => s_linqIsSizeOptimized.Value;
private static readonly Lazy<bool> s_linqIsSizeOptimized = new Lazy<bool>(IsLinqSizeOptimized);
private static bool IsLinqSizeOptimized()
{
return (bool)typeof(Enumerable).GetMethod("get_IsSizeOptimized", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, Array.Empty<object>());
}

public static bool IsBrowserDomSupported => IsEnvironmentVariableTrue("IsBrowserDomSupported");
public static bool IsBrowserDomSupportedOrNotBrowser => IsNotBrowser || IsBrowserDomSupported;
Expand Down
13 changes: 3 additions & 10 deletionssrc/libraries/System.Linq/src/System.Linq.csproj
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
<ProjectSdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)-wasi;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos</TargetFrameworks>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<UseCompilerGeneratedDocXmlFile>false</UseCompilerGeneratedDocXmlFile>
</PropertyGroup>

<!-- 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.

<DefineConstantsCondition="'$(OptimizeForSize)' == 'true'">$(DefineConstants);OPTIMIZE_FOR_SIZE</DefineConstants>
</PropertyGroup>

<ItemGroupCondition="'$(OptimizeForSize)' == true">
<ItemGroup>
<CompileInclude="System\Linq\Skip.SizeOpt.cs" />
<CompileInclude="System\Linq\Take.SizeOpt.cs" />
</ItemGroup>

<ItemGroupCondition="'$(OptimizeForSize)' != true">
<ItemGroup>
<CompileInclude="System\Linq\AppendPrepend.SpeedOpt.cs" />
<CompileInclude="System\Linq\Cast.SpeedOpt.cs" />
<CompileInclude="System\Linq\Concat.SpeedOpt.cs" />
Expand Down
4 changes: 1 addition & 3 deletionssrc/libraries/System.Linq/src/System/Linq/AnyAll.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,8 +20,7 @@ public static bool Any<TSource>(this IEnumerable<TSource> source)
return gc.Count != 0;
}

#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> iterator)
if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
int count = iterator.GetCount(onlyIfCheap: true);
if (count >= 0)
Expand All@@ -32,7 +31,6 @@ public static bool Any<TSource>(this IEnumerable<TSource> source)
iterator.TryGetFirst(out bool found);
return found;
}
#endif

if (source is ICollection ngc)
{
Expand Down
8 changes: 2 additions & 6 deletionssrc/libraries/System.Linq/src/System/Linq/Count.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,12 +20,10 @@ public static int Count<TSource>(this IEnumerable<TSource> source)
return collectionoft.Count;
}

#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> iterator)
if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
return iterator.GetCount(onlyIfCheap: false);
}
#endif

if (source is ICollection collection)
{
Expand DownExpand Up@@ -115,8 +113,7 @@ public static bool TryGetNonEnumeratedCount<TSource>(this IEnumerable<TSource> s
return true;
}

#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> iterator)
if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
int c = iterator.GetCount(onlyIfCheap: true);
if (c >= 0)
Expand All@@ -125,7 +122,6 @@ public static bool TryGetNonEnumeratedCount<TSource>(this IEnumerable<TSource> s
return true;
}
}
#endif

if (source is ICollection collection)
{
Expand Down
8 changes: 2 additions & 6 deletionssrc/libraries/System.Linq/src/System/Linq/ElementAt.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,9 +23,7 @@ public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int i

bool found;
TSource? element =
#if !OPTIMIZE_FOR_SIZE
source is Iterator<TSource> iterator ? iterator.TryGetElementAt(index, out found) :
#endif
!IsSizeOptimized && source is Iterator<TSource> iterator ? iterator.TryGetElementAt(index, out found) :
TryGetElementAtNonIterator(source, index, out found);

if (!found)
Expand DownExpand Up@@ -123,9 +121,7 @@ public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, Index
}

return
#if !OPTIMIZE_FOR_SIZE
source is Iterator<TSource> iterator ? iterator.TryGetElementAt(index, out found) :
#endif
!IsSizeOptimized && source is Iterator<TSource> iterator ? iterator.TryGetElementAt(index, out found) :
TryGetElementAtNonIterator(source, index, out found);
}

Expand Down
4 changes: 4 additions & 0 deletionssrc/libraries/System.Linq/src/System/Linq/Enumerable.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,13 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Linq
{
public static partial class Enumerable
{
[FeatureSwitchDefinition("System.Linq.Enumerable.IsSizeOptimized")]
internal static bool IsSizeOptimized { get; } = AppContext.TryGetSwitch("System.Linq.Enumerable.IsSizeOptimized", out bool isEnabled) ? isEnabled : false;

public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source) => source;

/// <summary>Returns an empty <see cref="IEnumerable{TResult}"/>.</summary>
Expand Down
4 changes: 1 addition & 3 deletionssrc/libraries/System.Linq/src/System/Linq/First.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,9 +70,7 @@ public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source,
}

return
#if !OPTIMIZE_FOR_SIZE
source is Iterator<TSource> iterator ? iterator.TryGetFirst(out found) :
#endif
!IsSizeOptimized && source is Iterator<TSource> iterator ? iterator.TryGetFirst(out found) :
TryGetFirstNonIterator(source, out found);
}

Expand Down
8 changes: 3 additions & 5 deletionssrc/libraries/System.Linq/src/System/Linq/Iterator.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,11 +88,9 @@ public Iterator<TSource> GetEnumerator()
/// <typeparam name="TResult">The type of the mapped items.</typeparam>
/// <param name="selector">The selector used to map each item.</param>
public virtual IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector) =>
#if OPTIMIZE_FOR_SIZE
new IEnumerableSelectIterator<TSource, TResult>(this, selector);
#else
new IteratorSelectIterator<TSource, TResult>(this, selector);
#endif
!IsSizeOptimized
? new IteratorSelectIterator<TSource, TResult>(this, selector)
: new IEnumerableSelectIterator<TSource, TResult>(this, selector);


/// <summary>
Expand Down
4 changes: 1 addition & 3 deletionssrc/libraries/System.Linq/src/System/Linq/Last.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,9 +69,7 @@ public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source, F
}

return
#if !OPTIMIZE_FOR_SIZE
source is Iterator<TSource> iterator ? iterator.TryGetLast(out found) :
#endif
!IsSizeOptimized && source is Iterator<TSource> iterator ? iterator.TryGetLast(out found) :
TryGetLastNonIterator(source, out found);
}

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@ namespace System.Linq
{
public static partial class Enumerable
{
private static IEnumerable<TSource>SkipIterator<TSource>(IEnumerable<TSource> source, int count)
private static IEnumerable<TSource>SizeOptimizedSkipIterator<TSource>(IEnumerable<TSource> source, int count)
{
using IEnumerator<TSource> e = source.GetEnumerator();
while (count > 0 && e.MoveNext()) count--;
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@ namespace System.Linq
{
public static partial class Enumerable
{
private static IEnumerable<TSource>SkipIterator<TSource>(IEnumerable<TSource> source, int count) =>
private static IEnumerable<TSource>SpeedOptimizedSkipIterator<TSource>(IEnumerable<TSource> source, int count) =>
source is IList<TSource> sourceList ?
(IEnumerable<TSource>)new IListSkipTakeIterator<TSource>(sourceList, count, int.MaxValue) :
new IEnumerableSkipTakeIterator<TSource>(source, count, -1);
Expand Down
6 changes: 2 additions & 4 deletionssrc/libraries/System.Linq/src/System/Linq/Skip.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,14 +30,12 @@ public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> sourc

count = 0;
}
#if !OPTIMIZE_FOR_SIZE
else if (source is Iterator<TSource> iterator)
else if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
return iterator.Skip(count) ?? Empty<TSource>();
}
#endif

returnSkipIterator(source, count);
returnIsSizeOptimized ? SizeOptimizedSkipIterator(source, count) : SpeedOptimizedSkipIterator(source, count);
}

public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
Expand Down
4 changes: 2 additions & 2 deletionssrc/libraries/System.Linq/src/System/Linq/Take.SizeOpt.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ namespace System.Linq
{
public static partial class Enumerable
{
private static IEnumerable<TSource>TakeIterator<TSource>(IEnumerable<TSource> source, int count)
private static IEnumerable<TSource>SizeOptimizedTakeIterator<TSource>(IEnumerable<TSource> source, int count)
{
Debug.Assert(count > 0);

Expand All@@ -19,7 +19,7 @@ private static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> s
}
}

private static IEnumerable<TSource>TakeRangeIterator<TSource>(IEnumerable<TSource> source, int startIndex, int endIndex)
private static IEnumerable<TSource>SizeOptimizedTakeRangeIterator<TSource>(IEnumerable<TSource> source, int startIndex, int endIndex)
{
Debug.Assert(source is not null);
Debug.Assert(startIndex >= 0 && startIndex < endIndex);
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ namespace System.Linq
{
public static partial class Enumerable
{
private static IEnumerable<TSource>TakeIterator<TSource>(IEnumerable<TSource> source, int count)
private static IEnumerable<TSource>SpeedOptimizedTakeIterator<TSource>(IEnumerable<TSource> source, int count)
{
Debug.Assert(source is not null && !IsEmptyArray(source));
Debug.Assert(count > 0);
Expand All@@ -19,7 +19,7 @@ private static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> s
new IEnumerableSkipTakeIterator<TSource>(source, 0, count - 1);
}

private static IEnumerable<TSource>TakeRangeIterator<TSource>(IEnumerable<TSource> source, int startIndex, int endIndex)
private static IEnumerable<TSource>SpeedOptimizedTakeRangeIterator<TSource>(IEnumerable<TSource> source, int startIndex, int endIndex)
{
Debug.Assert(source is not null && !IsEmptyArray(source));
Debug.Assert(startIndex >= 0 && startIndex < endIndex);
Expand Down
23 changes: 16 additions & 7 deletionssrc/libraries/System.Linq/src/System/Linq/Take.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,9 +15,12 @@ public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> sourc
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}

return count <= 0 || IsEmptyArray(source) ?
[] :
TakeIterator(source, count);
if (count <= 0 || IsEmptyArray(source))
{
return [];
}

return IsSizeOptimized ? SizeOptimizedTakeIterator(source, count) : SpeedOptimizedTakeIterator(source, count);
}

/// <summary>Returns a specified range of contiguous elements from a sequence.</summary>
Expand DownExpand Up@@ -60,9 +63,12 @@ public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> sourc
}
else if (!isEndIndexFromEnd)
{
return startIndex >= endIndex ?
[] :
TakeRangeIterator(source, startIndex, endIndex);
if (startIndex >= endIndex)
{
return [];
}

return IsSizeOptimized ? SizeOptimizedTakeRangeIterator(source, startIndex, endIndex) : SpeedOptimizedTakeRangeIterator(source, startIndex, endIndex);
}

return TakeRangeFromEndIterator(source, isStartIndexFromEnd, startIndex, isEndIndexFromEnd, endIndex);
Expand All@@ -88,7 +94,10 @@ private static IEnumerable<TSource> TakeRangeFromEndIterator<TSource>(IEnumerabl

if (startIndex < endIndex)
{
foreach (TSource element in TakeRangeIterator(source, startIndex, endIndex))
IEnumerable<TSource> rangeIterator = IsSizeOptimized
? SizeOptimizedTakeRangeIterator(source, startIndex, endIndex)
: SpeedOptimizedTakeRangeIterator(source, startIndex, endIndex);
foreach (TSource element in rangeIterator)
{
yield return element;
}
Expand Down
8 changes: 2 additions & 6 deletionssrc/libraries/System.Linq/src/System/Linq/ToCollection.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,12 +11,10 @@ public static partial class Enumerable
{
public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
{
#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> iterator)
if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
return iterator.ToArray();
}
#endif

if (source is ICollection<TSource> collection)
{
Expand DownExpand Up@@ -64,12 +62,10 @@ public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}

#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> iterator)
if (!IsSizeOptimized && source is Iterator<TSource> iterator)
{
return iterator.ToList();
}
#endif

return new List<TSource>(source);
}
Expand Down
7 changes: 3 additions & 4 deletionssrc/libraries/System.Linq/tests/CountTests.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -178,10 +178,11 @@ public static IEnumerable<object[]> NonEnumeratedCount_SupportedEnumerables()

yield return WrapArgs(0, Enumerable.Empty<string>());

yield return WrapArgs(100, Enumerable.Range(1, 100));
yield return WrapArgs(80, Enumerable.Repeat(1, 80));

if (PlatformDetection.IsSpeedOptimized)
{
yield return WrapArgs(100, Enumerable.Range(1, 100));
yield return WrapArgs(80, Enumerable.Repeat(1, 80));
yield return WrapArgs(50, Enumerable.Range(1, 50).Select(x => x + 1));
yield return WrapArgs(4, new int[] { 1, 2, 3, 4 }.Select(x => x + 1));
yield return WrapArgs(50, Enumerable.Range(1, 50).Select(x => x + 1).Select(x => x - 1));
Expand All@@ -202,8 +203,6 @@ public static IEnumerable<object[]> NonEnumeratedCount_UnsupportedEnumerables()

if (!PlatformDetection.IsSpeedOptimized)
{
yield return WrapArgs(Enumerable.Range(1, 100));
yield return WrapArgs(Enumerable.Repeat(1, 80));
yield return WrapArgs(Enumerable.Range(1, 50).Select(x => x + 1));
yield return WrapArgs(new int[] { 1, 2, 3, 4 }.Select(x => x + 1));
yield return WrapArgs(Enumerable.Range(1, 50).Select(x => x + 1).Select(x => x - 1));
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp