Skip to content

Commit 1521608

Browse files
committed
fix: optimize WUDetails call (#4422)
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent d1b8764 commit 1521608

File tree

12 files changed

+516
-474
lines changed

12 files changed

+516
-474
lines changed

package-lock.json

Lines changed: 404 additions & 383 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"test-node-cjs": "cd tests/node-cjs && npm i && npm test",
2626
"test-type-leaks": "cd tests/type-leaks && npm i && npm test",
2727
"test": "lerna run test",
28+
"test-ci": "cross-env ci=1 lerna run test",
2829
"test-all": "vitest run",
2930
"publish": "lerna publish from-package --yes",
3031
"update-workspaces": "lerna run update --no-sort --stream",
@@ -39,6 +40,7 @@
3940
"@typescript-eslint/parser": "8.38.0",
4041
"@vitest/browser": "3.2.4",
4142
"@vitest/coverage-v8": "3.2.4",
43+
"cross-env": "7.0.3",
4244
"eslint": "9.31.0",
4345
"eslint-plugin-react-hooks": "5.2.0",
4446
"lerna": "8.2.3",

packages/comms/src/ecl/query.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,31 +172,44 @@ export class Query extends StateObject<QueryEx, QueryEx> implements QueryEx {
172172
const meta = promises[1];
173173
const metrics: WsWorkunits.Scope[] = promises[2];
174174
const data = metrics.map(metric => {
175-
if (metric.Id[0] === "a" || metric.Id[0] === "e") {
175+
const firstChar = metric.Id[0];
176+
if (firstChar === "a" || firstChar === "e") {
176177
const item = graph.idx[metric.Id.substring(1)];
178+
if (!item) {
179+
logger.debug(`Missing graph data for metric ID: ${metric.Id}`);
180+
return metric;
181+
}
182+
const existingProperties = new Set(metric.Properties.Property.map(prop => prop.Name));
183+
const newProperties: WsWorkunits.Property[] = [];
177184
for (const key in item) {
178-
if (key.charAt(0) !== "_" && key.charAt(0) === key.charAt(0).toUpperCase() && (typeof item[key] === "string" || typeof item[key] === "number" || typeof item[key] === "boolean")) {
179-
180-
if (!metric.Properties.Property.some(row => row.Name === key)) {
181-
const isNum = isNumber(item[key]);
182-
let rawValue = isNum ? parseFloat(item[key] as string) : item[key];
183-
let formatted = item[key];
185+
const firstCharOfKey = key.charAt(0);
186+
if (firstCharOfKey !== "_" &&
187+
firstCharOfKey === firstCharOfKey.toUpperCase() &&
188+
!existingProperties.has(key)) {
189+
const value = item[key];
190+
const valueType = typeof value;
191+
if (valueType === "string" || valueType === "number" || valueType === "boolean") {
192+
const isNum = isNumber(value);
193+
let rawValue = isNum ? parseFloat(value as string) : value;
194+
let formatted = value;
184195
if (key.indexOf("Time") >= 0) {
185-
rawValue = rawValue as number / 1000000000;
196+
rawValue = (rawValue as number) / 1000000000;
186197
formatted = siFormatter(rawValue) + "s";
187198
}
188-
metric.Properties.Property.push({
199+
newProperties.push({
189200
Name: key,
190201
RawValue: rawValue as any,
191202
Formatted: formatted
192203
} as WsWorkunits.Property);
193204
}
194205
}
195206
}
207+
if (newProperties.length > 0) {
208+
metric.Properties.Property.push(...newProperties);
209+
}
196210
}
197211
return metric;
198212
});
199-
200213
return wu.normalizeDetails(meta, data);
201214
});
202215
}

packages/comms/src/ecl/workunit.ts

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -675,50 +675,60 @@ export class Workunit extends StateObject<UWorkunitState, IWorkunitState> implem
675675
Measure: "label"
676676
}
677677
};
678-
const data: IScope[] = [];
679-
for (const scope of scopes) {
680-
const props = {};
681-
const formattedProps = {};
682-
if (scope && scope.Id && scope.Properties && scope.Properties.Property) {
683-
for (const key in scope.Properties.Property) {
684-
const scopeProperty = scope.Properties.Property[key];
685-
if (scopeProperty.Measure === "ns") {
678+
const activityMap = new Map<number, string>();
679+
for (const activity of meta.Activities?.Activity ?? []) {
680+
activityMap.set(activity.Kind, activity.Name);
681+
}
682+
const data: IScope[] = new Array(scopes.length);
683+
for (let i = 0; i < scopes.length; i++) {
684+
const scope = scopes[i];
685+
const props: { [key: string]: any } = {};
686+
const formattedProps: { [key: string]: any } = {};
687+
if (scope.Id && scope.Properties?.Property) {
688+
for (const scopeProperty of scope.Properties.Property) {
689+
const measure = scopeProperty.Measure;
690+
const name = scopeProperty.Name;
691+
const rawValue = scopeProperty.RawValue;
692+
if (measure === "ns") {
686693
scopeProperty.Measure = "s";
687694
}
688-
if (scopeProperty.Name === "Kind") {
689-
const rawValue = parseInt(scopeProperty.RawValue, 10);
690-
scopeProperty.Formatted = meta.Activities.Activity.filter(a => a.Kind === rawValue)[0].Name ?? scopeProperty.RawValue;
695+
if (name === "Kind") {
696+
const rawValueInt = parseInt(rawValue, 10);
697+
scopeProperty.Formatted = activityMap.get(rawValueInt) ?? rawValue;
691698
}
692-
columns[scopeProperty.Name] = { ...scopeProperty };
693-
safeDelete(columns, scopeProperty.Name, "RawValue");
694-
safeDelete(columns, scopeProperty.Name, "Formatted");
699+
columns[name] = {
700+
Name: scopeProperty.Name,
701+
Measure: scopeProperty.Measure,
702+
Creator: scopeProperty.Creator,
703+
CreatorType: scopeProperty.CreatorType
704+
};
695705
switch (scopeProperty.Measure) {
696706
case "bool":
697-
props[scopeProperty.Name] = !!+scopeProperty.RawValue;
707+
props[name] = !!+rawValue;
698708
break;
699709
case "sz":
700-
props[scopeProperty.Name] = +scopeProperty.RawValue;
710+
props[name] = +rawValue;
701711
break;
702712
case "s":
703-
props[scopeProperty.Name] = +scopeProperty.RawValue / 1000000000;
713+
props[name] = +rawValue / 1000000000;
704714
break;
705715
case "ns":
706-
props[scopeProperty.Name] = +scopeProperty.RawValue;
716+
props[name] = +rawValue;
707717
break;
708718
case "ts":
709-
props[scopeProperty.Name] = new Date(+scopeProperty.RawValue / 1000).toISOString();
719+
props[name] = new Date(+rawValue / 1000).toISOString();
710720
break;
711721
case "cnt":
712-
props[scopeProperty.Name] = +scopeProperty.RawValue;
722+
props[name] = +rawValue;
713723
break;
714724
case "cost":
715-
props[scopeProperty.Name] = +scopeProperty.RawValue / 1000000;
725+
props[name] = +rawValue / 1000000;
716726
break;
717727
case "node":
718-
props[scopeProperty.Name] = +scopeProperty.RawValue;
728+
props[name] = +rawValue;
719729
break;
720730
case "skw":
721-
props[scopeProperty.Name] = +scopeProperty.RawValue;
731+
props[name] = +rawValue;
722732
break;
723733
case "cpu":
724734
case "ppm":
@@ -729,11 +739,10 @@ export class Workunit extends StateObject<UWorkunitState, IWorkunitState> implem
729739
case "id":
730740
case "fname":
731741
default:
732-
props[scopeProperty.Name] = scopeProperty.RawValue;
742+
props[name] = rawValue;
733743
}
734-
formattedProps[scopeProperty.Name] = formatNum(scopeProperty.Formatted ?? props[scopeProperty.Name]);
744+
formattedProps[name] = formatNum(scopeProperty.Formatted ?? props[name]);
735745
}
736-
// Other properties ---
737746
}
738747
const normalizedScope: IScope = {
739748
id: scope.Id,
@@ -748,37 +757,47 @@ export class Workunit extends StateObject<UWorkunitState, IWorkunitState> implem
748757
__StdDevsSource: "",
749758
...props
750759
};
751-
if (normalizedScope[DEFINITION_LIST]) {
760+
const definitionList = normalizedScope[DEFINITION_LIST];
761+
if (definitionList) {
752762
try {
753-
const definitionList = JSON.parse(normalizedScope[DEFINITION_LIST].split("\\").join("\\\\"));
754-
normalizedScope[DEFINITION_LIST] = [];
755-
definitionList.forEach((definition, idx) => {
756-
const matches = definition.match(definitionRegex);
763+
const parsedList = JSON.parse(definitionList.split("\\").join("\\\\"));
764+
const processedDefinitions: Array<{ filePath: string, line: number, col: number }> = [];
765+
766+
for (let k = 0; k < parsedList.length; k++) {
767+
const matches = parsedList[k].match(definitionRegex);
757768
if (matches) {
758-
const filePath = (matches[1] ?? "") + matches[2] + matches[3];
759-
const line = parseInt(matches[5]);
760-
const col = parseInt(matches[6]);
761-
normalizedScope[DEFINITION_LIST].push({ filePath, line, col });
769+
processedDefinitions.push({
770+
filePath: (matches[1] ?? "") + matches[2] + matches[3],
771+
line: parseInt(matches[5], 10),
772+
col: parseInt(matches[6], 10)
773+
});
762774
}
763-
});
775+
}
776+
normalizedScope[DEFINITION_LIST] = processedDefinitions;
764777
} catch (e) {
765-
logger.error(`Unexpected "DefinitionList": ${normalizedScope[DEFINITION_LIST]}`);
778+
logger.error(`Unexpected "DefinitionList": ${definitionList}`);
766779
}
767780
}
781+
768782
const dedup: DedupProperties = {};
783+
let maxStdDevs = 0;
784+
let maxStdDevsSource = "";
769785
for (const key in normalizedScope) {
770-
if (key.indexOf("__") !== 0) {
786+
if (!key.startsWith("__")) {
771787
const row = formatValues(normalizedScope, key, dedup);
772788
if (row) {
773789
normalizedScope.__groupedProps[row.Key] = row;
774-
if (!isNaN(row.StdDevs) && normalizedScope.__StdDevs < row.StdDevs) {
775-
normalizedScope.__StdDevs = row.StdDevs;
776-
normalizedScope.__StdDevsSource = row.Key;
790+
if (!isNaN(row.StdDevs) && row.StdDevs > maxStdDevs) {
791+
maxStdDevs = row.StdDevs;
792+
maxStdDevsSource = row.Key;
777793
}
778794
}
779795
}
780796
}
781-
data.push(normalizedScope);
797+
normalizedScope.__StdDevs = maxStdDevs;
798+
normalizedScope.__StdDevsSource = maxStdDevsSource;
799+
800+
data[i] = normalizedScope;
782801
}
783802
return {
784803
meta,

packages/dgrid/esbuild.js

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/esbuild-plugins/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"esbuild-copy-static-files": "0.1.0",
4343
"esbuild-plugin-inline-css": "0.0.1",
4444
"fzstd": "0.1.1",
45-
"vite": "7.0.5",
45+
"vite": "7.0.6",
4646
"vite-plugin-css-injected-by-js": "3.5.2",
4747
"vite-plugin-static-copy": "3.1.1"
4848
},

packages/esbuild-plugins/src/vite-utils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ export function createHpccViteConfig(pkg: any, options: ViteHpccConfigOptions =
114114
},
115115
...(configOverrides.build?.rollupOptions || {})
116116
},
117+
// Preserve class names and function names in minified output
118+
minify: "terser",
119+
terserOptions: {
120+
keep_classnames: true,
121+
mangle: {
122+
keep_classnames: true,
123+
}
124+
},
117125
sourcemap: true,
118126
...(configOverrides.build ? Object.fromEntries(Object.entries(configOverrides.build).filter(([key]) => key !== "lib" && key !== "rollupOptions")) : {})
119127
},
@@ -122,7 +130,7 @@ export function createHpccViteConfig(pkg: any, options: ViteHpccConfigOptions =
122130
...(configOverrides.resolve || {})
123131
},
124132
esbuild: {
125-
minifyIdentifiers: false,
133+
keepNames: true,
126134
...(configOverrides.esbuild || {})
127135
},
128136
plugins: allPlugins,

packages/observablehq-compiler/tests/simple.browser.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { fa } from "./File Attachments.ts";
55
import { imports } from "./Introduction to Imports.ts";
66
import { timechart } from "./Observable TimeChart.ts";
77

8-
const link = globalThis.document.createElement('link');
9-
link.rel = 'stylesheet';
10-
link.href = './__moduleRoot__/dist/index.css';
8+
const link = globalThis.document.createElement("link");
9+
link.rel = "stylesheet";
10+
link.href = "./__moduleRoot__/dist/index.css";
1111
document.head.appendChild(link);
1212

1313
const placeholder = globalThis.document.createElement("div");
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import { createHpccViteConfig } from "@hpcc-js/esbuild-plugins";
22
import pkg from "./package.json" with { type: "json" };
33

4-
export default createHpccViteConfig(pkg);
4+
export default createHpccViteConfig(pkg);
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { defineWorkspace } from "vitest/config";
2-
import baseWorkspace from "../../vitest.workspace.ts";
2+
import { browserConfig, nodeConfig } from "../../vitest.workspace.ts";
3+
4+
browserConfig.optimizeDeps = {
5+
include: ["acorn", "acorn-walk", "@observablehq/parser"]
6+
};
7+
8+
nodeConfig.optimizeDeps = {
9+
include: ["acorn", "acorn-walk", "@observablehq/parser"]
10+
};
311

412
export default defineWorkspace([
5-
...baseWorkspace
13+
browserConfig,
14+
nodeConfig
615
]);

0 commit comments

Comments
 (0)