Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LazyMetadataWrapper not super performant #195

Open
znakeeye opened this issue Feb 1, 2021 · 2 comments
Open

LazyMetadataWrapper not super performant #195

znakeeye opened this issue Feb 1, 2021 · 2 comments

Comments

@znakeeye
Copy link

znakeeye commented Feb 1, 2021

When querying attribute data - multiple times - for lazy imports, I see that a significant amount of time is spent In LazyMetadataWrapper.

image

Why the need to copy the arrays like that? What would be your recommendation here? Should the consumer cache the metadata?

@AArnott
Copy link
Member

AArnott commented Feb 2, 2021

It's been a long time since I looked at this code, but it looks like TypeRef.Get already has something like instance caching:

public static TypeRef? Get(Type? type, Resolver resolver)

Have you confirmed that in fact the cost here is paid multiple times for the same type?

I don't see us copying arrays as much as filtering and transforming them:

this.GenericTypeArguments = arrayElementType.GenericTypeArguments != null && arrayElementType.GenericTypeArguments.Length > 0
? arrayElementType.GenericTypeArguments.Where(t => !(shallow && t.IsGenericParameter)).Select(t => new TypeRef(resolver, t, shallow: true)).ToImmutableArray()
: ImmutableArray<TypeRef>.Empty;

But as this includes a few linq extension methods in a row, I suspect this could be optimized.

@znakeeye
Copy link
Author

znakeeye commented Feb 2, 2021

The performance problem is seen only when loading the MEF graph from a serialized file.

Also, I was performing a lookup multiple times. Hence, I was reading the ISomeMetadata metadata from a number of imported Lazy<IThing, ISomeMetadata>. Something like this:

lazyImports.Where(t => t.Metadata.MyTypeProperty == inputType);

Putting the SomeMetadataProperty value in a dictionary improves the performance, but you'd have to agree that this is a bit cumbersome:

// The metadata interface...
public interface ISomeMetadata
{
    Type MyTypeProperty { get; }
    Type OtherProperty { get; }
}

// And later I cache it:
private Dictionary<ISomeMetadata, Type> metadataCache;

More details

For 179 imported Lazy<IThing, ISomeMetadata> I got the following numbers when profiling:

  • Time spent in SubstituteValueIfRequired: 4005 ms
  • Number of calls: 6265
  • Number of MoveNext() enumerator calls: 216 912

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants