-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Cache semantic classifications and display from the cache while a solution is loading. #46955
Conversation
src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource.cs
Show resolved
Hide resolved
@@ -51,23 +51,8 @@ private VisualStudioRemoteHostClientProvider(HostWorkspaceServices services) | |||
_lazyClient = new AsyncLazy<RemoteHostClient>(CreateHostClientAsync, cacheResult: true); | |||
} | |||
|
|||
private async Task<RemoteHostClient> CreateHostClientAsync(CancellationToken cancellationToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not part of this PR. i'm branched off of Tomas's change so i can use VS without OOP crashing. Once #46929 goes in, this will be gone.
if (_uniqueItems.Add(item)) | ||
_nextBatch.Add(item); | ||
_nextBatchMap.Remove(item); | ||
_nextBatchMap.Add(item, _nextIndex++); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
safe to do ++ here as we're under the lock.
@@ -29,6 +29,7 @@ private class Tagger : ForegroundThreadAffinitizedObject, IAccurateTagger<IClass | |||
private readonly SemanticClassificationBufferTaggerProvider _owner; | |||
private readonly ITextBuffer _subjectBuffer; | |||
private readonly ITaggerEventSource _eventSource; | |||
private readonly SemanticClassifier _classifier; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed from static helpers to an instance type now that it contains more interesting logic around caching/shutdown.
@@ -20,9 +28,54 @@ | |||
|
|||
namespace Microsoft.CodeAnalysis.Editor.Implementation.Classification | |||
{ | |||
internal static class SemanticClassificationUtilities | |||
internal partial class SemanticClassifier |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i purposefully didn't rename the file as it causes github to lose the diff. this makes it easier to understand hte change. i will rename in followup pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point there's more code that's new than existed... 😄
{ | ||
// We're reading and interpreting arbitrary data from disk. This may be invalid for any reason. | ||
Logger.Log(FunctionId.SemanticClassifier_ExceptionInCacheRead); | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
general pattern we use elsewhere when reading from cache.
var seenIds = new HashSet<DocumentId>(); | ||
foreach (var document in documentsToClassify) | ||
Contract.ThrowIfFalse(seenIds.Add(document.Id)); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug check to ensure that we are only processing a document once per batch.
src/Workspaces/Core/Portable/Storage/AbstractPersistentStorageService.cs
Outdated
Show resolved
Hide resolved
src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorageService.cs
Outdated
Show resolved
Hide resolved
src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs
Outdated
Show resolved
Hide resolved
src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs
Outdated
Show resolved
Hide resolved
src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_DocumentIds.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a bug where the cache that's maintained in the OOP process only is using the DocumentKey as the cache key, but the contents being cached is implicitly depending on the textSpan being queried. Blocking only for that bug; the rest of this was both solid and also well-structured so it was nice and easy to read.
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Show resolved
Hide resolved
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Show resolved
Hide resolved
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Show resolved
Hide resolved
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Outdated
Show resolved
Hide resolved
// Then place the cached information for this doc at the end. | ||
_cachedData.AddLast((documentKey.Id, checksum, classifiedSpans)); | ||
|
||
// And ensure we don't cache too many docs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So once we do get everything loaded, is the intent that this cache then falls away, or is continued to be used for opening new documents even once we have full semantics?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So once we do get everything loaded, is the intent that this cache then falls away,
The caches falls away. This happens in two ways:
- teh calls to CacheSemanticClassifications will clear it explicitly (since we are fully loaded at that point)
- the classifier doesn't call into the cache once we are fully loaded.
if (textSpan.IntersectsWith(classifiedSpan)) | ||
tempResult.Add(new ClassifiedSpan(classification, classifiedSpan)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were the spans originally written in order? Can we abandon the loop once we're past the end of textSpan?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point!
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs
Outdated
Show resolved
Hide resolved
src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good other than the JTF.Run() that I think you need to put back.
src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.cs
Outdated
Show resolved
Hide resolved
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Outdated
Show resolved
Hide resolved
...s/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
Show resolved
Hide resolved
…lysisService_SemanticClassificationCache.cs Co-authored-by: Jason Malinowski <jason@jason-m.com>
Hello @CyrusNajmabadi! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto-approval
return workspaceLoadedService.WaitUntilFullyLoadedAsync(CancellationToken.None); | ||
}); | ||
var workspaceLoadedService = w.Services.GetRequiredService<IWorkspaceStatusService>(); | ||
await workspaceLoadedService.WaitUntilFullyLoadedAsync(CancellationToken.None).ConfigureAwait(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this need to be async? Task.Run() should have worked fine if the lambda is just directly returning the Task.
Apologies, while this PR appears ready to be merged, I've been configured to only merge when all checks have explicitly passed. The following integrations have not reported any progress on their checks and are blocking auto-merge:
These integrations are possibly never going to report a check, and unblocking auto-merge likely requires a human being to update my configuration to exempt these integrations from requiring a passing check. Give feedback on thisFrom the bot dev teamWe've tried to tune the bot such that it posts a comment like this only when auto-merge is blocked for exceptional, non-intuitive reasons. When the bot's auto-merge capability is properly configured, auto-merge should operate as you would intuitively expect and you should not see any spurious comments. Please reach out to us at fabricbotservices@microsoft.com to provide feedback if you believe you're seeing this comment appear spuriously. Please note that we usually are unable to update your bot configuration on your team's behalf, but we're happy to help you identify your bot admin. |
Draft idea around making VS feel less encumbered during initial solution load. Part of hte caching working group experiments.
Note, this has a substantial impact on perceived classification perf on load. With Roslyn.sln itself, i go from anywhere from 30s to +1minute, down to just a couple of seconds before you have semantic classifications.
Tagging @mikadumont. This also ties into our discussions with platform about having some sort of good affordance in VS to let users know that this is initial solution-load and that values may be cached/stale, but will be available soon.