From 4800f49c732e1f76ca5b02fdc6d32f2200124de4 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Sat, 30 Sep 2023 12:28:39 +0200 Subject: [PATCH 1/3] perf: Micro optimization EndsWith using --- src/Avalonia.Base/Animation/Cue.cs | 2 +- src/Avalonia.Base/Media/Fonts/FontFamilyLoader.cs | 6 +++--- src/Avalonia.Base/RelativePoint.cs | 4 ++-- .../GenerateAvaloniaResourcesTask.cs | 7 +++++-- .../XamlCompilerTaskExecutor.cs | 14 +++++++++----- .../NameGenerator/AvaloniaNameGenerator.cs | 9 +++++---- .../CompositionRoslynGenerator.cs | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Base/Animation/Cue.cs b/src/Avalonia.Base/Animation/Cue.cs index c48f2ab6b0b..5fa3ca812f0 100644 --- a/src/Avalonia.Base/Animation/Cue.cs +++ b/src/Avalonia.Base/Animation/Cue.cs @@ -34,7 +34,7 @@ public static Cue Parse(string value, CultureInfo? culture) { string v = value; - if (value.EndsWith("%")) + if (value.Length > 0 && value[value.Length -1 ] == '%') { v = v.TrimEnd('%'); } diff --git a/src/Avalonia.Base/Media/Fonts/FontFamilyLoader.cs b/src/Avalonia.Base/Media/Fonts/FontFamilyLoader.cs index 37992c895e5..2c61ffd4194 100644 --- a/src/Avalonia.Base/Media/Fonts/FontFamilyLoader.cs +++ b/src/Avalonia.Base/Media/Fonts/FontFamilyLoader.cs @@ -94,14 +94,14 @@ private static bool IsContainsFile(Uri x, string filePattern, string fileExtensi { var path = x.GetUnescapeAbsolutePath(); return path.IndexOf(filePattern, StringComparison.Ordinal) >= 0 - && path.EndsWith(fileExtension, StringComparison.Ordinal); + && path.EndsWith(fileExtension, StringComparison.OrdinalIgnoreCase); } private static bool IsFontTtfOrOtf(Uri uri) { var sourceWithoutArguments = GetSubString(uri.OriginalString, '?'); - return sourceWithoutArguments.EndsWith(".ttf", StringComparison.Ordinal) - || sourceWithoutArguments.EndsWith(".otf", StringComparison.Ordinal); + return sourceWithoutArguments.EndsWith(".ttf", StringComparison.OrdinalIgnoreCase) + || sourceWithoutArguments.EndsWith(".otf", StringComparison.OrdinalIgnoreCase); } private static (string fileNameWithoutExtension, string extension) GetFileNameAndExtension( diff --git a/src/Avalonia.Base/RelativePoint.cs b/src/Avalonia.Base/RelativePoint.cs index 5f04f4d57f8..1785883a61f 100644 --- a/src/Avalonia.Base/RelativePoint.cs +++ b/src/Avalonia.Base/RelativePoint.cs @@ -164,9 +164,9 @@ public static RelativePoint Parse(string s) var unit = RelativeUnit.Absolute; var scale = 1.0; - if (x.EndsWith("%")) + if (x.Length > 0 && x[x.Length - 1] == '%') { - if (!y.EndsWith("%")) + if (!(y.Length > 0 && y[y.Length - 1] == '%')) { throw new FormatException("If one coordinate is relative, both must be."); } diff --git a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs index 620cd4723d4..86c04132a08 100644 --- a/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs +++ b/src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs @@ -88,7 +88,10 @@ private bool PreProcessXamlFiles(List sources) foreach (var s in sources.ToArray()) { - if (s.Path.ToLowerInvariant().EndsWith(".xaml") || s.Path.ToLowerInvariant().EndsWith(".paml") || s.Path.ToLowerInvariant().EndsWith(".axaml")) + var path = s.Path; + if (path.EndsWith(".axaml", StringComparison.OrdinalIgnoreCase) + || path.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase) + || path.EndsWith(".paml", StringComparison.OrdinalIgnoreCase) ) { XamlFileInfo info; try @@ -110,7 +113,7 @@ private bool PreProcessXamlFiles(List sources) $"Duplicate x:Class directive, {info.XClass} is already used in {typeToXamlIndex[info.XClass]}"); return false; } - typeToXamlIndex[info.XClass] = s.Path; + typeToXamlIndex[info.XClass] = path; } } } diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index 469a51f32a5..b99c209ec4f 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -23,11 +23,15 @@ namespace Avalonia.Build.Tasks public static partial class XamlCompilerTaskExecutor { private const string CompiledAvaloniaXamlNamespace = "CompiledAvaloniaXaml"; - - static bool CheckXamlName(IResource r) => r.Name.ToLowerInvariant().EndsWith(".xaml") - || r.Name.ToLowerInvariant().EndsWith(".paml") - || r.Name.ToLowerInvariant().EndsWith(".axaml"); - + + static bool CheckXamlName(IResource r) + { + var name = r.Name; + return name.EndsWith(".axaml", StringComparison.OrdinalIgnoreCase) + || name.EndsWith(".xaml",StringComparison.OrdinalIgnoreCase) + || name.EndsWith(".paml", StringComparison.OrdinalIgnoreCase); + } + public class CompileResult { public bool Success { get; set; } diff --git a/src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameGenerator.cs b/src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameGenerator.cs index fa20be721c1..67389ef826e 100644 --- a/src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameGenerator.cs +++ b/src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameGenerator.cs @@ -36,10 +36,11 @@ public IEnumerable GenerateNameReferences(IEnumerable file.Path.EndsWith("composition-schema.xml")); + context.AdditionalTextsProvider.Where(static file => file.Path.EndsWith("composition-schema.xml", System.StringComparison.OrdinalIgnoreCase)); var configs = schema.Select((t, _) => t.GetText()) .Where(source => source is not null) .Select((source, _) => (GConfig)new XmlSerializer(typeof(GConfig)).Deserialize(new StringReader(source!.ToString()))); From 27a0d399585b17393d53f9a5141d5a5ed42f8b59 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Sun, 1 Oct 2023 10:11:48 +0200 Subject: [PATCH 2/3] fix: Address reviews --- Avalonia.sln | 2 +- src/Avalonia.Base/Animation/Cue.cs | 2 +- src/Avalonia.Base/Media/Color.cs | 4 ++-- src/Avalonia.Base/Media/HslColor.cs | 4 ++-- src/Avalonia.Base/RelativePoint.cs | 4 ++-- src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj | 5 +++++ src/Shared/StringCompatibilityExtensions.cs | 8 ++++++++ 7 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Avalonia.sln b/Avalonia.sln index 2777f1b923f..2f2acb4bde6 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -42,7 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs src\Shared\NullableAttributes.cs = src\Shared\NullableAttributes.cs src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs - src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs = src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs + src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}" diff --git a/src/Avalonia.Base/Animation/Cue.cs b/src/Avalonia.Base/Animation/Cue.cs index 5fa3ca812f0..793bd16f6f4 100644 --- a/src/Avalonia.Base/Animation/Cue.cs +++ b/src/Avalonia.Base/Animation/Cue.cs @@ -34,7 +34,7 @@ public static Cue Parse(string value, CultureInfo? culture) { string v = value; - if (value.Length > 0 && value[value.Length -1 ] == '%') + if (value.EndsWith('%')) { v = v.TrimEnd('%'); } diff --git a/src/Avalonia.Base/Media/Color.cs b/src/Avalonia.Base/Media/Color.cs index 17ee14e5332..d100fa28226 100644 --- a/src/Avalonia.Base/Media/Color.cs +++ b/src/Avalonia.Base/Media/Color.cs @@ -346,7 +346,7 @@ private static bool TryParseCssFormat(string? s, out Color color) if (workingString.Length >= 11 && workingString.StartsWith("rgba(", StringComparison.OrdinalIgnoreCase) && - workingString.EndsWith(")", StringComparison.Ordinal)) + workingString.EndsWith(')')) { workingString = workingString.Substring(5, workingString.Length - 6); prefixMatched = true; @@ -355,7 +355,7 @@ private static bool TryParseCssFormat(string? s, out Color color) if (prefixMatched == false && workingString.Length >= 10 && workingString.StartsWith("rgb(", StringComparison.OrdinalIgnoreCase) && - workingString.EndsWith(")", StringComparison.Ordinal)) + workingString.EndsWith(')')) { workingString = workingString.Substring(4, workingString.Length - 5); prefixMatched = true; diff --git a/src/Avalonia.Base/Media/HslColor.cs b/src/Avalonia.Base/Media/HslColor.cs index 84f2149367e..02176d65d72 100644 --- a/src/Avalonia.Base/Media/HslColor.cs +++ b/src/Avalonia.Base/Media/HslColor.cs @@ -256,7 +256,7 @@ public static bool TryParse(string? s, out HslColor hslColor) if (workingString.Length >= 11 && workingString.StartsWith("hsla(", StringComparison.OrdinalIgnoreCase) && - workingString.EndsWith(")", StringComparison.Ordinal)) + workingString.EndsWith(')')) { workingString = workingString.Substring(5, workingString.Length - 6); prefixMatched = true; @@ -265,7 +265,7 @@ public static bool TryParse(string? s, out HslColor hslColor) if (prefixMatched == false && workingString.Length >= 10 && workingString.StartsWith("hsl(", StringComparison.OrdinalIgnoreCase) && - workingString.EndsWith(")", StringComparison.Ordinal)) + workingString.EndsWith(')')) { workingString = workingString.Substring(4, workingString.Length - 5); prefixMatched = true; diff --git a/src/Avalonia.Base/RelativePoint.cs b/src/Avalonia.Base/RelativePoint.cs index 1785883a61f..c20c279c00a 100644 --- a/src/Avalonia.Base/RelativePoint.cs +++ b/src/Avalonia.Base/RelativePoint.cs @@ -164,9 +164,9 @@ public static RelativePoint Parse(string s) var unit = RelativeUnit.Absolute; var scale = 1.0; - if (x.Length > 0 && x[x.Length - 1] == '%') + if (x.EndsWith('%')) { - if (!(y.Length > 0 && y[y.Length - 1] == '%')) + if (!y.EndsWith('%')) { throw new FormatException("If one coordinate is relative, both must be."); } diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj index bc36c610c7c..5dbd5ba0ed1 100644 --- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj +++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj @@ -118,11 +118,16 @@ + + + + + diff --git a/src/Shared/StringCompatibilityExtensions.cs b/src/Shared/StringCompatibilityExtensions.cs index 7c894dba97c..b978229581e 100644 --- a/src/Shared/StringCompatibilityExtensions.cs +++ b/src/Shared/StringCompatibilityExtensions.cs @@ -8,5 +8,13 @@ internal static class StringCompatibilityExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Contains(this string str, char search) => str.Contains(search.ToString()); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EndsWith(this string str, char search) => + str?.Length switch + { + int len when len > 0 => str[len - 1] == search, + _ => false + }; } #endif From 2010febe5926972353d1428bc530df1f4c359f2e Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Sun, 1 Oct 2023 18:27:51 +0200 Subject: [PATCH 3/3] fix: Address reviews --- src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj | 4 ---- src/Shared/StringCompatibilityExtensions.cs | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj index 5dbd5ba0ed1..55a72c4af91 100644 --- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj +++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj @@ -125,9 +125,5 @@ - - - - diff --git a/src/Shared/StringCompatibilityExtensions.cs b/src/Shared/StringCompatibilityExtensions.cs index b978229581e..dc694e6af59 100644 --- a/src/Shared/StringCompatibilityExtensions.cs +++ b/src/Shared/StringCompatibilityExtensions.cs @@ -11,10 +11,6 @@ public static bool Contains(this string str, char search) => [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EndsWith(this string str, char search) => - str?.Length switch - { - int len when len > 0 => str[len - 1] == search, - _ => false - }; + str.Length > 0 && str[str.Length - 1] == search; } #endif