Skip to content

Commit 644e759

Browse files
jpobstjonpryor
authored andcommitted
[generator] Cache finding descendants of a GenBase (#441)
Finding the descendants of a `GenBase` is relatively expensive. Caching the results causes the `GenBase.UpdateEnums()` method to drop from ~9.5s to ~1s when generating `Mono.Android.dll`.
1 parent 35b0ce8 commit 644e759

File tree

5 files changed

+64
-15
lines changed

5 files changed

+64
-15
lines changed

tools/generator/CodeGenerationOptions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ internal CodeGenerator CreateCodeGenerator (TextWriter writer)
6868
public bool IgnoreNonPublicType { get; set; }
6969
public string AssemblyName { get; set; }
7070
public bool UseShortFileNames { get; set; }
71-
public IList<GenBase> Gens {get;set;}
7271
public int ProductVersion { get; set; }
7372
public bool SupportInterfaceConstants { get; set; }
7473

tools/generator/CodeGenerator.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Java.Interop.Tools.Cecil;
1212
using Java.Interop.Tools.Diagnostics;
1313
using Java.Interop.Tools.TypeNameMappings;
14+
using MonoDroid.Generation.Utilities;
1415

1516
namespace Xamarin.Android.Binder
1617
{
@@ -130,7 +131,6 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
130131
return;
131132
}
132133
apiSource = p.ApiSource;
133-
opt.Gens = gens;
134134

135135
// disable interface default methods here, especially before validation.
136136
gens = gens.Where (g => !g.IsObfuscated && g.Visibility != "private").ToList ();
@@ -148,8 +148,10 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
148148
foreach (GenBase gen in gens)
149149
gen.FillProperties ();
150150

151+
var cache = new AncestorDescendantCache (gens);
152+
151153
foreach (var gen in gens)
152-
gen.UpdateEnums (opt);
154+
gen.UpdateEnums (opt, cache);
153155

154156
foreach (GenBase gen in gens)
155157
gen.FixupMethodOverrides (opt);

tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Collections;
1111
using System.Security.Policy;
1212
using System.Text;
13+
using MonoDroid.Generation.Utilities;
1314

1415
namespace MonoDroid.Generation {
1516

@@ -798,24 +799,24 @@ GenBase GetBaseGen (CodeGenerationOptions opt)
798799

799800
bool enum_updated;
800801

801-
public virtual void UpdateEnums (CodeGenerationOptions opt)
802+
public virtual void UpdateEnums (CodeGenerationOptions opt, AncestorDescendantCache cache)
802803
{
803804
if (enum_updated || !IsGeneratable)
804805
return;
805806
enum_updated = true;
806807
var baseGen = GetBaseGen (opt);
807808
if (baseGen != null)
808-
baseGen.UpdateEnums (opt);
809+
baseGen.UpdateEnums (opt, cache);
809810

810811
foreach (Method m in methods) {
811-
AutoDetectEnumifiedOverrideParameters (m, opt);
812-
AutoDetectEnumifiedOverrideReturn (m, opt);
812+
AutoDetectEnumifiedOverrideParameters (m, cache);
813+
AutoDetectEnumifiedOverrideReturn (m, cache);
813814
}
814815
foreach (Property p in Properties)
815-
AutoDetectEnumifiedOverrideProperties (p, opt);
816+
AutoDetectEnumifiedOverrideProperties (p, cache);
816817
UpdateEnumsInInterfaceImplementation ();
817818
foreach (var ngen in NestedTypes)
818-
ngen.UpdateEnums (opt);
819+
ngen.UpdateEnums (opt, cache);
819820
}
820821

821822
public virtual void UpdateEnumsInInterfaceImplementation ()
@@ -951,11 +952,11 @@ static IEnumerable<Method> GetAllMethods (GenBase t)
951952
return t.Methods.Concat (t.Properties.Select (p => p.Getter)).Concat (t.Properties.Select (p => p.Setter).Where (m => m != null));
952953
}
953954

954-
static string [] AutoDetectEnumifiedOverrideParameters (MethodBase method, CodeGenerationOptions opt)
955+
static string [] AutoDetectEnumifiedOverrideParameters (MethodBase method, AncestorDescendantCache cache)
955956
{
956957
if (method.Parameters.All (p => p.Type != "int"))
957958
return null;
958-
var classes = method.DeclaringType.Ancestors ().Concat (method.DeclaringType.Descendants (opt.Gens));
959+
var classes = cache.GetAncestorsAndDescendants (method.DeclaringType);
959960
classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ()));
960961
foreach (var t in classes) {
961962
foreach (var candidate in GetAllMethods (t).Where (m => m.Name == method.Name
@@ -982,11 +983,11 @@ static string [] AutoDetectEnumifiedOverrideParameters (MethodBase method, CodeG
982983
return null;
983984
}
984985

985-
static string AutoDetectEnumifiedOverrideReturn (Method method, CodeGenerationOptions opt)
986+
static string AutoDetectEnumifiedOverrideReturn (Method method, AncestorDescendantCache cache)
986987
{
987988
if (method.RetVal.FullName != "int")
988989
return null;
989-
var classes = method.DeclaringType.Ancestors ().Concat (method.DeclaringType.Descendants (opt.Gens));
990+
var classes = cache.GetAncestorsAndDescendants (method.DeclaringType);
990991
classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ()));
991992
foreach (var t in classes) {
992993
foreach (var candidate in GetAllMethods (t).Where (m => m.Name == method.Name && m.Parameters.Count == method.Parameters.Count)) {
@@ -999,11 +1000,11 @@ static string AutoDetectEnumifiedOverrideReturn (Method method, CodeGenerationOp
9991000
return null;
10001001
}
10011002

1002-
void AutoDetectEnumifiedOverrideProperties (Property prop, CodeGenerationOptions opt)
1003+
void AutoDetectEnumifiedOverrideProperties (Property prop, AncestorDescendantCache cache)
10031004
{
10041005
if (prop.Type != "int")
10051006
return;
1006-
var classes = prop.Getter.DeclaringType.Ancestors ().Concat (prop.Getter.DeclaringType.Descendants (opt.Gens));
1007+
var classes = cache.GetAncestorsAndDescendants (prop.Getter.DeclaringType);
10071008
classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ()));
10081009
foreach (var t in classes) {
10091010
foreach (var candidate in t.Properties.Where (p => p.Name == prop.Name)) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace MonoDroid.Generation.Utilities
6+
{
7+
// Finding all descendants of a type is expensive, so we cache the results here
8+
public class AncestorDescendantCache
9+
{
10+
readonly List<GenBase> gens;
11+
readonly Dictionary<GenBase, IEnumerable<GenBase>> cache = new Dictionary<GenBase, IEnumerable<GenBase>> ();
12+
13+
public AncestorDescendantCache (List<GenBase> gens)
14+
{
15+
this.gens = gens;
16+
}
17+
18+
public IEnumerable<GenBase> GetAncestorsAndDescendants (GenBase gen)
19+
{
20+
if (cache.TryGetValue (gen, out var value))
21+
return value;
22+
23+
var new_value = GetAncestors (gen).Concat (GetDescendants (gen)).ToList ();
24+
25+
cache [gen] = new_value;
26+
27+
return new_value;
28+
}
29+
30+
IEnumerable<GenBase> GetAncestors (GenBase gen)
31+
{
32+
for (var g = gen.BaseGen; g != null; g = g.BaseGen)
33+
yield return g;
34+
}
35+
36+
IEnumerable<GenBase> GetDescendants (GenBase gen)
37+
{
38+
foreach (var directDescendants in gens.Where (x => x.BaseGen == gen)) {
39+
yield return directDescendants;
40+
41+
foreach (var indirectDescendants in GetDescendants (directDescendants))
42+
yield return indirectDescendants;
43+
}
44+
}
45+
}
46+
}

tools/generator/generator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\Parameter.cs" />
106106
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\ParameterList.cs" />
107107
<Compile Include="Java.Interop.Tools.Generator.Transformation\Parser.cs" />
108+
<Compile Include="Utilities\AncestorDescendantCache.cs" />
108109
<Compile Include="Utilities\ProcessRocks.cs" />
109110
<Compile Include="Properties\AssemblyInfo.cs" />
110111
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\Property.cs" />

0 commit comments

Comments
 (0)