Skip to content

Commit

Permalink
UI: Fix performance of getting subject models (#3666)
Browse files Browse the repository at this point in the history
  • Loading branch information
grigasp committed May 24, 2022
1 parent f17953a commit 6924185
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/appui-react",
"comment": "Models Tree: Fix performance of determining Subject nodes' display state.",
"type": "none"
}
],
"packageName": "@itwin/appui-react"
}
Original file line number Diff line number Diff line change
Expand Up @@ -419,43 +419,58 @@ class SubjectModelIdsCache {
this._imodel = imodel;
}

private async initSubjectsHierarchy() {
this._subjectsHierarchy = new Map();
const ecsql = `SELECT ECInstanceId id, Parent.Id parentId FROM bis.Subject WHERE Parent IS NOT NULL`;
const result = this._imodel.query(ecsql, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames });
for await (const row of result) {
let list = this._subjectsHierarchy.get(row.parentId);
private async initSubjectModels() {
const querySubjects = (): AsyncIterableIterator<{ id: Id64String, parentId?: Id64String, targetPartitionId?: Id64String }> => {
const subjectsQuery = `
SELECT ECInstanceId id, Parent.Id parentId, json_extract(JsonProperties, '$.Subject.Model.TargetPartition') targetPartitionId
FROM bis.Subject
`;
return this._imodel.query(subjectsQuery, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames });
};
const queryModels = (): AsyncIterableIterator<{ id: Id64String, parentId: Id64String, content?: string }> => {
const modelsQuery = `
SELECT p.ECInstanceId id, p.Parent.Id parentId, json_extract(p.JsonProperties, '$.PhysicalPartition.Model.Content') content
FROM bis.InformationPartitionElement p
INNER JOIN bis.GeometricModel3d m ON m.ModeledElement.Id = p.ECInstanceId
WHERE NOT m.IsPrivate
`;
return this._imodel.query(modelsQuery, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames });
};

function pushToMap<TKey, TValue>(map: Map<TKey, TValue[]>, key: TKey, value: TValue) {
let list = map.get(key);
if (!list) {
list = [];
this._subjectsHierarchy.set(row.parentId, list);
map.set(key, list);
}
list.push(row.id);
list.push(value);
}

this._subjectsHierarchy = new Map();
const targetPartitionSubjects = new Map<Id64String, Id64String[]>();
for await (const subject of querySubjects()) {
if (subject.parentId)
pushToMap(this._subjectsHierarchy, subject.parentId, subject.id);
if (subject.targetPartitionId)
pushToMap(targetPartitionSubjects, subject.targetPartitionId, subject.id);
}
}

private async initSubjectModels() {
this._subjectModels = new Map();
const ecsql = `
SELECT p.ECInstanceId id, s.ECInstanceId subjectId, json_extract(p.JsonProperties, '$.PhysicalPartition.Model.Content') content
FROM bis.InformationPartitionElement p
INNER JOIN bis.GeometricModel3d m ON m.ModeledElement.Id = p.ECInstanceId
INNER JOIN bis.Subject s ON (s.ECInstanceId = p.Parent.Id OR json_extract(s.JsonProperties, '$.Subject.Model.TargetPartition') = printf('0x%x', p.ECInstanceId))
WHERE NOT m.IsPrivate`;
const result = this._imodel.query(ecsql, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames });
for await (const row of result) {
let list = this._subjectModels.get(row.subjectId);
if (!list) {
list = [];
this._subjectModels.set(row.subjectId, list);
}
const isHidden = row.content !== undefined;
list.push({ id: row.id, isHidden });
for await (const model of queryModels()) {
const subjectIds = targetPartitionSubjects.get(model.id) ?? [];
if (!subjectIds.includes(model.parentId))
subjectIds.push(model.parentId);

const v = { id: model.id, isHidden: (model.content !== undefined) };
subjectIds.forEach((subjectId) => {
pushToMap(this._subjectModels!, subjectId, v);
});
}
}

private async initCache() {
if (!this._init) {
this._init = Promise.all([this.initSubjectModels(), this.initSubjectsHierarchy()]).then(() => { });
this._init = this.initSubjectModels().then(() => { });
}
return this._init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ describe("ModelsVisibilityHandler", () => {
});
props.imodelMock.setup((x) => x.query(moq.It.is((q: string) => (-1 !== q.indexOf("FROM bis.InformationPartitionElement"))), undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }))
.returns(async function* () {
const list = new Array<{ id: Id64String, subjectId: Id64String, content?: string }>();
props.subjectModels.forEach((modelInfos, subjectId) => modelInfos.forEach((modelInfo) => list.push({ id: modelInfo.id, subjectId, content: modelInfo.content })));
const list = new Array<{ id: Id64String, parentId: Id64String, content?: string }>();
props.subjectModels.forEach((modelInfos, subjectId) => modelInfos.forEach((modelInfo) => list.push({ id: modelInfo.id, parentId: subjectId, content: modelInfo.content })));
while (list.length)
yield list.shift();
});
Expand Down

0 comments on commit 6924185

Please sign in to comment.