Skip to content

Commit 76ca47a

Browse files
committed
feat: Cache parsed SQL when building sequence diagram
1 parent 13ca5f1 commit 76ca47a

File tree

5 files changed

+46
-22
lines changed

5 files changed

+46
-22
lines changed

packages/models/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"eslint-plugin-import": "^2.22.1",
3939
"jest": "^27.4.7",
4040
"lint-staged": "^10.5.4",
41+
"lru-cache": "6.0.0",
4142
"prettier": "^2.7.1",
4243
"ts-jest": "^27.1.4",
4344
"tsup": "^6.5.0",

packages/models/src/event.js

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable */
12
import { addHiddenProperty, hasProp, transformToJSON } from './util';
23
import analyzeSQL, { abstractSqlAstJSON } from './sql/analyze';
34
import normalizeSQL from './sql/normalize';
@@ -362,14 +363,14 @@ export default class Event {
362363

363364
get identityHash() {
364365
if (!this.$hidden.identityHash) {
365-
this.$hidden.identityHash = this.buildIdentityHash(this).digest();
366+
this.$hidden.identityHash = this.buildIdentityHash().digest();
366367
}
367368
return this.$hidden.identityHash;
368369
}
369370

370371
get hash() {
371372
if (!this.$hidden.hash) {
372-
this.$hidden.hash = this.buildStableHash(this).digest();
373+
this.$hidden.hash = this.buildStableHash().digest();
373374
}
374375
return this.$hidden.hash;
375376
}
@@ -381,6 +382,13 @@ export default class Event {
381382
return this.$hidden.stableProperties;
382383
}
383384

385+
getHashWithSqlCache(parsedSqlCache) {
386+
if (!this.$hidden.hash) {
387+
this.$hidden.hash = this.buildStableHash(parsedSqlCache).digest();
388+
}
389+
return this.$hidden.hash;
390+
}
391+
384392
callStack() {
385393
const stack = this.ancestors().reverse();
386394
stack.push(this.callEvent);
@@ -501,7 +509,7 @@ export default class Event {
501509

502510
// Collects properties of an event which are not dependent on the specifics
503511
// of invocation.
504-
gatherStableProperties() {
512+
gatherStableProperties(parsedSqlCache) {
505513
const { sqlQuery } = this;
506514

507515
// Convert null and undefined values to empty strings
@@ -526,10 +534,17 @@ export default class Event {
526534

527535
let properties;
528536
if (sqlQuery) {
529-
const sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
530-
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
531-
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
532-
.join(`{"type":"variable"}`);
537+
let sqlNormalized;
538+
const cacheKey = `${this.sql.database_type}:${sqlQuery}`;
539+
if (parsedSqlCache) sqlNormalized = parsedSqlCache.get(cacheKey);
540+
if (!sqlNormalized) {
541+
sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
542+
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
543+
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
544+
.join(`{"type":"variable"}`);
545+
parsedSqlCache.set(cacheKey, sqlNormalized);
546+
}
547+
533548
properties = {
534549
event_type: 'sql',
535550
sql_normalized: sqlNormalized,
@@ -554,7 +569,10 @@ export default class Event {
554569
return HashBuilder.buildHash('event-identity-v2', this.gatherIdentityProperties());
555570
}
556571

557-
buildStableHash() {
558-
return HashBuilder.buildHash('event-stable-properties-v2', this.gatherStableProperties());
572+
buildStableHash(parsedSqlCache) {
573+
return HashBuilder.buildHash(
574+
'event-stable-properties-v2',
575+
this.gatherStableProperties(parsedSqlCache)
576+
);
559577
}
560578
}

packages/models/types/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { SqliteParser } from './sqlite-parser';
2+
import type { LRUCache } from 'lru-cache';
23

34
declare module '@appland/models' {
45
export type CodeObjectType =
@@ -214,6 +215,7 @@ declare module '@appland/models' {
214215
dataObjects(): Array<ParameterObject | ReturnValueObject>;
215216
toString(): string;
216217
toJSON(): any;
218+
getHashWithSqlCache(parsedSqlCache: LRUCache<string, any>): string;
217219
}
218220

219221
export class EventNavigator {

packages/sequence-diagram/src/buildDiagram.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AppMap, Event } from '@appland/models';
22
import { classNameToOpenAPIType } from '@appland/openapi';
33
import sha256 from 'crypto-js/sha256.js';
4+
import LRUCache from 'lru-cache';
45
import { merge } from './mergeWindow';
56
import { selectEvents } from './selectEvents';
67
import Specification from './specification';
@@ -19,6 +20,7 @@ import {
1920
} from './types';
2021

2122
const MAX_WINDOW_SIZE = 5;
23+
const parsedSqlCache = new LRUCache<string, any>({ max: 1000 });
2224

2325
class ActorManager {
2426
private _actorsByCodeObjectId = new Map<string, Actor>();
@@ -68,7 +70,7 @@ export default function buildDiagram(
6870
callee: actorManager.findOrCreateActor(callee),
6971
route: callee.route,
7072
status: response.status || response.status_code,
71-
digest: callee.hash,
73+
digest: callee.getHashWithSqlCache(parsedSqlCache),
7274
subtreeDigest: 'undefined',
7375
children: [],
7476
elapsed: callee.elapsedTime,
@@ -83,7 +85,7 @@ export default function buildDiagram(
8385
callee: actorManager.findOrCreateActor(callee),
8486
route: callee.route,
8587
status: response.status || response.status_code,
86-
digest: callee.hash,
88+
digest: callee.getHashWithSqlCache(parsedSqlCache),
8789
subtreeDigest: 'undefined',
8890
children: [],
8991
elapsed: callee.elapsedTime,
@@ -96,7 +98,7 @@ export default function buildDiagram(
9698
caller: caller ? actorManager.findOrCreateActor(caller) : undefined,
9799
callee: actorManager.findOrCreateActor(callee),
98100
query: callee.sqlQuery,
99-
digest: truncatedQuery ? 'truncatedQuery' : callee.hash,
101+
digest: truncatedQuery ? 'truncatedQuery' : callee.getHashWithSqlCache(parsedSqlCache),
100102
subtreeDigest: 'undefined',
101103
children: [],
102104
elapsed: callee.elapsedTime,
@@ -109,7 +111,7 @@ export default function buildDiagram(
109111
callee: actorManager.findOrCreateActor(callee),
110112
name: callee.codeObject.name,
111113
static: callee.codeObject.static,
112-
digest: callee.hash,
114+
digest: callee.getHashWithSqlCache(parsedSqlCache),
113115
subtreeDigest: 'undefined',
114116
stableProperties: { ...callee.stableProperties },
115117
returnValue: buildReturnValue(callee),

yarn.lock

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ __metadata:
380380
eslint-plugin-import: ^2.22.1
381381
jest: ^27.4.7
382382
lint-staged: ^10.5.4
383+
lru-cache: 6.0.0
383384
prettier: ^2.7.1
384385
ts-jest: ^27.1.4
385386
tsup: ^6.5.0
@@ -24788,6 +24789,15 @@ __metadata:
2478824789
languageName: node
2478924790
linkType: hard
2479024791

24792+
"lru-cache@npm:6.0.0, lru-cache@npm:^6.0.0":
24793+
version: 6.0.0
24794+
resolution: "lru-cache@npm:6.0.0"
24795+
dependencies:
24796+
yallist: ^4.0.0
24797+
checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297
24798+
languageName: node
24799+
linkType: hard
24800+
2479124801
"lru-cache@npm:^4.0.1, lru-cache@npm:^4.1.2, lru-cache@npm:^4.1.5":
2479224802
version: 4.1.5
2479324803
resolution: "lru-cache@npm:4.1.5"
@@ -24807,15 +24817,6 @@ __metadata:
2480724817
languageName: node
2480824818
linkType: hard
2480924819

24810-
"lru-cache@npm:^6.0.0":
24811-
version: 6.0.0
24812-
resolution: "lru-cache@npm:6.0.0"
24813-
dependencies:
24814-
yallist: ^4.0.0
24815-
checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297
24816-
languageName: node
24817-
linkType: hard
24818-
2481924820
"lru-cache@npm:^7.14.1":
2482024821
version: 7.18.3
2482124822
resolution: "lru-cache@npm:7.18.3"

0 commit comments

Comments
 (0)