Skip to content

Commit

Permalink
cache casing information for faster lookup, #93368
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Jun 9, 2020
1 parent 1b46cb1 commit e956533
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
40 changes: 30 additions & 10 deletions src/vs/workbench/services/uriIdentity/common/uriIdentityService.ts
Expand Up @@ -6,9 +6,11 @@
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
import { URI } from 'vs/base/common/uri';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
import { IFileService, FileSystemProviderCapabilities, IFileSystemProviderCapabilitiesChangeEvent, IFileSystemProviderRegistrationEvent } from 'vs/platform/files/common/files';
import { ExtUri, IExtUri, normalizePath } from 'vs/base/common/resources';
import { SkipList } from 'vs/base/common/skipList';
import { Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';

class Entry {
static _clock = 0;
Expand All @@ -26,27 +28,45 @@ export class UriIdentityService implements IUriIdentityService {

readonly extUri: IExtUri;

private readonly _dispooables = new DisposableStore();
private readonly _canonicalUris: SkipList<URI, Entry>;
private readonly _limit = 2 ** 16;

constructor(@IFileService private readonly _fileService: IFileService) {

// assume path casing matters unless the file system provider spec'ed the opposite
const schemeIgnoresPathCasingCache = new Map<string, boolean>();

// assume path casing matters unless the file system provider spec'ed the opposite.
// for all other cases path casing matters, e.g for
// * virtual documents
// * in-memory uris
// * all kind of "private" schemes
const ignorePathCasing = (uri: URI): boolean => {
// perf@jrieken cache this information
if (this._fileService.canHandleResource(uri)) {
return !this._fileService.hasCapability(uri, FileSystemProviderCapabilities.PathCaseSensitive);
let ignorePathCasing = schemeIgnoresPathCasingCache.get(uri.scheme);
if (ignorePathCasing === undefined) {
// retrieve once and then case per scheme until a change happens
ignorePathCasing = _fileService.canHandleResource(uri) && !this._fileService.hasCapability(uri, FileSystemProviderCapabilities.PathCaseSensitive);
schemeIgnoresPathCasingCache.set(uri.scheme, ignorePathCasing);
}
// this defaults to false which is a good default for
// * virtual documents
// * in-memory uris
// * all kind of "private" schemes
return false;
return ignorePathCasing;
};
this._dispooables.add(Event.any<IFileSystemProviderCapabilitiesChangeEvent | IFileSystemProviderRegistrationEvent>(
_fileService.onDidChangeFileSystemProviderRegistrations,
_fileService.onDidChangeFileSystemProviderCapabilities
)(e => {
// remove from cache
schemeIgnoresPathCasingCache.delete(e.scheme);
}));

this.extUri = new ExtUri(ignorePathCasing);
this._canonicalUris = new SkipList((a, b) => this.extUri.compare(a, b, true), this._limit);
}

dispose(): void {
this._dispooables.dispose();
this._canonicalUris.clear();
}

asCanonicalUri(uri: URI): URI {

// (1) normalize URI
Expand Down
Expand Up @@ -8,11 +8,15 @@ import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uri
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';

suite('URI Identity', function () {

class FakeFileService extends mock<IFileService>() {

onDidChangeFileSystemProviderCapabilities = Event.None;
onDidChangeFileSystemProviderRegistrations = Event.None;

constructor(readonly data: Map<string, FileSystemProviderCapabilities>) {
super();
}
Expand Down

0 comments on commit e956533

Please sign in to comment.