提交 00e9a2f3 编写于 作者: C CyrusNajmabadi

Stash around completed tasks to prevent task allocations.

上级 8705f523
......@@ -303,7 +303,8 @@ private int BinarySearch(string name)
// of immutable state (like a Solution) that we don't want kept around indefinitely. So we
// only cache results (the symbol tree infos) if they successfully compute to completion.
private static readonly ConditionalWeakTable<MetadataId, SemaphoreSlim> s_metadataIdToGate = new ConditionalWeakTable<MetadataId, SemaphoreSlim>();
private static readonly ConditionalWeakTable<MetadataId, SymbolTreeInfo> s_metadataIdToInfo = new ConditionalWeakTable<MetadataId, SymbolTreeInfo>();
private static readonly ConditionalWeakTable<MetadataId, Task<SymbolTreeInfo>> s_metadataIdToInfo =
new ConditionalWeakTable<MetadataId, Task<SymbolTreeInfo>>();
private static readonly ConditionalWeakTable<MetadataId, SemaphoreSlim>.CreateValueCallback s_metadataIdToGateCallback =
_ => new SemaphoreSlim(1);
......
......@@ -87,10 +87,10 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
// allocations around acquiring the task for it. Note: once ValueTask is available
// (and enabled in the language), we'd likely want to use it here. (Presuming
// the lock is not being held most of the time).
SymbolTreeInfo info;
if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info))
Task<SymbolTreeInfo> infoTask;
if (s_metadataIdToInfo.TryGetValue(metadata.Id, out infoTask))
{
return Task.FromResult(info);
return infoTask;
}
return TryGetInfoForMetadataReferenceSlowAsync(
......@@ -108,20 +108,25 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
{
cancellationToken.ThrowIfCancellationRequested();
SymbolTreeInfo info;
if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info))
Task<SymbolTreeInfo> infoTask;
if (s_metadataIdToInfo.TryGetValue(metadata.Id, out infoTask))
{
return info;
return await infoTask.ConfigureAwait(false);
}
info = await LoadOrCreateMetadataSymbolTreeInfoAsync(
var info = await LoadOrCreateMetadataSymbolTreeInfoAsync(
solution, reference, loadOnly, cancellationToken: cancellationToken).ConfigureAwait(false);
if (info == null && loadOnly)
{
return null;
}
return s_metadataIdToInfo.GetValue(metadata.Id, _ => info);
// Cache the result in our dictionary. Store it as a completed task so that
// future callers don't need to allocate to get the result back.
infoTask = Task.FromResult(info);
s_metadataIdToInfo.Add(metadata.Id, infoTask);
return info;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册