@bldrs-ai/conway 1.549.1515 → 1.553.1520
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiled/examples/browser-bundled.cjs +23 -2
- package/compiled/examples/cli-bundled.cjs +35 -3
- package/compiled/examples/cli-step-bundled.cjs +28 -4
- package/compiled/examples/validator-bundled.cjs +23 -2
- package/compiled/src/AP214E3_2010/ap214_command_line_main.js +4 -1
- package/compiled/src/AP214E3_2010/ap214_regression_main.js +47 -4
- package/compiled/src/core/wasm_heap.d.ts +5 -4
- package/compiled/src/core/wasm_heap.d.ts.map +1 -1
- package/compiled/src/core/wasm_heap.js +5 -4
- package/compiled/src/ifc/ifc_command_line_main.js +12 -0
- package/compiled/src/ifc/ifc_regression_main.js +97 -6
- package/compiled/src/loaders/conway_model_loader.d.ts.map +1 -1
- package/compiled/src/loaders/conway_model_loader.js +26 -0
- package/compiled/src/memory/memory.d.ts.map +1 -1
- package/compiled/src/memory/memory.js +25 -1
- package/compiled/src/memory/memory_stats.test.d.ts +2 -0
- package/compiled/src/memory/memory_stats.test.d.ts.map +1 -0
- package/compiled/src/memory/memory_stats.test.js +115 -0
- package/compiled/src/scripts/bless_perf_snapshot.test.js +44 -6
- package/compiled/src/scripts/perf_csv_quoting.test.js +113 -23
- package/compiled/src/statistics/statistics.d.ts +18 -0
- package/compiled/src/statistics/statistics.d.ts.map +1 -1
- package/compiled/src/statistics/statistics.js +22 -0
- package/compiled/src/statistics/statistics_wasm_heap.test.d.ts +2 -0
- package/compiled/src/statistics/statistics_wasm_heap.test.d.ts.map +1 -0
- package/compiled/src/statistics/statistics_wasm_heap.test.js +60 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
|
|
|
30
30
|
var readline = __toESM(require("node:readline"), 1);
|
|
31
31
|
|
|
32
32
|
// compiled/src/version/version.js
|
|
33
|
-
var versionString = "Conway v1.
|
|
33
|
+
var versionString = "Conway v1.553.1520";
|
|
34
34
|
|
|
35
35
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
36
36
|
var wasmType = "";
|
|
@@ -145,6 +145,27 @@ var Statistics = class {
|
|
|
145
145
|
setGeometryMemory(value) {
|
|
146
146
|
this.geometryMemory = value;
|
|
147
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Wasm linear-memory high-water mark in MB, from wasmHeapByteLength.
|
|
150
|
+
*
|
|
151
|
+
* @return {number | undefined} - wasm heap high-water, or undefined
|
|
152
|
+
*/
|
|
153
|
+
getWasmHeapPeak() {
|
|
154
|
+
return this.wasmHeapPeak;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The wasm heap only ever grows, so a single reading of it IS the peak —
|
|
158
|
+
* no sampling loop and no forced GC. It is a different quantity from
|
|
159
|
+
* geometryMemory, and by a wide margin: on MB-Khaya an 8 MB live geometry
|
|
160
|
+
* payload sits under an 85 MB wasm heap, the gap being allocator overhead,
|
|
161
|
+
* fragmentation and the intermediate buffers a boolean leaves behind (see
|
|
162
|
+
* src/ifc/geometry_residency.ts). Neither substitutes for the other.
|
|
163
|
+
*
|
|
164
|
+
* @param value - wasm heap high-water in MB
|
|
165
|
+
*/
|
|
166
|
+
setWasmHeapPeak(value) {
|
|
167
|
+
this.wasmHeapPeak = value;
|
|
168
|
+
}
|
|
148
169
|
/**
|
|
149
170
|
*
|
|
150
171
|
* @return {string | undefined} - preprocessor version or undefined
|
|
@@ -278,7 +299,7 @@ var Statistics = class {
|
|
|
278
299
|
const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
|
|
279
300
|
const breakdown = this.formatGeometryTypeCounts();
|
|
280
301
|
const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
|
|
281
|
-
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
302
|
+
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, WASM Heap High-Water: ${this.wasmHeapPeak?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
282
303
|
}
|
|
283
304
|
};
|
|
284
305
|
|
|
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
|
|
|
14965
14965
|
var import_process = require("process");
|
|
14966
14966
|
|
|
14967
14967
|
// compiled/src/version/version.js
|
|
14968
|
-
var versionString = "Conway v1.
|
|
14968
|
+
var versionString = "Conway v1.553.1520";
|
|
14969
14969
|
|
|
14970
14970
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
14971
14971
|
function pThreadsAllowed() {
|
|
@@ -15819,6 +15819,27 @@ var Statistics = class {
|
|
|
15819
15819
|
setGeometryMemory(value) {
|
|
15820
15820
|
this.geometryMemory = value;
|
|
15821
15821
|
}
|
|
15822
|
+
/**
|
|
15823
|
+
* Wasm linear-memory high-water mark in MB, from wasmHeapByteLength.
|
|
15824
|
+
*
|
|
15825
|
+
* @return {number | undefined} - wasm heap high-water, or undefined
|
|
15826
|
+
*/
|
|
15827
|
+
getWasmHeapPeak() {
|
|
15828
|
+
return this.wasmHeapPeak;
|
|
15829
|
+
}
|
|
15830
|
+
/**
|
|
15831
|
+
* The wasm heap only ever grows, so a single reading of it IS the peak —
|
|
15832
|
+
* no sampling loop and no forced GC. It is a different quantity from
|
|
15833
|
+
* geometryMemory, and by a wide margin: on MB-Khaya an 8 MB live geometry
|
|
15834
|
+
* payload sits under an 85 MB wasm heap, the gap being allocator overhead,
|
|
15835
|
+
* fragmentation and the intermediate buffers a boolean leaves behind (see
|
|
15836
|
+
* src/ifc/geometry_residency.ts). Neither substitutes for the other.
|
|
15837
|
+
*
|
|
15838
|
+
* @param value - wasm heap high-water in MB
|
|
15839
|
+
*/
|
|
15840
|
+
setWasmHeapPeak(value) {
|
|
15841
|
+
this.wasmHeapPeak = value;
|
|
15842
|
+
}
|
|
15822
15843
|
/**
|
|
15823
15844
|
*
|
|
15824
15845
|
* @return {string | undefined} - preprocessor version or undefined
|
|
@@ -15952,7 +15973,7 @@ var Statistics = class {
|
|
|
15952
15973
|
const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
|
|
15953
15974
|
const breakdown = this.formatGeometryTypeCounts();
|
|
15954
15975
|
const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
|
|
15955
|
-
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
15976
|
+
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, WASM Heap High-Water: ${this.wasmHeapPeak?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
15956
15977
|
}
|
|
15957
15978
|
};
|
|
15958
15979
|
|
|
@@ -16324,7 +16345,10 @@ var Memory = class {
|
|
|
16324
16345
|
const rss = (memoryUsage.rss / 1024 / 1024).toFixed(3);
|
|
16325
16346
|
const heapTotal = (memoryUsage.heapTotal / 1024 / 1024).toFixed(3);
|
|
16326
16347
|
const heapUsed = (memoryUsage.heapUsed / 1024 / 1024).toFixed(3);
|
|
16327
|
-
|
|
16348
|
+
const external = (memoryUsage.external / 1024 / 1024).toFixed(3);
|
|
16349
|
+
const arrayBuffers = (memoryUsage.arrayBuffers / 1024 / 1024).toFixed(3);
|
|
16350
|
+
const peakRss = (process.resourceUsage().maxRSS / 1024).toFixed(3);
|
|
16351
|
+
return `Node Memory Usage: RSS ${rss} MB, Heap Total: ${heapTotal} MB, Heap Used: ${heapUsed} MB, Peak RSS: ${peakRss} MB, External: ${external} MB, ArrayBuffers: ${arrayBuffers} MB`;
|
|
16328
16352
|
}
|
|
16329
16353
|
};
|
|
16330
16354
|
|
|
@@ -27012,6 +27036,10 @@ function wasmHeapView(wasmModule, arrayType, pointer, elementCount) {
|
|
|
27012
27036
|
const numBytes = elementCount * arrayType.BYTES_PER_ELEMENT;
|
|
27013
27037
|
return new arrayType(reconcileHeapBuffer(wasmModule, address, numBytes), address, elementCount);
|
|
27014
27038
|
}
|
|
27039
|
+
function wasmHeapByteLength(wasmModule) {
|
|
27040
|
+
refreshHeapViews(wasmModule);
|
|
27041
|
+
return currentHeapBuffer(wasmModule)?.byteLength ?? 0;
|
|
27042
|
+
}
|
|
27015
27043
|
function arrayToWasmHeap(wasmModule, array) {
|
|
27016
27044
|
const numBytes = array.length * array.BYTES_PER_ELEMENT;
|
|
27017
27045
|
const arrayPtr = wasmModule._malloc(numBytes) >>> 0;
|
|
@@ -95450,6 +95478,10 @@ function geometryExtraction(model, limitCSGDepth = true, maxCSGDepth = 20, onPro
|
|
|
95450
95478
|
const ONE_KB = 1024;
|
|
95451
95479
|
const ONE_MB = ONE_KB * ONE_KB;
|
|
95452
95480
|
statistics?.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / ONE_MB);
|
|
95481
|
+
const wasmModule = conwaywasm.wasmModule;
|
|
95482
|
+
if (wasmModule !== void 0) {
|
|
95483
|
+
statistics?.setWasmHeapPeak(wasmHeapByteLength(wasmModule) / ONE_MB);
|
|
95484
|
+
}
|
|
95453
95485
|
const ifcProjectName = conwayModel.getIfcProjectName();
|
|
95454
95486
|
if (ifcProjectName !== null) {
|
|
95455
95487
|
statistics?.setProjectName(ifcProjectName);
|
|
@@ -15943,7 +15943,7 @@ var ParsingBuffer = class {
|
|
|
15943
15943
|
};
|
|
15944
15944
|
|
|
15945
15945
|
// compiled/src/version/version.js
|
|
15946
|
-
var versionString = "Conway v1.
|
|
15946
|
+
var versionString = "Conway v1.553.1520";
|
|
15947
15947
|
|
|
15948
15948
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
15949
15949
|
function pThreadsAllowed() {
|
|
@@ -16797,6 +16797,27 @@ var Statistics = class {
|
|
|
16797
16797
|
setGeometryMemory(value) {
|
|
16798
16798
|
this.geometryMemory = value;
|
|
16799
16799
|
}
|
|
16800
|
+
/**
|
|
16801
|
+
* Wasm linear-memory high-water mark in MB, from wasmHeapByteLength.
|
|
16802
|
+
*
|
|
16803
|
+
* @return {number | undefined} - wasm heap high-water, or undefined
|
|
16804
|
+
*/
|
|
16805
|
+
getWasmHeapPeak() {
|
|
16806
|
+
return this.wasmHeapPeak;
|
|
16807
|
+
}
|
|
16808
|
+
/**
|
|
16809
|
+
* The wasm heap only ever grows, so a single reading of it IS the peak —
|
|
16810
|
+
* no sampling loop and no forced GC. It is a different quantity from
|
|
16811
|
+
* geometryMemory, and by a wide margin: on MB-Khaya an 8 MB live geometry
|
|
16812
|
+
* payload sits under an 85 MB wasm heap, the gap being allocator overhead,
|
|
16813
|
+
* fragmentation and the intermediate buffers a boolean leaves behind (see
|
|
16814
|
+
* src/ifc/geometry_residency.ts). Neither substitutes for the other.
|
|
16815
|
+
*
|
|
16816
|
+
* @param value - wasm heap high-water in MB
|
|
16817
|
+
*/
|
|
16818
|
+
setWasmHeapPeak(value) {
|
|
16819
|
+
this.wasmHeapPeak = value;
|
|
16820
|
+
}
|
|
16800
16821
|
/**
|
|
16801
16822
|
*
|
|
16802
16823
|
* @return {string | undefined} - preprocessor version or undefined
|
|
@@ -16930,7 +16951,7 @@ var Statistics = class {
|
|
|
16930
16951
|
const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
|
|
16931
16952
|
const breakdown = this.formatGeometryTypeCounts();
|
|
16932
16953
|
const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
|
|
16933
|
-
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
16954
|
+
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, WASM Heap High-Water: ${this.wasmHeapPeak?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
16934
16955
|
}
|
|
16935
16956
|
};
|
|
16936
16957
|
|
|
@@ -17302,7 +17323,10 @@ var Memory = class {
|
|
|
17302
17323
|
const rss = (memoryUsage.rss / 1024 / 1024).toFixed(3);
|
|
17303
17324
|
const heapTotal = (memoryUsage.heapTotal / 1024 / 1024).toFixed(3);
|
|
17304
17325
|
const heapUsed = (memoryUsage.heapUsed / 1024 / 1024).toFixed(3);
|
|
17305
|
-
|
|
17326
|
+
const external = (memoryUsage.external / 1024 / 1024).toFixed(3);
|
|
17327
|
+
const arrayBuffers = (memoryUsage.arrayBuffers / 1024 / 1024).toFixed(3);
|
|
17328
|
+
const peakRss = (process.resourceUsage().maxRSS / 1024).toFixed(3);
|
|
17329
|
+
return `Node Memory Usage: RSS ${rss} MB, Heap Total: ${heapTotal} MB, Heap Used: ${heapUsed} MB, Peak RSS: ${peakRss} MB, External: ${external} MB, ArrayBuffers: ${arrayBuffers} MB`;
|
|
17306
17330
|
}
|
|
17307
17331
|
};
|
|
17308
17332
|
|
|
@@ -86173,7 +86197,7 @@ function geometryExtraction(model, limitCSGDepth = true, maxCSGDepth = 20) {
|
|
|
86173
86197
|
const ONE_MB = ONE_KB * ONE_KB;
|
|
86174
86198
|
const wasmModule = conwaywasm.wasmModule;
|
|
86175
86199
|
if (wasmModule !== void 0) {
|
|
86176
|
-
|
|
86200
|
+
statistics?.setWasmHeapPeak(wasmHeapByteLength(wasmModule) / ONE_MB);
|
|
86177
86201
|
}
|
|
86178
86202
|
statistics?.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / ONE_MB);
|
|
86179
86203
|
model.invalidate(true);
|
|
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
|
|
|
944
944
|
var entity_types_ifc_gen_default = EntityTypesIfc;
|
|
945
945
|
|
|
946
946
|
// compiled/src/version/version.js
|
|
947
|
-
var versionString = "Conway v1.
|
|
947
|
+
var versionString = "Conway v1.553.1520";
|
|
948
948
|
|
|
949
949
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
950
950
|
var wasmType = "";
|
|
@@ -1059,6 +1059,27 @@ var Statistics = class {
|
|
|
1059
1059
|
setGeometryMemory(value) {
|
|
1060
1060
|
this.geometryMemory = value;
|
|
1061
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Wasm linear-memory high-water mark in MB, from wasmHeapByteLength.
|
|
1064
|
+
*
|
|
1065
|
+
* @return {number | undefined} - wasm heap high-water, or undefined
|
|
1066
|
+
*/
|
|
1067
|
+
getWasmHeapPeak() {
|
|
1068
|
+
return this.wasmHeapPeak;
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* The wasm heap only ever grows, so a single reading of it IS the peak —
|
|
1072
|
+
* no sampling loop and no forced GC. It is a different quantity from
|
|
1073
|
+
* geometryMemory, and by a wide margin: on MB-Khaya an 8 MB live geometry
|
|
1074
|
+
* payload sits under an 85 MB wasm heap, the gap being allocator overhead,
|
|
1075
|
+
* fragmentation and the intermediate buffers a boolean leaves behind (see
|
|
1076
|
+
* src/ifc/geometry_residency.ts). Neither substitutes for the other.
|
|
1077
|
+
*
|
|
1078
|
+
* @param value - wasm heap high-water in MB
|
|
1079
|
+
*/
|
|
1080
|
+
setWasmHeapPeak(value) {
|
|
1081
|
+
this.wasmHeapPeak = value;
|
|
1082
|
+
}
|
|
1062
1083
|
/**
|
|
1063
1084
|
*
|
|
1064
1085
|
* @return {string | undefined} - preprocessor version or undefined
|
|
@@ -1192,7 +1213,7 @@ var Statistics = class {
|
|
|
1192
1213
|
const products = this.productCount !== void 0 ? `Products: ${this.productCount}, ` : "";
|
|
1193
1214
|
const breakdown = this.formatGeometryTypeCounts();
|
|
1194
1215
|
const geometryTypes = breakdown !== void 0 ? `, Geometry Types: ${breakdown}` : "";
|
|
1195
|
-
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
1216
|
+
return `[${dateString}]: Load Status: ${this.loadStatus}, Project Name: ${this.projectName}, Version: ${versionStr}, Conway Version: ${conwayVersionNumber}-${wasmType}, Parse Time: ${this.parseTime} ms, Geometry Time: ${this.geometryTime} ms, Total Time: ${this.totalTime} ms, Geometry Memory: ${this.geometryMemory?.toFixed(3)} MB, WASM Heap High-Water: ${this.wasmHeapPeak?.toFixed(3)} MB, ` + products + `Memory Statistics: ${this.memoryStatistics}, Preprocessor Version: ${this.preprocessorVersion}, Originating System: ${this.originatingSystem}` + geometryTypes;
|
|
1196
1217
|
}
|
|
1197
1218
|
};
|
|
1198
1219
|
|
|
@@ -405,12 +405,15 @@ function geometryExtraction(model, limitCSGDepth = true, maxCSGDepth = 20) {
|
|
|
405
405
|
statistics?.setGeometryTime(executionTimeInMs);
|
|
406
406
|
const ONE_KB = 1024;
|
|
407
407
|
const ONE_MB = ONE_KB * ONE_KB;
|
|
408
|
+
// Recorded on the statistics rather than logged on its own line, so the one
|
|
409
|
+
// spelling of this number reaches the benchmark's `peakWasmHeapMb` column
|
|
410
|
+
// through the same load-status line as every other measurement (#552).
|
|
408
411
|
// Measured through wasmHeapByteLength rather than HEAPU8.length: the
|
|
409
412
|
// module's cached view can be a growth step behind the real heap (#485), and
|
|
410
413
|
// a high-water figure that under-reports is worse than none.
|
|
411
414
|
const wasmModule = conwaywasm.wasmModule;
|
|
412
415
|
if (wasmModule !== void 0) {
|
|
413
|
-
|
|
416
|
+
statistics?.setWasmHeapPeak(wasmHeapByteLength(wasmModule) / ONE_MB);
|
|
414
417
|
}
|
|
415
418
|
statistics?.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / (ONE_MB));
|
|
416
419
|
model.invalidate(true);
|
|
@@ -9,6 +9,7 @@ import fsPromises from "fs/promises";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import crypto from "crypto";
|
|
11
11
|
import { ConwayGeometry } from "../../dependencies/conway-geom/index.js";
|
|
12
|
+
import { wasmHeapByteLength } from "../core/wasm_heap.js";
|
|
12
13
|
import Logger from "../logging/logger.js";
|
|
13
14
|
import Environment from "../utilities/environment.js";
|
|
14
15
|
import { ExtractResult } from "../core/shared_constants.js";
|
|
@@ -35,22 +36,40 @@ function csvSafeString(from) {
|
|
|
35
36
|
// Bytes per megabyte for memory-stat formatting in the perf CSV.
|
|
36
37
|
// eslint-disable-next-line no-magic-numbers
|
|
37
38
|
const BYTES_PER_MB = 1024 * 1024;
|
|
39
|
+
// Kilobytes per megabyte, for resourceUsage().maxRSS which reports kB.
|
|
40
|
+
// eslint-disable-next-line no-magic-numbers
|
|
41
|
+
const KB_PER_MB = 1024;
|
|
38
42
|
// Fixed-point precision for perf MB values.
|
|
39
43
|
// eslint-disable-next-line no-magic-numbers
|
|
40
44
|
const PERF_MB_PRECISION = 2;
|
|
45
|
+
/** Placeholder for a column this row has no measurement for. */
|
|
46
|
+
const UNMEASURED = "N/A";
|
|
41
47
|
/**
|
|
42
48
|
* Write a single-row per-file perf CSV at the given path, matching the
|
|
43
49
|
* column layout of the IFC regression child so the batch aggregator can
|
|
44
50
|
* merge STEP and IFC rows into one perf CSV. No-op when perfPath is empty.
|
|
45
51
|
*
|
|
52
|
+
* `peakRssMb` is the process high-water mark; `rssMb`, `heapUsedMb`,
|
|
53
|
+
* `heapTotalMb`, `externalMb` and `arrayBuffersMb` are single instants
|
|
54
|
+
* sampled at write time, and `geometryMemoryMb` is conway's own vertex+index
|
|
55
|
+
* payload rather than a process metric. `arrayBuffersMb` is a subset of
|
|
56
|
+
* `externalMb`, and neither sees the wasm heap. See the fuller
|
|
57
|
+
* column-by-column note on the IFC child's copy of this function
|
|
58
|
+
* (`src/ifc/ifc_regression_main.ts`), which is the writer these columns have
|
|
59
|
+
* to stay identical to.
|
|
60
|
+
*
|
|
46
61
|
* @param perfPath Path to write the CSV to. Empty string disables.
|
|
47
62
|
* @param stepFile Source STEP file path (basename used as the row key).
|
|
48
63
|
* @param status OK or FAIL.
|
|
49
64
|
* @param parseTimeMs Parse stage duration in ms.
|
|
50
65
|
* @param geometryTimeMs Geometry extraction duration in ms.
|
|
51
66
|
* @param totalTimeMs Sum of parse + geometry in ms.
|
|
67
|
+
* @param geometryMemoryBytes Geometry payload conway allocated, in bytes, or
|
|
68
|
+
* undefined where no geometry was extracted (written as N/A).
|
|
69
|
+
* @param wasmHeapBytes Wasm linear-memory high-water in bytes, or undefined
|
|
70
|
+
* where the module was never brought up (written as N/A).
|
|
52
71
|
*/
|
|
53
|
-
async function writePerfCsvIfRequested(perfPath, stepFile, status, parseTimeMs, geometryTimeMs, totalTimeMs) {
|
|
72
|
+
async function writePerfCsvIfRequested(perfPath, stepFile, status, parseTimeMs, geometryTimeMs, totalTimeMs, geometryMemoryBytes, wasmHeapBytes) {
|
|
54
73
|
if (perfPath.length === 0) {
|
|
55
74
|
return;
|
|
56
75
|
}
|
|
@@ -58,10 +77,23 @@ async function writePerfCsvIfRequested(perfPath, stepFile, status, parseTimeMs,
|
|
|
58
77
|
const rssMb = (mem.rss / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
59
78
|
const heapUsedMb = (mem.heapUsed / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
60
79
|
const heapTotalMb = (mem.heapTotal / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
80
|
+
const externalMb = (mem.external / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
81
|
+
const arrayBuffersMb = (mem.arrayBuffers / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
82
|
+
// maxRSS is reported in kilobytes, unlike memoryUsage() which is in bytes.
|
|
83
|
+
const peakRssMb = (process.resourceUsage().maxRSS / KB_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
84
|
+
const geometryMemoryMb = geometryMemoryBytes !== void 0 ?
|
|
85
|
+
(geometryMemoryBytes / BYTES_PER_MB).toFixed(PERF_MB_PRECISION) :
|
|
86
|
+
UNMEASURED;
|
|
87
|
+
const peakWasmHeapMb = wasmHeapBytes !== void 0 ?
|
|
88
|
+
(wasmHeapBytes / BYTES_PER_MB).toFixed(PERF_MB_PRECISION) :
|
|
89
|
+
UNMEASURED;
|
|
61
90
|
const fileName = csvSafeString(path.basename(stepFile));
|
|
62
|
-
const header = "file,status,parseTimeMs,geometryTimeMs,totalTimeMs,
|
|
91
|
+
const header = "file,status,parseTimeMs,geometryTimeMs,totalTimeMs,geometryMemoryMb," +
|
|
92
|
+
"peakWasmHeapMb,rssMb,peakRssMb,heapUsedMb,heapTotalMb,externalMb," +
|
|
93
|
+
"arrayBuffersMb\n";
|
|
63
94
|
const row = `${fileName},${status},${parseTimeMs},${geometryTimeMs},${totalTimeMs},` +
|
|
64
|
-
`${
|
|
95
|
+
`${geometryMemoryMb},${peakWasmHeapMb},${rssMb},${peakRssMb},` +
|
|
96
|
+
`${heapUsedMb},${heapTotalMb},${externalMb},${arrayBuffersMb}\n`;
|
|
65
97
|
try {
|
|
66
98
|
await fsPromises.writeFile(perfPath, header + row);
|
|
67
99
|
}
|
|
@@ -206,7 +238,18 @@ function doWork() {
|
|
|
206
238
|
const geometryTimeMs = geomEndMs - geomStartMs;
|
|
207
239
|
const totalTimeMs = geomEndMs - parseStartMs;
|
|
208
240
|
const perfStatus = extraction === void 0 ? "FAIL" : "OK";
|
|
209
|
-
|
|
241
|
+
// Sized before anything downstream can release meshes, and only on
|
|
242
|
+
// the OK path: a failed extraction leaves a partial cache whose size
|
|
243
|
+
// is not this model's geometry footprint.
|
|
244
|
+
const geometryMemoryBytes = extraction !== void 0 ?
|
|
245
|
+
model.geometry.calculateGeometrySize() : void 0;
|
|
246
|
+
// The heap is grow-only, so this is the run's high-water mark even
|
|
247
|
+
// though it is read once, after the fact. conwayGeom is the engine
|
|
248
|
+
// every extraction in this process runs against.
|
|
249
|
+
const wasmModule = conwayGeom.wasmModule;
|
|
250
|
+
const wasmHeapBytes = wasmModule !== void 0 ?
|
|
251
|
+
wasmHeapByteLength(wasmModule) : void 0;
|
|
252
|
+
await writePerfCsvIfRequested(perfPath, stepFile, perfStatus, parseTimeMs, geometryTimeMs, totalTimeMs, geometryMemoryBytes, wasmHeapBytes);
|
|
210
253
|
// AFTP sizing pass: no-op unless the wasm module was built with
|
|
211
254
|
// CONWAY_ALLOC_TELEMETRY (see conway-geom structures/alloc_telemetry.h).
|
|
212
255
|
conwayGeom.dumpAllocTelemetry(path.basename(stepFile));
|
|
@@ -125,10 +125,11 @@ export declare function wasmHeapView<TArray>(wasmModule: WasmHeapModule, arrayTy
|
|
|
125
125
|
* trade. Do not put it in a loop.
|
|
126
126
|
*
|
|
127
127
|
* That the refresh cannot throw (see refreshHeapViews) matters more here than
|
|
128
|
-
* at the other call site: this figure
|
|
129
|
-
* high-water
|
|
130
|
-
*
|
|
131
|
-
*
|
|
128
|
+
* at the other call site: every consumer of this figure is reporting — the
|
|
129
|
+
* loaders' and CLIs' high-water statistic, and the regression children's
|
|
130
|
+
* `peakWasmHeapMb` perf column (#552) — so an embind failure escaping would
|
|
131
|
+
* abort an otherwise complete extraction from a measurement. A lagging number
|
|
132
|
+
* is the right answer there.
|
|
132
133
|
*
|
|
133
134
|
* @param wasmModule The module to measure.
|
|
134
135
|
* @return {number} The heap's size in bytes, or 0 if it has no heap yet.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm_heap.d.ts","sourceRoot":"","sources":["../../../src/core/wasm_heap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAKH;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,CAAA;IAChC,KAAK,CAAE,OAAO,EAAE,MAAM,GAAI,IAAI,CAAA;IAC9B,MAAM,EAAE,UAAU,CAAA;IAElB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;IAE9B;;;;OAIG;IACH,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;KAAE,CAAA;IAEjD;;;OAGG;IACH,YAAY,CAAC,EAAE,UAAU;QAAE,SAAS,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;QAAC,MAAM,IAAI,IAAI,CAAA;KAAE,CAAA;CAC9E;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAA;AAMrE;;;GAGG;AACH,MAAM,WAAW,wBAAwB,CAAE,MAAM;IAC/C,KAAM,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,MAAM,CAAA;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;CACnC;AA6MD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAE,MAAM,EAChC,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,wBAAwB,CAAE,MAAM,CAAE,EAC7C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GAAI,MAAM,CASjC;AAGD
|
|
1
|
+
{"version":3,"file":"wasm_heap.d.ts","sourceRoot":"","sources":["../../../src/core/wasm_heap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAKH;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,CAAA;IAChC,KAAK,CAAE,OAAO,EAAE,MAAM,GAAI,IAAI,CAAA;IAC9B,MAAM,EAAE,UAAU,CAAA;IAElB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;IAE9B;;;;OAIG;IACH,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;KAAE,CAAA;IAEjD;;;OAGG;IACH,YAAY,CAAC,EAAE,UAAU;QAAE,SAAS,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;QAAC,MAAM,IAAI,IAAI,CAAA;KAAE,CAAA;CAC9E;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAA;AAMrE;;;GAGG;AACH,MAAM,WAAW,wBAAwB,CAAE,MAAM;IAC/C,KAAM,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,MAAM,CAAA;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;CACnC;AA6MD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAE,MAAM,EAChC,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,wBAAwB,CAAE,MAAM,CAAE,EAC7C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GAAI,MAAM,CASjC;AAGD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAE,UAAU,EAAE,cAAc,GAAI,MAAM,CAKvE;AAGD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAI,MAAM,CA8C7D;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC5B,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,SAAS,aAAa,EAAE,GAAI,MAAM,EAAE,CAqB/C;AAGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAE,OAAO,EAAE,MAAM,IAAI,GAAI,IAAI,CAW1D;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,GAAI,CAAC,CAiBtE;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CACnB,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAI,IAAI,CAkBlE"}
|
|
@@ -250,10 +250,11 @@ export function wasmHeapView(wasmModule, arrayType, pointer, elementCount) {
|
|
|
250
250
|
* trade. Do not put it in a loop.
|
|
251
251
|
*
|
|
252
252
|
* That the refresh cannot throw (see refreshHeapViews) matters more here than
|
|
253
|
-
* at the other call site: this figure
|
|
254
|
-
* high-water
|
|
255
|
-
*
|
|
256
|
-
*
|
|
253
|
+
* at the other call site: every consumer of this figure is reporting — the
|
|
254
|
+
* loaders' and CLIs' high-water statistic, and the regression children's
|
|
255
|
+
* `peakWasmHeapMb` perf column (#552) — so an embind failure escaping would
|
|
256
|
+
* abort an otherwise complete extraction from a measurement. A lagging number
|
|
257
|
+
* is the right answer there.
|
|
257
258
|
*
|
|
258
259
|
* @param wasmModule The module to measure.
|
|
259
260
|
* @return {number} The heap's size in bytes, or 0 if it has no heap yet.
|
|
@@ -9,6 +9,7 @@ import { IfcGeometryExtraction } from "./ifc_geometry_extraction.js";
|
|
|
9
9
|
import { IfcPropertyExtraction } from "./ifc_property_extraction.js";
|
|
10
10
|
import { ConwayGeometry } from "../../dependencies/conway-geom/index.js";
|
|
11
11
|
import GeometryConvertor from "../core/geometry_convertor.js";
|
|
12
|
+
import { wasmHeapByteLength } from "../core/wasm_heap.js";
|
|
12
13
|
import GeometryAggregator from "../core/geometry_aggregator.js";
|
|
13
14
|
import Logger, { LogLevel } from "../logging/logger.js";
|
|
14
15
|
import { ProgressTracker } from "../core/progress.js";
|
|
@@ -545,6 +546,17 @@ function geometryExtraction(model, limitCSGDepth = true, maxCSGDepth = 20, onPro
|
|
|
545
546
|
const ONE_KB = 1024;
|
|
546
547
|
const ONE_MB = ONE_KB * ONE_KB;
|
|
547
548
|
statistics?.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / (ONE_MB));
|
|
549
|
+
// The wasm heap, which nothing else here can see: geometryMemory above is
|
|
550
|
+
// the vertex+index payload only, and the JS-side heap/external figures do
|
|
551
|
+
// not include emscripten's linear memory at all. Grow-only, so one reading
|
|
552
|
+
// is the high-water mark. Measured through wasmHeapByteLength rather than
|
|
553
|
+
// HEAPU8.length: the module's cached view can be a growth step behind the
|
|
554
|
+
// real heap (#485), and a high-water figure that under-reports is worse
|
|
555
|
+
// than none.
|
|
556
|
+
const wasmModule = conwaywasm.wasmModule;
|
|
557
|
+
if (wasmModule !== void 0) {
|
|
558
|
+
statistics?.setWasmHeapPeak(wasmHeapByteLength(wasmModule) / ONE_MB);
|
|
559
|
+
}
|
|
548
560
|
const ifcProjectName = conwayModel.getIfcProjectName();
|
|
549
561
|
if (ifcProjectName !== null) {
|
|
550
562
|
statistics?.setProjectName(ifcProjectName);
|
|
@@ -14,6 +14,7 @@ import fsPromises from "fs/promises";
|
|
|
14
14
|
import EntityTypesIfc from "./ifc4_gen/entity_types_ifc.gen.js";
|
|
15
15
|
import { IfcBooleanResult } from "./ifc4_gen/index.js";
|
|
16
16
|
import { MemoizationCapture, RegressionCaptureState } from "../core/regression_capture_state.js";
|
|
17
|
+
import { wasmHeapByteLength } from "../core/wasm_heap.js";
|
|
17
18
|
import { materialHashes } from "./ifc_material_cache_node.js";
|
|
18
19
|
import { dumpGeometryOBJs, geometryHashes } from "./ifc_model_geometry_node.js";
|
|
19
20
|
import { curveHashes, dumpCurveOBJs } from "./ifc_model_curves_node.js";
|
|
@@ -39,28 +40,93 @@ function csvSafeString(from) {
|
|
|
39
40
|
// Bytes per megabyte for memory-stat formatting in the perf CSV.
|
|
40
41
|
// eslint-disable-next-line no-magic-numbers
|
|
41
42
|
const BYTES_PER_MB = 1024 * 1024;
|
|
43
|
+
// Kilobytes per megabyte, for resourceUsage().maxRSS which reports kB.
|
|
44
|
+
// eslint-disable-next-line no-magic-numbers
|
|
45
|
+
const KB_PER_MB = 1024;
|
|
42
46
|
// Fixed-point precision for perf MB values.
|
|
43
47
|
// eslint-disable-next-line no-magic-numbers
|
|
44
48
|
const PERF_MB_PRECISION = 2;
|
|
49
|
+
/** Placeholder for a column this row has no measurement for. */
|
|
50
|
+
const UNMEASURED = "N/A";
|
|
45
51
|
/**
|
|
46
52
|
* Write a single-row per-file perf CSV at the given path. Memory snapshot is
|
|
47
53
|
* taken at call time; for the OK path this is right after geometry extraction
|
|
48
54
|
* — close to peak. No-op when perfPath is empty.
|
|
49
55
|
*
|
|
50
|
-
*
|
|
51
|
-
* the
|
|
56
|
+
* WHICH COLUMNS ARE PEAK AND WHICH ARE INSTANTS — they are not comparable and
|
|
57
|
+
* the difference is large (conway#552):
|
|
58
|
+
*
|
|
59
|
+
* peakRssMb PEAK. The kernel's high-water mark for this process
|
|
60
|
+
* (`resourceUsage().maxRSS`, kB), i.e. the number that
|
|
61
|
+
* decides whether a browser tab or a runner survives the
|
|
62
|
+
* load. Free to read and perturbs nothing.
|
|
63
|
+
* rssMb INSTANT. One `memoryUsage()` sample at write time. A run
|
|
64
|
+
* that transiently hit 5 GB and settled to 1 GB reports
|
|
65
|
+
* 1 GB here and 5 GB in peakRssMb.
|
|
66
|
+
* heapUsedMb INSTANT, and *not* live set: it is live data plus
|
|
67
|
+
* whatever garbage GC has not collected yet, so it moves
|
|
68
|
+
* with GC timing. Measuring SKYLARK250 this way gives
|
|
69
|
+
* 2547 MB where the same run's live heap after two forced
|
|
70
|
+
* full GCs is 981 MB. A live-heap column would need forced
|
|
71
|
+
* GC, which wrecks the timing columns, so it is not here.
|
|
72
|
+
* heapTotalMb INSTANT. V8's reserved heap.
|
|
73
|
+
* externalMb INSTANT. Off-heap bytes V8 knows about, which heapUsed
|
|
74
|
+
* does not include and which are a real part of the
|
|
75
|
+
* footprint: on MB-Khaya (31 MB IFC) `readFileSync` alone
|
|
76
|
+
* moves this 1.7 -> 33.1 MB while heapUsed does not move.
|
|
77
|
+
* arrayBuffersMb INSTANT, and a SUBSET of externalMb — the ArrayBuffer
|
|
78
|
+
* share of it, which is where the source buffer and the
|
|
79
|
+
* parse structures land (31.5 of that 33.1 MB).
|
|
80
|
+
* geometryMemoryMb Not a process metric at all: the vertex+index PAYLOAD
|
|
81
|
+
* conway itself allocated for this model, summed by
|
|
82
|
+
* `calculateGeometrySize()` — what a consumer would copy
|
|
83
|
+
* out. Unlike rss/heap it excludes everything the harness
|
|
84
|
+
* happens to be holding, and unlike peakWasmHeapMb it
|
|
85
|
+
* excludes everything the allocator is holding.
|
|
86
|
+
* peakWasmHeapMb PEAK, and the only column that sees conway's native
|
|
87
|
+
* memory. Emscripten's linear memory grows and never
|
|
88
|
+
* shrinks, so one reading of `wasmHeapByteLength` IS the
|
|
89
|
+
* high-water mark — nothing to sample, nothing perturbed.
|
|
90
|
+
* Read through that helper rather than `HEAPU8.length`,
|
|
91
|
+
* whose cached view can be a growth step behind the real
|
|
92
|
+
* heap (#485); a high-water figure that under-reports is
|
|
93
|
+
* worse than none. This is NOT geometryMemoryMb: it
|
|
94
|
+
* includes allocator overhead, fragmentation and the
|
|
95
|
+
* intermediate buffers a boolean leaves behind, which on
|
|
96
|
+
* MB-Khaya is an 85 MB heap over an 8 MB live payload.
|
|
97
|
+
*
|
|
98
|
+
* There is deliberately no `heapUsed + external` total. It looks like a
|
|
99
|
+
* portable stand-in for RSS and is not one: on that same model it reads
|
|
100
|
+
* 284 MB against an RSS of 510 MB after geometry, and wasm init alone adds
|
|
101
|
+
* ~65 MB of RSS while moving `external` by under 2 MB. Emscripten's heap is
|
|
102
|
+
* structurally invisible to JS-side accounting, so such a total would be
|
|
103
|
+
* blind to exactly the memory this bench exists to track. peakRssMb is the
|
|
104
|
+
* headline.
|
|
105
|
+
*
|
|
106
|
+
* `rssMb` and `peakRssMb` include the conway-geom WASM heap (mmap'd into the
|
|
107
|
+
* process) and are the load-bearing memory metrics for geometry work.
|
|
52
108
|
* `heapUsedMb` / `heapTotalMb` are V8-only — useful for tracking JS-side
|
|
53
109
|
* allocation pressure but they exclude WASM-side buffers. Expect a large
|
|
54
110
|
* gap between rss and heap on geometry-heavy models.
|
|
55
111
|
*
|
|
112
|
+
* The column list here is shared with the AP214 regression child
|
|
113
|
+
* (`ap214_regression_main.ts`): `aggregatePerfCsvs` in
|
|
114
|
+
* `ifc_regression_batch_main.ts` keeps the header of whichever per-file CSV it
|
|
115
|
+
* reads first and concatenates the rest as rows, so a mixed IFC/STEP corpus
|
|
116
|
+
* mislabels every column if the two writers drift apart.
|
|
117
|
+
*
|
|
56
118
|
* @param perfPath Path to write the CSV to. Empty string disables.
|
|
57
119
|
* @param ifcFile Source IFC file path (basename used as the row key).
|
|
58
120
|
* @param status OK or FAIL.
|
|
59
121
|
* @param parseTimeMs Parse stage duration in ms.
|
|
60
122
|
* @param geometryTimeMs Geometry extraction duration in ms.
|
|
61
123
|
* @param totalTimeMs Sum of parse + geometry in ms.
|
|
124
|
+
* @param geometryMemoryBytes Geometry payload conway allocated, in bytes, or
|
|
125
|
+
* undefined where no geometry was extracted (written as N/A).
|
|
126
|
+
* @param wasmHeapBytes Wasm linear-memory high-water in bytes, or undefined
|
|
127
|
+
* where the module was never brought up (written as N/A).
|
|
62
128
|
*/
|
|
63
|
-
async function writePerfCsvIfRequested(perfPath, ifcFile, status, parseTimeMs, geometryTimeMs, totalTimeMs) {
|
|
129
|
+
async function writePerfCsvIfRequested(perfPath, ifcFile, status, parseTimeMs, geometryTimeMs, totalTimeMs, geometryMemoryBytes, wasmHeapBytes) {
|
|
64
130
|
if (perfPath.length === 0) {
|
|
65
131
|
return;
|
|
66
132
|
}
|
|
@@ -68,10 +134,23 @@ async function writePerfCsvIfRequested(perfPath, ifcFile, status, parseTimeMs, g
|
|
|
68
134
|
const rssMb = (mem.rss / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
69
135
|
const heapUsedMb = (mem.heapUsed / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
70
136
|
const heapTotalMb = (mem.heapTotal / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
137
|
+
const externalMb = (mem.external / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
138
|
+
const arrayBuffersMb = (mem.arrayBuffers / BYTES_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
139
|
+
// maxRSS is reported in kilobytes, unlike memoryUsage() which is in bytes.
|
|
140
|
+
const peakRssMb = (process.resourceUsage().maxRSS / KB_PER_MB).toFixed(PERF_MB_PRECISION);
|
|
141
|
+
const geometryMemoryMb = geometryMemoryBytes !== void 0 ?
|
|
142
|
+
(geometryMemoryBytes / BYTES_PER_MB).toFixed(PERF_MB_PRECISION) :
|
|
143
|
+
UNMEASURED;
|
|
144
|
+
const peakWasmHeapMb = wasmHeapBytes !== void 0 ?
|
|
145
|
+
(wasmHeapBytes / BYTES_PER_MB).toFixed(PERF_MB_PRECISION) :
|
|
146
|
+
UNMEASURED;
|
|
71
147
|
const fileName = csvSafeString(path.basename(ifcFile));
|
|
72
|
-
const header = "file,status,parseTimeMs,geometryTimeMs,totalTimeMs,
|
|
148
|
+
const header = "file,status,parseTimeMs,geometryTimeMs,totalTimeMs,geometryMemoryMb," +
|
|
149
|
+
"peakWasmHeapMb,rssMb,peakRssMb,heapUsedMb,heapTotalMb,externalMb," +
|
|
150
|
+
"arrayBuffersMb\n";
|
|
73
151
|
const row = `${fileName},${status},${parseTimeMs},${geometryTimeMs},${totalTimeMs},` +
|
|
74
|
-
`${
|
|
152
|
+
`${geometryMemoryMb},${peakWasmHeapMb},${rssMb},${peakRssMb},` +
|
|
153
|
+
`${heapUsedMb},${heapTotalMb},${externalMb},${arrayBuffersMb}\n`;
|
|
75
154
|
try {
|
|
76
155
|
await fsPromises.writeFile(perfPath, header + row);
|
|
77
156
|
}
|
|
@@ -220,7 +299,19 @@ function doWork() {
|
|
|
220
299
|
const geometryTimeMs = geomEndMs - geomStartMs;
|
|
221
300
|
const totalTimeMs = geomEndMs - parseStartMs;
|
|
222
301
|
const perfStatus = result === void 0 ? "FAIL" : "OK";
|
|
223
|
-
|
|
302
|
+
// Sized before anything downstream can release meshes, and only on
|
|
303
|
+
// the OK path: a failed extraction leaves a partial cache whose size
|
|
304
|
+
// is not this model's geometry footprint.
|
|
305
|
+
const geometryMemoryBytes = result !== void 0 ?
|
|
306
|
+
model.geometry.calculateGeometrySize() : void 0;
|
|
307
|
+
// The heap is grow-only, so this is the run's high-water mark even
|
|
308
|
+
// though it is read once, after the fact. geometryExtraction hands
|
|
309
|
+
// back the engine it brought up; there is no heap to measure when
|
|
310
|
+
// it failed before that.
|
|
311
|
+
const wasmModule = result?.[1].wasmModule;
|
|
312
|
+
const wasmHeapBytes = wasmModule !== void 0 ?
|
|
313
|
+
wasmHeapByteLength(wasmModule) : void 0;
|
|
314
|
+
await writePerfCsvIfRequested(perfPath, ifcFile, perfStatus, parseTimeMs, geometryTimeMs, totalTimeMs, geometryMemoryBytes, wasmHeapBytes);
|
|
224
315
|
// AFTP sizing pass: no-op unless the wasm module was built with
|
|
225
316
|
// CONWAY_ALLOC_TELEMETRY (see conway-geom structures/alloc_telemetry.h).
|
|
226
317
|
conwayGeom.dumpAllocTelemetry(path.basename(ifcFile));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conway_model_loader.d.ts","sourceRoot":"","sources":["../../../src/loaders/conway_model_loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAmB,MAAM,sBAAsB,CAAA;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"conway_model_loader.d.ts","sourceRoot":"","sources":["../../../src/loaders/conway_model_loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAmB,MAAM,sBAAsB,CAAA;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AA4CrC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE/B;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAE1B,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAE,IAAI,EAAE,SAAS,KAAM,IAAI,CAAA;CAC1C;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAE5B;;;;;;;;;OASG;WACiB,kBAAkB,CAClC,IAAI,EAAE,UAAU,EAChB,aAAa,GAAE,OAAc,EAC7B,eAAe,GAAE,MAAW,EAC5B,OAAO,GAAE,MAAU,EACnB,OAAO,CAAC,EAAE,gBAAgB,GAAI,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;CA8c1D"}
|
|
@@ -13,8 +13,32 @@ import Memory from "../memory/memory.js";
|
|
|
13
13
|
import ParsingBuffer from "../parsing/parsing_buffer.js";
|
|
14
14
|
import { ParseResult } from "../step/parsing/step_parser.js";
|
|
15
15
|
import { extractModelInfo, parseFileHeader } from "./loading_utilities.js";
|
|
16
|
+
import { wasmHeapByteLength } from "../core/wasm_heap.js";
|
|
16
17
|
const ONE_KB = 1024;
|
|
17
18
|
const ONE_MB = ONE_KB * ONE_KB;
|
|
19
|
+
/**
|
|
20
|
+
* Record the wasm heap's high-water mark on the run's statistics.
|
|
21
|
+
*
|
|
22
|
+
* The wasm heap only grows, so one reading of it is already the peak — there
|
|
23
|
+
* is nothing to sample and nothing to perturb. This is the only column that
|
|
24
|
+
* sees conway's native memory at all: `heapUsed`/`external` cannot (wasm init
|
|
25
|
+
* alone moves RSS by ~65 MB while moving `external` by under 2 MB), and
|
|
26
|
+
* `geometryMemory` is the vertex+index payload only, which on MB-Khaya is
|
|
27
|
+
* 8 MB live under an 85 MB wasm heap.
|
|
28
|
+
*
|
|
29
|
+
* Measured through wasmHeapByteLength rather than HEAPU8.length: the module's
|
|
30
|
+
* cached view can be a growth step behind the real heap (#485), and a
|
|
31
|
+
* high-water figure that under-reports is worse than none.
|
|
32
|
+
*
|
|
33
|
+
* @param statistics The run's statistics.
|
|
34
|
+
* @param conwayWasm The geometry engine whose heap to measure.
|
|
35
|
+
*/
|
|
36
|
+
function recordWasmHeapPeak(statistics, conwayWasm) {
|
|
37
|
+
const wasmModule = conwayWasm.wasmModule;
|
|
38
|
+
if (wasmModule !== void 0) {
|
|
39
|
+
statistics.setWasmHeapPeak(wasmHeapByteLength(wasmModule) / ONE_MB);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
18
42
|
/**
|
|
19
43
|
* Static class for loading a model from a Uint 8 array...
|
|
20
44
|
*
|
|
@@ -134,6 +158,7 @@ export class ConwayModelLoader {
|
|
|
134
158
|
tracker?.endPhase();
|
|
135
159
|
statistics.setGeometryTime(executionTimeInMs);
|
|
136
160
|
statistics.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / (ONE_MB));
|
|
161
|
+
recordWasmHeapPeak(statistics, conwayWasm);
|
|
137
162
|
statistics.setGeometryTypeCounts(conwayModel.geometryTypeCounts);
|
|
138
163
|
model.invalidate(true);
|
|
139
164
|
if (extractionResult !== ExtractResult.COMPLETE) {
|
|
@@ -264,6 +289,7 @@ export class ConwayModelLoader {
|
|
|
264
289
|
tracker?.endPhase();
|
|
265
290
|
statistics.setGeometryTime(executionTimeInMs);
|
|
266
291
|
statistics.setGeometryMemory(conwayModel.model.geometry.calculateGeometrySize() / (ONE_MB));
|
|
292
|
+
recordWasmHeapPeak(statistics, conwayWasm);
|
|
267
293
|
const ifcProjectName = conwayModel.getIfcProjectName();
|
|
268
294
|
if (ifcProjectName !== null) {
|
|
269
295
|
statistics.setProjectName(ifcProjectName);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/memory/memory.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IAEX,UAAU,WAAW;QACjB,MAAM,CAAC,EAAE;YACL,eAAe,EAAE,MAAM,CAAA;YACvB,eAAe,EAAE,MAAM,CAAA;YACvB,cAAc,EAAE,MAAM,CAAA;SACzB,CAAA;KACJ;CACJ;AAKD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB;;;OAGG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM;IAiBjC;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;IAiBvC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAYjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/memory/memory.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IAEX,UAAU,WAAW;QACjB,MAAM,CAAC,EAAE;YACL,eAAe,EAAE,MAAM,CAAA;YACvB,eAAe,EAAE,MAAM,CAAA;YACvB,cAAc,EAAE,MAAM,CAAA;SACzB,CAAA;KACJ;CACJ;AAKD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB;;;OAGG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM;IAiBjC;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;IAiBvC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAYjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;CAoC/B"}
|