Skip to content

Commit e85abeb

Browse files
committed
Improve performance via Triemap in workspace
1 parent d7c92f8 commit e85abeb

File tree

4 files changed

+1094
-1276
lines changed

4 files changed

+1094
-1276
lines changed

package-lock.json

+15-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/foam-vscode/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@
720720
"lodash": "^4.17.21",
721721
"lru-cache": "^7.14.1",
722722
"markdown-it-regex": "^0.2.0",
723+
"mnemonist": "^0.39.8",
723724
"path-browserify": "^1.0.1",
724725
"remark-frontmatter": "^2.0.0",
725726
"remark-parse": "^8.0.2",

packages/foam-vscode/src/core/model/workspace.ts

+50-14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Emitter } from '../common/event';
66
import { ResourceProvider } from './provider';
77
import { IDisposable } from '../common/lifecycle';
88
import { IDataStore } from '../services/datastore';
9+
import TrieMap from 'mnemonist/trie-map';
910

1011
export class FoamWorkspace implements IDisposable {
1112
private onDidAddEmitter = new Emitter<Resource>();
@@ -20,7 +21,7 @@ export class FoamWorkspace implements IDisposable {
2021
/**
2122
* Resources by path
2223
*/
23-
private _resources: Map<string, Resource> = new Map();
24+
private _resources: TrieMap<string, Resource> = new TrieMap();
2425

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

3435
set(resource: Resource) {
3536
const old = this.find(resource.uri);
36-
this._resources.set(normalize(resource.uri.path), resource);
37+
38+
// store resource
39+
this._resources.set(this.getTrieIdentifier(resource.uri.path), resource);
40+
3741
isSome(old)
3842
? this.onDidUpdateEmitter.fire({ old: old, new: resource })
3943
: this.onDidAddEmitter.fire(resource);
4044
return this;
4145
}
4246

4347
delete(uri: URI) {
44-
const deleted = this._resources.get(normalize(uri.path));
45-
this._resources.delete(normalize(uri.path));
48+
const deleted = this._resources.get(this.getTrieIdentifier(uri));
49+
this._resources.delete(this.getTrieIdentifier(uri));
4650

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

5963
public resources(): IterableIterator<Resource> {
60-
return this._resources.values();
64+
const resources: Array<Resource> = Array.from(
65+
this._resources.values()
66+
).sort(Resource.sortByPath);
67+
68+
return resources.values();
6169
}
6270

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

7280
public listByIdentifier(identifier: string): Resource[] {
73-
const needle = normalize('/' + identifier);
81+
let needle = this.getTrieIdentifier(identifier);
82+
7483
const mdNeedle =
75-
getExtension(needle) !== this.defaultExtension
76-
? needle + this.defaultExtension
84+
getExtension(normalize(identifier)) !== this.defaultExtension
85+
? this.getTrieIdentifier(identifier + this.defaultExtension)
7786
: undefined;
87+
7888
const resources: Resource[] = [];
79-
for (const key of this._resources.keys()) {
80-
if (key.endsWith(mdNeedle) || key.endsWith(needle)) {
81-
resources.push(this._resources.get(normalize(key)));
82-
}
89+
90+
this._resources.find(needle).forEach(elm => {
91+
resources.push(elm[1]);
92+
});
93+
if (mdNeedle) {
94+
this._resources.find(mdNeedle).forEach(elm => resources.push(elm[1]));
8395
}
96+
8497
return resources.sort(Resource.sortByPath);
8598
}
8699

@@ -119,9 +132,32 @@ export class FoamWorkspace implements IDisposable {
119132
return identifier;
120133
}
121134

135+
/**
136+
* Returns a note identifier in reversed order. Used to optimise the storage of notes in
137+
* the workspace to optimise retrieval of notes.
138+
*
139+
* @param reference the URI path to reverse
140+
*/
141+
private getTrieIdentifier(reference: URI | string): string {
142+
let path: string;
143+
if (reference instanceof URI) {
144+
path = (reference as URI).path;
145+
} else {
146+
path = reference as string;
147+
}
148+
149+
let reversedPath = normalize(path).split('/').reverse().join('/');
150+
151+
if (reversedPath.indexOf('/') < 0) {
152+
reversedPath = reversedPath + '/';
153+
}
154+
155+
return reversedPath;
156+
}
157+
122158
public find(reference: URI | string, baseUri?: URI): Resource | null {
123159
if (reference instanceof URI) {
124-
return this._resources.get(normalize((reference as URI).path)) ?? null;
160+
return this._resources.get(this.getTrieIdentifier(reference)) ?? null;
125161
}
126162
let resource: Resource | null = null;
127163
const [path, fragment] = (reference as string).split('#');
@@ -135,7 +171,7 @@ export class FoamWorkspace implements IDisposable {
135171
: isSome(baseUri)
136172
? baseUri.resolve(candidate).path
137173
: null;
138-
resource = this._resources.get(normalize(searchKey));
174+
resource = this._resources.get(this.getTrieIdentifier(searchKey));
139175
if (resource) {
140176
break;
141177
}

0 commit comments

Comments
 (0)