Skip to content

Commit 9290417

Browse files
pengweiqhcaliuhaoyang
authored andcommitted
Use ReadOnlySpan<char> Improve performance after .netcoreapp2.1 (#192)
1 parent 7016ef2 commit 9290417

File tree

8 files changed

+112
-5
lines changed

8 files changed

+112
-5
lines changed

benchmark/SkyApm.Benchmark/SkyApm.Benchmark.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>netcoreapp2.1</TargetFramework>
5+
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1</TargetFrameworks>
66
</PropertyGroup>
77

88
<ItemGroup>

benchmark/SkyApm.Benchmark/UniqueId.cs renamed to benchmark/SkyApm.Benchmark/UniqueIdGenerate.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace SkyApm.Benchmark
55
{
6-
public class UniqueId
6+
public class UniqueIdGenerate
77
{
88
private static readonly IUniqueIdGenerator Generator = new UniqueIdGenerator(new RuntimeEnvironment());
99

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using BenchmarkDotNet.Attributes;
2+
using SkyApm.Tracing;
3+
4+
namespace SkyApm.Benchmark
5+
{
6+
public class UniqueIdParse
7+
{
8+
private static readonly IUniqueIdParser Parser = new UniqueIdParser();
9+
private static readonly string Id = new UniqueId(long.MaxValue, long.MaxValue, long.MaxValue).ToString();
10+
11+
[Benchmark]
12+
public void Parse() => Parser.TryParse(Id, out _);
13+
}
14+
}

skyapm-dotnet.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Agent.GeneralHost",
8686
EndProject
8787
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GeneralHost", "sample\SkyApm.Sample.GeneralHost\SkyApm.Sample.GeneralHost.csproj", "{477D705E-576B-46C8-8F1E-9A86EDAE9D86}"
8888
EndProject
89-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.Benchmark", "benchmark\SkyApm.Benchmark\SkyApm.Benchmark.csproj", "{33581FDE-ABAF-4C27-A40A-1A2743309399}"
89+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Benchmark", "benchmark\SkyApm.Benchmark\SkyApm.Benchmark.csproj", "{33581FDE-ABAF-4C27-A40A-1A2743309399}"
9090
EndProject
9191
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{2B7F59E8-147F-4399-9804-E7EAEF2DCB22}"
9292
EndProject
93+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.Core.Tests", "test\SkyApm.Core.Tests\SkyApm.Core.Tests.csproj", "{5E654407-E22F-4696-A33F-C4B372F547BD}"
94+
EndProject
9395
Global
9496
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9597
Debug|Any CPU = Debug|Any CPU
@@ -196,6 +198,10 @@ Global
196198
{33581FDE-ABAF-4C27-A40A-1A2743309399}.Debug|Any CPU.Build.0 = Debug|Any CPU
197199
{33581FDE-ABAF-4C27-A40A-1A2743309399}.Release|Any CPU.ActiveCfg = Release|Any CPU
198200
{33581FDE-ABAF-4C27-A40A-1A2743309399}.Release|Any CPU.Build.0 = Release|Any CPU
201+
{5E654407-E22F-4696-A33F-C4B372F547BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
202+
{5E654407-E22F-4696-A33F-C4B372F547BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
203+
{5E654407-E22F-4696-A33F-C4B372F547BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
204+
{5E654407-E22F-4696-A33F-C4B372F547BD}.Release|Any CPU.Build.0 = Release|Any CPU
199205
EndGlobalSection
200206
GlobalSection(SolutionProperties) = preSolution
201207
HideSolutionNode = FALSE
@@ -234,6 +240,7 @@ Global
234240
{4C1CF0E7-4CD3-4731-9A56-E033D5216D58} = {EF6194B2-9ACB-49B9-8049-DD6AFAEB0399}
235241
{477D705E-576B-46C8-8F1E-9A86EDAE9D86} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
236242
{33581FDE-ABAF-4C27-A40A-1A2743309399} = {2B7F59E8-147F-4399-9804-E7EAEF2DCB22}
243+
{5E654407-E22F-4696-A33F-C4B372F547BD} = {613F0980-91ED-4064-8E8C-168582EF4AD7}
237244
EndGlobalSection
238245
GlobalSection(ExtensibilityGlobals) = postSolution
239246
SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583}

src/SkyApm.Core/SkyApm.Core.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
<PackageReleaseNotes>
1010
</PackageReleaseNotes>
1111
<RootNamespace>SkyWalking</RootNamespace>
12-
<TargetFramework>netstandard2.0</TargetFramework>
12+
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
13+
<DefineConstants Condition="'$(TargetFramework)' == 'netcoreapp2.1'">$(DefineConstants);SPAN</DefineConstants>
1314
</PropertyGroup>
1415
<ItemGroup>
1516
<PackageReference Include="AspectCore.Extensions.Reflection" Version="1.2.0" />

src/SkyApm.Core/Tracing/UniqueIdParser.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,51 @@
1616
*
1717
*/
1818

19+
using System;
20+
1921
namespace SkyApm.Tracing
2022
{
2123
public class UniqueIdParser : IUniqueIdParser
2224
{
2325
public bool TryParse(string text, out UniqueId uniqueId)
2426
{
2527
uniqueId = default(UniqueId);
26-
if (text == null) return false;
28+
if (string.IsNullOrEmpty(text)) return false;
29+
#if SPAN
30+
var id = text.AsSpan();
31+
var index = FindIndex(id);
32+
33+
if (index < 1) return false;
34+
var id1 = id.Slice(0, index);
35+
36+
index = FindIndex(id.Slice(index + 1));
37+
if (index < 1) return false;
38+
39+
if (!long.TryParse(id1, out var part0)) return false;
40+
if (!long.TryParse(id.Slice(id1.Length + 1, index), out var part1)) return false;
41+
if (!long.TryParse(id.Slice(id1.Length + index + 2), out var part2)) return false;
42+
#else
2743
var parts = text.Split("\\.".ToCharArray(), 3);
2844
if (parts.Length < 3) return false;
2945
if (!long.TryParse(parts[0], out var part0)) return false;
3046
if (!long.TryParse(parts[1], out var part1)) return false;
3147
if (!long.TryParse(parts[2], out var part2)) return false;
48+
#endif
3249
uniqueId = new UniqueId(part0, part1, part2);
3350
return true;
3451
}
52+
#if SPAN
53+
private static int FindIndex(ReadOnlySpan<char> id)
54+
{
55+
var index = 0;
56+
do
57+
{
58+
if (id[index] == '\\' || id[index] == '.')
59+
return index;
60+
} while (++index < id.Length);
61+
62+
return -1;
63+
}
64+
#endif
3565
}
3666
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1</TargetFrameworks>
5+
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0" />
11+
<PackageReference Include="xunit" Version="2.4.0" />
12+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
13+
14+
<ProjectReference Include="..\..\src\SkyApm.Core\SkyApm.Core.csproj" />
15+
</ItemGroup>
16+
17+
</Project>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using SkyApm.Tracing;
2+
using System;
3+
using Xunit;
4+
5+
namespace SkyApm.Core.Tests
6+
{
7+
public class UniqueIdParserTest
8+
{
9+
private static readonly IUniqueIdParser Parser = new UniqueIdParser();
10+
11+
[Theory]
12+
[InlineData(null, false)]
13+
[InlineData("", false)]
14+
[InlineData("1", false)]
15+
[InlineData("1.1", false)]
16+
[InlineData("1.1.", false)]
17+
[InlineData("1.1.a", false)]
18+
[InlineData("1.1.1.1", false)]
19+
[InlineData("1\\1.-1", true)]
20+
public void TryParse_Return(string text, bool result) =>
21+
Assert.Equal(result, Parser.TryParse(text, out _));
22+
23+
[Theory]
24+
[InlineData("1.2.3", 1, 2, 3)]
25+
[InlineData("123.456.789", 123, 456, 789)]
26+
[InlineData("-1.-2.-3", -1, -2, -3)]
27+
[InlineData("9223372036854775807.9223372036854775807.9223372036854775807", 9223372036854775807, 9223372036854775807, 9223372036854775807)]
28+
[InlineData("-9223372036854775807.-9223372036854775807.-9223372036854775807", -9223372036854775807, -9223372036854775807, -9223372036854775807)]
29+
public void TryParse_Out(string text, long part1, long part2, long part3)
30+
{
31+
Parser.TryParse(text, out var id);
32+
33+
Assert.Equal(part1, id.Part1);
34+
Assert.Equal(part2, id.Part2);
35+
Assert.Equal(part3, id.Part3);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)