Skip to content

Commit d7d0054

Browse files
Merge pull request #575 from lukecotter/perf-monomorphic-logevent
perf: monomorphic logevent
2 parents f13480c + 288457a commit d7d0054

21 files changed

Lines changed: 3052 additions & 2900 deletions

log-viewer/modules/Database.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
/*
22
* Copyright (c) 2020 Certinia Inc. All rights reserved.
33
*/
4-
import { ApexLog, DMLBeginLine, Method, SOQLExecuteBeginLine } from './parsers/ApexLogParser.js';
4+
import {
5+
type ApexLog,
6+
DMLBeginLine,
7+
type LogEvent,
8+
SOQLExecuteBeginLine,
9+
} from './parsers/LogEvents.js';
510

6-
export type Stack = Method[];
11+
export type Stack = LogEvent[];
712

813
export class DatabaseAccess {
914
private static _instance: DatabaseAccess | null = null;
@@ -23,13 +28,13 @@ export class DatabaseAccess {
2328
public getStack(
2429
timestamp: number,
2530
stack: Stack = [],
26-
line: Method = DatabaseAccess._treeRoot,
31+
line: LogEvent = DatabaseAccess._treeRoot,
2732
): Stack {
2833
const children = line.children;
2934
const len = children.length;
3035
for (let i = 0; i < len; ++i) {
3136
const child = children[i];
32-
if (child instanceof Method) {
37+
if (child?.isParent) {
3338
stack.push(child);
3439
if (child.timestamp === timestamp) {
3540
return stack;
@@ -45,7 +50,7 @@ export class DatabaseAccess {
4550
return [];
4651
}
4752

48-
public getSOQLLines(line: Method = DatabaseAccess._treeRoot): SOQLExecuteBeginLine[] {
53+
public getSOQLLines(line: LogEvent = DatabaseAccess._treeRoot): SOQLExecuteBeginLine[] {
4954
const results: SOQLExecuteBeginLine[] = [];
5055

5156
const children = line.children;
@@ -56,15 +61,15 @@ export class DatabaseAccess {
5661
results.push(child);
5762
}
5863

59-
if (child instanceof Method) {
64+
if (child?.isParent) {
6065
Array.prototype.push.apply(results, this.getSOQLLines(child));
6166
}
6267
}
6368

6469
return results;
6570
}
6671

67-
public getDMLLines(line: Method = DatabaseAccess._treeRoot): DMLBeginLine[] {
72+
public getDMLLines(line: LogEvent = DatabaseAccess._treeRoot): DMLBeginLine[] {
6873
const results: DMLBeginLine[] = [];
6974

7075
const children = line.children;
@@ -75,7 +80,7 @@ export class DatabaseAccess {
7580
results.push(child);
7681
}
7782

78-
if (child instanceof Method) {
83+
if (child?.isParent) {
7984
// results = results.concat(this.getDMLLines(child));
8085
Array.prototype.push.apply(results, this.getDMLLines(child));
8186
}

log-viewer/modules/__tests__/ApexLogParser.test.ts

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@
22
* Copyright (c) 2020 Certinia Inc. All rights reserved.
33
*/
44
import {
5-
ApexLogParser,
65
CodeUnitStartedLine,
76
ExecutionStartedLine,
8-
LogLine,
9-
Method,
7+
LogEvent,
108
MethodEntryLine,
119
SOQLExecuteBeginLine,
1210
SOQLExecuteExplainLine,
13-
TimedNode,
14-
lineTypeMap,
15-
parse,
1611
parseObjectNamespace,
1712
parseRows,
1813
parseVfNamespace,
19-
} from '../parsers/ApexLogParser.js';
14+
} from '../parsers/LogEvents.js';
15+
import { lineTypeMap } from '../parsers/LogLineMapping.js';
16+
17+
import { ApexLogParser, parse } from '../parsers/ApexLogParser.js';
18+
19+
class DummyLine extends LogEvent {
20+
constructor(parser: ApexLogParser, parts: string[]) {
21+
super(parser, parts);
22+
}
23+
}
2024

2125
describe('parseObjectNamespace tests', () => {
2226
it('Should consider no separator to be unmanaged', () => {
@@ -79,30 +83,30 @@ describe('Pseudo EXIT events', () => {
7983
expect(log1.children.length).toEqual(4);
8084
expect(log1.duration).toEqual({ self: 0, total: 3 });
8185

82-
const approval1 = log1.children[0] as Method;
86+
const approval1 = log1.children[0];
8387
expect(approval1).toMatchObject({
8488
type: 'WF_APPROVAL_SUBMIT',
8589
timestamp: 1,
8690
duration: { self: 1, total: 1 },
8791
});
8892

89-
const processFound1 = log1.children[1] as Method;
93+
const processFound1 = log1.children[1];
9094
expect(processFound1).toMatchObject({
9195
parent: log1,
9296
type: 'WF_PROCESS_FOUND',
9397
timestamp: 2,
9498
duration: { self: 1, total: 1 },
9599
});
96100

97-
const approval2 = log1.children[2] as Method;
101+
const approval2 = log1.children[2];
98102
expect(approval2).toMatchObject({
99103
parent: log1,
100104
type: 'WF_APPROVAL_SUBMIT',
101105
timestamp: 3,
102106
duration: { self: 1, total: 1 },
103107
});
104108

105-
const processFound2 = log1.children[3] as Method;
109+
const processFound2 = log1.children[3];
106110
expect(processFound2).toMatchObject({
107111
parent: log1,
108112
type: 'WF_PROCESS_FOUND',
@@ -125,22 +129,22 @@ describe('Pseudo EXIT events', () => {
125129
expect(log1.children.length).toEqual(1);
126130
expect(log1.duration).toEqual({ self: 0, total: 6 });
127131

128-
const children = (log1.children[0] as Method).children;
132+
const children = log1.children[0]?.children ?? [];
129133
expect(children.length).toEqual(4);
130134

131-
const child1 = children[0] as Method;
135+
const child1 = children[0]!;
132136
expect(child1.timestamp).toEqual(2);
133137
expect(child1.exitStamp).toEqual(3);
134138

135-
const child2 = children[1] as Method;
139+
const child2 = children[1]!;
136140
expect(child2.timestamp).toEqual(3);
137141
expect(child2.exitStamp).toEqual(4);
138142

139-
const child3 = children[2] as Method;
143+
const child3 = children[2]!;
140144
expect(child3.timestamp).toEqual(4);
141145
expect(child3.exitStamp).toEqual(5);
142146

143-
const child4 = children[3] as Method;
147+
const child4 = children[3]!;
144148
expect(child4.timestamp).toEqual(5);
145149
expect(child4.exitStamp).toEqual(6);
146150
});
@@ -157,18 +161,18 @@ describe('Pseudo EXIT events', () => {
157161
expect(log1.children.length).toEqual(1);
158162
expect(log1.duration).toEqual({ self: 0, total: 4 });
159163

160-
const children = (log1.children[0] as Method).children;
164+
const children = log1.children[0]?.children ?? [];
161165
expect(children.length).toEqual(3);
162166

163-
const child1 = children[0] as Method;
167+
const child1 = children[0]!;
164168
expect(child1.timestamp).toEqual(2);
165169
expect(child1.exitStamp).toEqual(3);
166170

167-
const child2 = children[1] as Method;
171+
const child2 = children[1]!;
168172
expect(child2.timestamp).toEqual(3);
169173
expect(child2.exitStamp).toEqual(4);
170174

171-
const child3 = children[2] as Method;
175+
const child3 = children[2]!;
172176
expect(child3.timestamp).toEqual(4);
173177
expect(child3.exitStamp).toEqual(5);
174178
});
@@ -204,7 +208,7 @@ describe('parseLog tests', () => {
204208
expect(logLines.length).toEqual(1);
205209
expect(logLines[0]).toBeInstanceOf(ExecutionStartedLine);
206210

207-
const firstChildren = (logLines[0] as Method).children;
211+
const firstChildren = logLines[0]?.children ?? [];
208212
expect(firstChildren.length).toEqual(1);
209213
expect(firstChildren[0]).toBeInstanceOf(CodeUnitStartedLine);
210214
});
@@ -222,7 +226,7 @@ describe('parseLog tests', () => {
222226
expect(apexLog.children.length).toEqual(1);
223227
expect(apexLog.children[0]).toBeInstanceOf(ExecutionStartedLine);
224228

225-
const firstChildren = (apexLog.children[0] as Method).children;
229+
const firstChildren = apexLog.children[0]?.children ?? [];
226230
expect(firstChildren.length).toEqual(1);
227231
expect(firstChildren[0]).toBeInstanceOf(CodeUnitStartedLine);
228232
});
@@ -237,7 +241,7 @@ describe('parseLog tests', () => {
237241
expect(apexLog.children.length).toBe(1);
238242
expect(apexLog.children[0]).toBeInstanceOf(ExecutionStartedLine);
239243

240-
const firstChildren = (apexLog.children[0] as Method).children;
244+
const firstChildren = apexLog.children[0]?.children ?? [];
241245
expect(firstChildren[0]).toBeInstanceOf(CodeUnitStartedLine);
242246
});
243247

@@ -403,7 +407,7 @@ describe('parseLog tests', () => {
403407

404408
const apexLog = parse(log);
405409

406-
const methods = apexLog.children as Method[];
410+
const methods = apexLog.children;
407411
expect(methods.length).toBe(24);
408412
methods.forEach((line) => {
409413
expect(line.exitTypes.length).toBe(0);
@@ -420,7 +424,7 @@ describe('parseLog tests', () => {
420424
'09:19:13.82 (51595120059)|EXECUTION_FINISHED\n';
421425

422426
const apexLog = parse(log);
423-
const execEvent = apexLog.children[0] as MethodEntryLine;
427+
const execEvent = <MethodEntryLine>apexLog.children[0];
424428
expect(execEvent).toBeInstanceOf(ExecutionStartedLine);
425429

426430
expect(execEvent.children.length).toEqual(1);
@@ -433,7 +437,7 @@ describe('parseLog tests', () => {
433437
soqlCount: { self: 1, total: 1 },
434438
});
435439

436-
const soqlExplain = soqlLine.children[0] as SOQLExecuteExplainLine;
440+
const soqlExplain = soqlLine.children[0];
437441
expect(soqlExplain).toMatchObject({
438442
parent: soqlLine,
439443
type: 'SOQL_EXECUTE_EXPLAIN',
@@ -461,7 +465,7 @@ describe('getRootMethod tests', () => {
461465

462466
const apexLog = parse(log);
463467

464-
const timedLogLines = apexLog.children as TimedNode[];
468+
const timedLogLines = apexLog.children;
465469
expect(timedLogLines.length).toBe(1);
466470
const startLine = timedLogLines[0];
467471
expect(startLine?.type).toBe('EXECUTION_STARTED');
@@ -475,7 +479,7 @@ describe('getRootMethod tests', () => {
475479
});
476480

477481
expect(unitStart.children.length).toBe(1);
478-
const interViewsBegin = unitStart.children[0] as TimedNode;
482+
const interViewsBegin = unitStart.children[0]!;
479483
expect(interViewsBegin).toMatchObject({
480484
parent: unitStart,
481485
type: 'FLOW_START_INTERVIEWS_BEGIN',
@@ -505,7 +509,7 @@ describe('getRootMethod tests', () => {
505509

506510
const apexLog = parse(log);
507511

508-
const timedLogLines = apexLog.children as TimedNode[];
512+
const timedLogLines = apexLog.children;
509513
expect(timedLogLines.length).toBe(1);
510514
const startLine = timedLogLines[0];
511515
expect(startLine?.type).toBe('EXECUTION_STARTED');
@@ -516,7 +520,7 @@ describe('getRootMethod tests', () => {
516520
expect(unitStart.codeUnitType).toBe('Flow');
517521

518522
expect(unitStart.children.length).toBe(1);
519-
const interViewsBegin = unitStart.children[0] as TimedNode;
523+
const interViewsBegin = unitStart.children[0]!;
520524
expect(interViewsBegin.type).toBe('FLOW_START_INTERVIEWS_BEGIN');
521525
expect(interViewsBegin.text).toBe('FLOW_START_INTERVIEWS : Example Flow');
522526
expect(interViewsBegin.suffix).toBe(' (Flow)');
@@ -544,7 +548,7 @@ describe('getRootMethod tests', () => {
544548

545549
const apexLog = parse(log);
546550

547-
const timedLogLines = apexLog.children as TimedNode[];
551+
const timedLogLines = apexLog.children;
548552
expect(timedLogLines.length).toBe(1);
549553
const startLine = timedLogLines[0];
550554
expect(startLine?.type).toBe('EXECUTION_STARTED');
@@ -555,17 +559,17 @@ describe('getRootMethod tests', () => {
555559
expect(unitStart.codeUnitType).toBe('Workflow');
556560

557561
expect(unitStart.children.length).toBe(1);
558-
const pbBegin = unitStart.children[0] as TimedNode;
562+
const pbBegin = unitStart.children[0]!;
559563
expect(pbBegin.type).toBe('FLOW_START_INTERVIEWS_BEGIN');
560564
expect(pbBegin.text).toBe('FLOW_START_INTERVIEWS : Example Process Builder');
561565
expect(pbBegin.suffix).toBe(' (Process Builder)');
562566

563567
expect(pbBegin.children.length).toBe(1);
564-
const pbDetail = pbBegin.children[0] as TimedNode;
568+
const pbDetail = pbBegin.children[0]!;
565569
expect(pbDetail.type).toBe('FLOW_START_INTERVIEW_BEGIN');
566570
expect(pbDetail.text).toBe('Example Process Builder');
567571

568-
const interViewsBegin = pbDetail.children[0] as TimedNode;
572+
const interViewsBegin = pbDetail.children[0]!;
569573
expect(interViewsBegin.type).toBe('FLOW_START_INTERVIEWS_BEGIN');
570574
expect(interViewsBegin.text).toBe('FLOW_START_INTERVIEWS : Example Flow');
571575
expect(interViewsBegin.suffix).toBe(' (Flow)');
@@ -640,9 +644,9 @@ describe('getRootMethod tests', () => {
640644
expect(apexLog.exitStamp).toBe(1100);
641645
expect(apexLog.executionEndTime).toBe(1100);
642646

643-
const rootChildren = apexLog.children as Method[];
647+
const rootChildren = apexLog.children;
644648
const executionStarted = rootChildren[0];
645-
const executionChildren = executionStarted?.children as Method[];
649+
const executionChildren = executionStarted?.children ?? [];
646650
expect(executionChildren.length).toBe(5);
647651

648652
expect(executionChildren[0]).toMatchObject({
@@ -1115,7 +1119,8 @@ describe('namespace tests', () => {
11151119
describe('Recalculate durations tests', () => {
11161120
it('Recalculates parent node', () => {
11171121
const parser = new ApexLogParser();
1118-
const node = new Method(parser, ['14:32:07.563 (1)', 'DUMMY'], [], 'Method', '');
1122+
const node = new DummyLine(parser, ['14:32:07.563 (1)', 'DUMMY']);
1123+
node.subCategory = 'Method';
11191124
node.exitStamp = 3;
11201125

11211126
node.recalculateDurations();
@@ -1249,20 +1254,17 @@ describe('Governor Limits Parsing', () => {
12491254
describe('Line Type Tests', () => {
12501255
it('Lines referenced by exitTypes should be exits', () => {
12511256
const parser = new ApexLogParser();
1252-
for (const [key, lineType] of lineTypeMap) {
1257+
for (const lineType of Object.values(lineTypeMap)) {
12531258
const line = new lineType(parser, [
12541259
'14:32:07.563 (17358806534)',
12551260
'DUMMY',
12561261
'[10]',
12571262
'Rows:3',
12581263
'',
12591264
'Rows:5',
1260-
]) as LogLine;
1261-
if (line instanceof Method) {
1262-
expect(line.exitTypes).not.toBe(null);
1263-
if (line.isExit) {
1264-
expect(line.exitTypes).toEqual([key]);
1265-
}
1265+
]) as LogEvent;
1266+
1267+
if (line.isParent) {
12661268
line.exitTypes.forEach((exitType) => {
12671269
const exitCls = lineTypeMap.get(exitType);
12681270
expect(exitCls).not.toBe(null);
@@ -1274,7 +1276,7 @@ describe('Line Type Tests', () => {
12741276
'Rows:3',
12751277
'',
12761278
'Rows:5',
1277-
]) as LogLine;
1279+
]) as LogEvent;
12781280
expect(exitLine.isExit).toBe(true);
12791281
}
12801282
});

0 commit comments

Comments
 (0)