Skip to content

Commit def9bd0

Browse files
Less parsing, allocation & LINQ when splitting strings (#18048)
* Less parsing, allocation & LINQ when splitting strings * Added unit test verifying refactoring of GetIdsFromPathReversed. --------- Co-authored-by: Andy Butland <[email protected]>
1 parent c64ec51 commit def9bd0

File tree

7 files changed

+47
-30
lines changed

7 files changed

+47
-30
lines changed

src/Umbraco.Core/DynamicRoot/Origin/SiteDynamicRootOriginFinder.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ public SiteDynamicRootOriginFinder(IEntityService entityService, IDomainService
3333
return null;
3434
}
3535

36-
37-
IEnumerable<string> reversePath = entity.Path.Split(",").Reverse();
38-
foreach (var contentIdString in reversePath)
36+
string[] contentIdStrings = entity.Path.Split(',');
37+
for (int i = contentIdStrings.Length - 1; i >= 0; i--)
3938
{
40-
var contentId = int.Parse(contentIdString, NumberStyles.Integer, CultureInfo.InvariantCulture);
39+
var contentId = int.Parse(contentIdStrings[i], NumberStyles.Integer, CultureInfo.InvariantCulture);
4140
IEnumerable<IDomain> domains = _domainService.GetAssignedDomains(contentId, true);
4241
if (!domains.Any())
4342
{

src/Umbraco.Core/Extensions/StringExtensions.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,17 @@ static StringExtensions()
5757
/// <returns></returns>
5858
public static int[] GetIdsFromPathReversed(this string path)
5959
{
60-
var nodeIds = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
61-
.Select(x =>
62-
int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var output)
63-
? Attempt<int>.Succeed(output)
64-
: Attempt<int>.Fail())
65-
.Where(x => x.Success)
66-
.Select(x => x.Result)
67-
.Reverse()
68-
.ToArray();
69-
return nodeIds;
60+
string[] pathSegments = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries);
61+
List<int> nodeIds = new(pathSegments.Length);
62+
for (int i = pathSegments.Length - 1; i >= 0; i--)
63+
{
64+
if (int.TryParse(pathSegments[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out int pathSegment))
65+
{
66+
nodeIds.Add(pathSegment);
67+
}
68+
}
69+
70+
return nodeIds.ToArray();
7071
}
7172

7273
/// <summary>
@@ -79,7 +80,7 @@ public static int[] GetIdsFromPathReversed(this string path)
7980
public static string StripFileExtension(this string fileName)
8081
{
8182
// filenames cannot contain line breaks
82-
if (fileName.Contains(Environment.NewLine) || fileName.Contains("\r") || fileName.Contains("\n"))
83+
if (fileName.Contains('\n') || fileName.Contains('\r'))
8384
{
8485
return fileName;
8586
}
@@ -434,8 +435,7 @@ public static IList<string> ToDelimitedList(this string list, string delimiter =
434435
{
435436
var delimiters = new[] { delimiter };
436437
return !list.IsNullOrWhiteSpace()
437-
? list.Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
438-
.Select(i => i.Trim())
438+
? list.Split(delimiters, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
439439
.ToList()
440440
: new List<string>();
441441
}
@@ -617,7 +617,7 @@ public static bool InvariantEndsWith(this string compare, string compareTo) =>
617617
compare.EndsWith(compareTo, StringComparison.InvariantCultureIgnoreCase);
618618

619619
public static bool InvariantContains(this string compare, string compareTo) =>
620-
compare.IndexOf(compareTo, StringComparison.OrdinalIgnoreCase) >= 0;
620+
compare.Contains(compareTo, StringComparison.OrdinalIgnoreCase);
621621

622622
public static bool InvariantContains(this IEnumerable<string> compare, string compareTo) =>
623623
compare.Contains(compareTo, StringComparer.InvariantCultureIgnoreCase);

src/Umbraco.Core/Extensions/TreeEntityExtensions.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,20 @@ namespace Umbraco.Cms.Core.Extensions;
55

66
public static class TreeEntityExtensions
77
{
8-
public static int[] AncestorIds(this ITreeEntity entity) => entity.Path
9-
.Split(Constants.CharArrays.Comma)
10-
.Select(item => int.Parse(item, CultureInfo.InvariantCulture))
11-
.Take(new Range(Index.FromStart(1), Index.FromEnd(1)))
12-
.ToArray();
8+
public static int[] AncestorIds(this ITreeEntity entity)
9+
{
10+
string[] commaSeparatedValues = entity.Path.Split(Constants.CharArrays.Comma);
11+
if (commaSeparatedValues.Length < 2)
12+
{
13+
return [];
14+
}
15+
16+
int[] ancestorIds = new int[commaSeparatedValues.Length - 2];
17+
for (int i = 1; i <= commaSeparatedValues.Length - 2; i++)
18+
{
19+
ancestorIds[i - 1] = int.Parse(commaSeparatedValues[i], CultureInfo.InvariantCulture);
20+
}
21+
22+
return ancestorIds;
23+
}
1324
}

src/Umbraco.Core/Models/PropertyTagsExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,12 @@ private static IEnumerable<string> GetTagsValue(this IProperty property, TagsSto
226226
switch (storageType)
227227
{
228228
case TagsStorageType.Csv:
229-
return value.Split(new[] { delimiter }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim());
229+
return value.Split([delimiter], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
230230

231231
case TagsStorageType.Json:
232232
try
233233
{
234-
return serializer.Deserialize<string[]>(value)?.Select(x => x.Trim()) ?? Enumerable.Empty<string>();
234+
return serializer.Deserialize<string[]>(value)?.Select(x => x.Trim()) ?? [];
235235
}
236236
catch (Exception)
237237
{

src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static string Localize(this ILocalizedTextService manager, string area, s
5252
return null;
5353
}
5454

55-
if (text.StartsWith("#") == false)
55+
if (text.StartsWith('#') == false)
5656
{
5757
return text;
5858
}
@@ -64,7 +64,7 @@ public static string Localize(this ILocalizedTextService manager, string area, s
6464
return value;
6565
}
6666

67-
if (text.IndexOf('_') == -1)
67+
if (!text.Contains('_'))
6868
{
6969
return text;
7070
}
@@ -77,7 +77,7 @@ public static string Localize(this ILocalizedTextService manager, string area, s
7777
}
7878

7979
value = manager.Localize(areaAndKey[0], areaAndKey[1]);
80-
return value.StartsWith("[") ? text : value;
80+
return value.StartsWith('[') ? text : value;
8181
}
8282

8383
/// <summary>

tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/TreeEntityExtensionsTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
using Moq;
1+
using Moq;
22
using NUnit.Framework;
33
using Umbraco.Cms.Core.Extensions;
44
using Umbraco.Cms.Core.Models.Entities;
5-
using Range = System.Range;
65

76
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions;
87

tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,12 @@ private static void TryIsFullPath(string path, bool expectedIsFull, bool expecte
387387
Assert.AreNotEqual(path, Path.GetFullPath(path));
388388
}
389389
}
390+
391+
[TestCase("1,2,3,4,5", "5,4,3,2,1")]
392+
[TestCase("1,2,x,4,5", "5,4,2,1")]
393+
public void GetIdsFromPathReversed(string input, string expected)
394+
{
395+
var ids = input.GetIdsFromPathReversed();
396+
Assert.AreEqual(expected, string.Join(",", ids));
397+
}
390398
}

0 commit comments

Comments
 (0)