Skip to content

Commit

Permalink
Improve performance via Triemap in workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
pderaaij committed Oct 11, 2024
1 parent d7c92f8 commit e85abeb
Show file tree
Hide file tree
Showing 4 changed files with 1,094 additions and 1,276 deletions.
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/foam-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@
"lodash": "^4.17.21",
"lru-cache": "^7.14.1",
"markdown-it-regex": "^0.2.0",
"mnemonist": "^0.39.8",
"path-browserify": "^1.0.1",
"remark-frontmatter": "^2.0.0",
"remark-parse": "^8.0.2",
Expand Down
64 changes: 50 additions & 14 deletions packages/foam-vscode/src/core/model/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Emitter } from '../common/event';
import { ResourceProvider } from './provider';
import { IDisposable } from '../common/lifecycle';
import { IDataStore } from '../services/datastore';
import TrieMap from 'mnemonist/trie-map';

export class FoamWorkspace implements IDisposable {
private onDidAddEmitter = new Emitter<Resource>();
Expand All @@ -20,7 +21,7 @@ export class FoamWorkspace implements IDisposable {
/**
* Resources by path
*/
private _resources: Map<string, Resource> = new Map();
private _resources: TrieMap<string, Resource> = new TrieMap();

/**
* @param defaultExtension: The default extension for notes in this workspace (e.g. `.md`)
Expand All @@ -33,16 +34,19 @@ export class FoamWorkspace implements IDisposable {

set(resource: Resource) {
const old = this.find(resource.uri);
this._resources.set(normalize(resource.uri.path), resource);

// store resource
this._resources.set(this.getTrieIdentifier(resource.uri.path), resource);

isSome(old)
? this.onDidUpdateEmitter.fire({ old: old, new: resource })
: this.onDidAddEmitter.fire(resource);
return this;
}

delete(uri: URI) {
const deleted = this._resources.get(normalize(uri.path));
this._resources.delete(normalize(uri.path));
const deleted = this._resources.get(this.getTrieIdentifier(uri));
this._resources.delete(this.getTrieIdentifier(uri));

isSome(deleted) && this.onDidDeleteEmitter.fire(deleted);
return deleted ?? null;
Expand All @@ -57,7 +61,11 @@ export class FoamWorkspace implements IDisposable {
}

public resources(): IterableIterator<Resource> {
return this._resources.values();
const resources: Array<Resource> = Array.from(
this._resources.values()
).sort(Resource.sortByPath);

return resources.values();
}

public get(uri: URI): Resource {
Expand All @@ -70,17 +78,22 @@ export class FoamWorkspace implements IDisposable {
}

public listByIdentifier(identifier: string): Resource[] {
const needle = normalize('/' + identifier);
let needle = this.getTrieIdentifier(identifier);

const mdNeedle =
getExtension(needle) !== this.defaultExtension
? needle + this.defaultExtension
getExtension(normalize(identifier)) !== this.defaultExtension
? this.getTrieIdentifier(identifier + this.defaultExtension)
: undefined;

const resources: Resource[] = [];
for (const key of this._resources.keys()) {
if (key.endsWith(mdNeedle) || key.endsWith(needle)) {
resources.push(this._resources.get(normalize(key)));
}

this._resources.find(needle).forEach(elm => {
resources.push(elm[1]);
});
if (mdNeedle) {
this._resources.find(mdNeedle).forEach(elm => resources.push(elm[1]));
}

return resources.sort(Resource.sortByPath);
}

Expand Down Expand Up @@ -119,9 +132,32 @@ export class FoamWorkspace implements IDisposable {
return identifier;
}

/**
* Returns a note identifier in reversed order. Used to optimise the storage of notes in
* the workspace to optimise retrieval of notes.
*
* @param reference the URI path to reverse
*/
private getTrieIdentifier(reference: URI | string): string {
let path: string;
if (reference instanceof URI) {
path = (reference as URI).path;
} else {
path = reference as string;
}

let reversedPath = normalize(path).split('/').reverse().join('/');

if (reversedPath.indexOf('/') < 0) {
reversedPath = reversedPath + '/';
}

return reversedPath;
}

public find(reference: URI | string, baseUri?: URI): Resource | null {
if (reference instanceof URI) {
return this._resources.get(normalize((reference as URI).path)) ?? null;
return this._resources.get(this.getTrieIdentifier(reference)) ?? null;
}
let resource: Resource | null = null;
const [path, fragment] = (reference as string).split('#');
Expand All @@ -135,7 +171,7 @@ export class FoamWorkspace implements IDisposable {
: isSome(baseUri)
? baseUri.resolve(candidate).path
: null;
resource = this._resources.get(normalize(searchKey));
resource = this._resources.get(this.getTrieIdentifier(searchKey));
if (resource) {
break;
}
Expand Down
Loading

0 comments on commit e85abeb

Please sign in to comment.