Uh oh!
There was an error while loading. Please reload this page.
[ApiXmlAdjuster] Use different data model structures for better performance - #756
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| // It's debatable whether we handle this "properly", as most callers just | ||
| // do `First ()`, but it's been working for years so I'm not changing it. | ||
| // Exposes an IReadOnlyDictionary so caller cannot bypass our AddType/RemoveType code. | ||
| public IReadOnlyDictionary<string, List<JavaType>> Types { get; } |
There was a problem hiding this comment.
…alternatively, should this be Set<JavaType> instead of List<JavaType>? Does it make sense to allow for the same instance to be added multiple times?
There was a problem hiding this comment.
The same "compatibility"/"diff minimization" question/concern applies to Types vs. AllTypes: I suspect that if Types became an IEnumerable<JavaType> property and AllTypes were the "Dictionary-like" property, fewer changes would be required.
Uh oh!
There was an error while loading. Please reload this page.
jpobst
commented
Dec 9, 2020
IMO, the changed I added |
| public partial class JavaPackage | ||
| { | ||
| private Dictionary<string, List<JavaType>> types = new Dictionary<string, List<JavaType>> (StringComparer.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Java type names are not filesystem-bound constructs; they are case sensitive, and it is entirely valid to have a package example and package Example in the same app. (It'll cause pain & suffering on case-insensitive filesystems! But Java allows it.)
I think this should use StringComparer.Ordinal.
| if (reader.LocalName == "class") { | ||
| var kls = new JavaClass (package) { IsReferenceOnly = isReferenceOnly }; | ||
| kls.Load (reader); | ||
| package.Types.Add (kls); |
There was a problem hiding this comment.
…back on the "smaller diffs!" front, if we did have a class JavaTypes : KeyedCollection<string, JavaType> class, this statement wouldn't need to change, nor the many other statements just like it…
There was a problem hiding this comment.
I tested out KeyedCollection, but it cannot handle duplicate keys:
System.ArgumentException: 'An item with the same key has already been added. Key: key1'
Today, our ApiXmlAdjuster process builds an in-memory model of every Java type we know about, and then queries this model many times in order to ensure we can resolve every needed Java type to build a binding. The data structure of this model is:
Then it is queried using LINQ like this:
In the random GPS package I used for testing,
JavaApicontained 310 packages and a total of 5941 types. Repeatedly looping through them looking for the correct type takes a considerable amount of time.Instead, we can use a
Dictionaryto store packages and types keyed by name to significantly speed up type resolution:For the GPS project, this reduced time taken considerably:
The only "interesting" detail is that we can have multiple types with the same Java name, such as
MyInterfaceandMyInterfaceConsts. Thus we need to useDictionary<string, List<JavaType>>to ensure we collect them all.For good measure I ran a XA build with this to ensure
Mono.AndroidApiCompatdidn't find any issues: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=4282925.