Skip to content

Commit b07901e

Browse files
authored
Improve the performance of the RtxtParser. (#9839)
* Improve the performance of the RtxtParser. There are some small improvements in the RtxtParser that can be done to improve the performance of the parser. This commit includes the following changes: 1. Update the `enum` to be `byte`. This saves us a few bytes per instance. 2. Reorder the fields to reduce padding. 3. Encode is a type is a stylable into the `RType` enum. 4. Pre-allocate the array so we reduce the number of allocations. The following table shows the improvements for 10000 items. We have to use a large number to see the improvements. Note that the default Maui template has about 7000 entries in the R.txt file. So this is not an unreasonable test size. | Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | |------------------- |---------:|---------:|---------:|----------:|----------:|---------:|----------:| | RtxtParserBaseLine | 53.40 ms | 0.315 ms | 0.246 ms | 7500.0000 | 3000.0000 | 300.0000 | 67.32 MB | | RtxtParser | 48.58 ms | 0.192 ms | 0.179 ms | 7454.5455 | 2454.5455 | 272.7273 | 60.44 MB |
1 parent fc68a2c commit b07901e

File tree

4 files changed

+20
-15
lines changed

4 files changed

+20
-15
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ bool Run (DirectoryAssemblyResolver res)
177177
foreach (var r in resources) {
178178
switch (r.Type) {
179179
case RType.Integer:
180+
case RType.Integer_Styleable:
180181
if (IsApplication)
181182
CreateIntField (cache, r.ResourceTypeName, r.Identifier, r.Id, constDesigner, module);
182183
CreateIntProperty (cache, r.ResourceTypeName, r.Identifier, r.Id, resourceDesigner, module);

src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public IList<R> Parse (string resourceDirectory, IEnumerable<string> additionalR
156156
foreach (R r in resources[t].OrderBy(x => x.ToSortedString(), StringComparer.Ordinal)) {
157157

158158
int id = Convert.ToInt32 (itemPackageId + typeid.ToString ("X2") + itemid.ToString ("X4"), fromBase: 16);
159-
if (r.Type == RType.Integer && r.Id == -1) {
159+
if ((r.Type != RType.Array) && r.Id == -1) {
160160
itemid++;
161161
r.UpdateId (id);
162162
} else {
@@ -352,6 +352,7 @@ resources [field.ResourceTypeName].Add (new R () {
352352
ResourceTypeName = field.ResourceTypeName,
353353
Identifier = $"{field.Identifier}_{r.Replace (":", "_")}",
354354
Id = id++,
355+
Type = RType.Integer_Styleable,
355356
});
356357
}
357358
}

src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs

+1
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ void ProcessRtxtFile (string file)
295295
var cl = CreateClass (r.ResourceTypeName);
296296
switch (r.Type) {
297297
case RType.Integer:
298+
case RType.Integer_Styleable:
298299
CreateIntField (cl, r.Identifier, r.Id);
299300
break;
300301
case RType.Array:

src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs

+16-14
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,35 @@
55
using System.Text.RegularExpressions;
66
using Microsoft.Android.Build.Tasks;
77
using Microsoft.Build.Utilities;
8+
using System.Runtime.InteropServices;
89

910
namespace Xamarin.Android.Tasks
1011
{
11-
public enum RType {
12+
public enum RType : byte {
1213
Integer,
14+
Integer_Styleable,
1315
Array,
1416
}
1517

16-
public enum ResourceType {
18+
public enum ResourceType : byte {
1719
System,
1820
Custom,
1921
}
2022

23+
[StructLayout(LayoutKind.Sequential)]
2124
public struct R : IComparable<R> {
22-
public RType Type;
2325
public int Id;
24-
public int [] Ids;
26+
public RType Type;
27+
public ResourceType ResourceType;
2528
public string Identifier;
2629
public string ResourceTypeName;
27-
public ResourceType ResourceType;
28-
30+
public int [] Ids;
2931
public string Key => $"{ResourceTypeName}:{Identifier}";
3032

3133
public override string ToString ()
3234
{
33-
if (Type == RType.Integer) {
34-
if (ResourceTypeName == "styleable")
35-
return $"int {ResourceTypeName} {Identifier} {Id}";
36-
return $"int {ResourceTypeName} {Identifier} 0x{Id.ToString ("x8")}";
35+
if (Type != RType.Array) {
36+
return $"int {ResourceTypeName} {Identifier} { (Type == RType.Integer ? $"0x{Id.ToString ("x8")}" : $"{Id}")}";
3737
}
3838
return $"int[] {ResourceTypeName} {Identifier} {{ {String.Join (", ", Ids.Select (x => $"0x{x.ToString ("x8")}"))} }}";
3939
}
@@ -60,7 +60,7 @@ public void UpdateIds (int [] newIds)
6060
}
6161

6262
public class RtxtParser {
63-
63+
static readonly int DefaultCapacity = 10000; // a Maui template project has 7000+ resource entires.
6464
static readonly char[] EmptyChar = new char [] { ' ' };
6565
static readonly char[] CurlyBracketsChar = new char [] { '{', '}' };
6666
static readonly char[] CommaChar = new char [] { ',' };
@@ -98,16 +98,16 @@ public IEnumerable<R> Parse (string file, TaskLoggingHelper logger, Dictionary<s
9898
{
9999
log = logger;
100100
map = mapping;
101-
var result = new List<R> ();
101+
var result = new List<R> (DefaultCapacity);
102102
if (File.Exists (file))
103103
ProcessRtxtFile (file, result);
104104
return result;
105105
}
106106

107-
void ProcessRtxtFile (string file, IList<R> result)
107+
void ProcessRtxtFile (string file, List<R> result)
108108
{
109109
int lineNumber = 0;
110-
foreach (var line in File.ReadLines (file)) {
110+
foreach (var line in File.ReadLines (file) ) {
111111
lineNumber++;
112112
var items = line.Split (EmptyChar, 4);
113113
if (items.Length < 4) {
@@ -124,6 +124,7 @@ void ProcessRtxtFile (string file, IList<R> result)
124124
if (items [1] != "styleable") {
125125
result.Add (new R () {
126126
ResourceTypeName = items [1],
127+
Type = RType.Integer,
127128
Identifier = itemName,
128129
Id = value,
129130
});
@@ -133,6 +134,7 @@ void ProcessRtxtFile (string file, IList<R> result)
133134
case "int":
134135
result.Add (new R () {
135136
ResourceTypeName = items [1],
137+
Type = RType.Integer_Styleable,
136138
Identifier = itemName,
137139
Id = Convert.ToInt32 (items [3].Trim (), 10),
138140
});

0 commit comments

Comments
 (0)