Background
Currently GreasedLineMesh._setPoints allocates many buffers for each new TypedArray call, there is even memory allocation in loop, this preallocated the buffer needed to reduce memory pressure.
Proposed change
Note that this is not benchmarked yet.
diff --git a/packages/dev/core/src/Meshes/GreasedLine/greasedLineMesh.ts b/packages/dev/core/src/Meshes/GreasedLine/greasedLineMesh.ts
index e6e0a5fecb..dc456c83a9 100644
--- a/packages/dev/core/src/Meshes/GreasedLine/greasedLineMesh.ts
+++ b/packages/dev/core/src/Meshes/GreasedLine/greasedLineMesh.ts
@@ -93,19 +93,28 @@ export class GreasedLineMesh extends GreasedLineBaseMesh {
let vertexPositionsLen = 0,
indicesLength = 0,
uvLength = 0,
- previousAndSideLength = 0;
+ previousAndSideLength = 0,
+ maxLineLength = 0;
for (const p of points) {
+ maxLineLength = Math.max(p.length, maxLineLength);
vertexPositionsLen += p.length * 2;
indicesLength += (p.length - 3) * 2;
uvLength += (p.length * 4) / 3;
previousAndSideLength += (p.length * 8) / 3;
}
- const vertexPositionsArr = new Float32Array(vertexPositionsLen);
- const indicesArr = vertexPositionsLen > 65535 ? new Uint32Array(indicesLength) : new Uint16Array(indicesLength);
- const uvArr = new Float32Array(uvLength);
- const previousAndSide = new Float32Array(previousAndSideLength);
+ const buffer = new ArrayBuffer(vertexPositionsLen * 4 + indicesLength * (vertexPositionsLen > 65535 ? 4 : 2) + uvLength * 4 + previousAndSideLength * 4 * 2);
+ const tempBuffer = new ArrayBuffer((maxLineLength / 3 + maxLineLength * 4) * 4);
+ let byteOffset = 0;
+ const vertexPositionsArr = new Float32Array(buffer, byteOffset, vertexPositionsLen);
+ byteOffset += vertexPositionsArr.byteLength;
+ const indicesArr = vertexPositionsLen > 65535 ? new Uint32Array(buffer, byteOffset, indicesLength) : new Uint16Array(buffer, byteOffset, indicesLength);
+ byteOffset += indicesArr.byteLength;
+ const uvArr = new Float32Array(buffer, byteOffset, uvLength);
+ byteOffset += uvArr.byteLength;
+ const previousAndSide = new Float32Array(buffer, byteOffset, previousAndSideLength);
+ byteOffset += previousAndSide.byteLength;
// it's the same length here
- const nextAndCounters = new Float32Array(previousAndSideLength);
+ const nextAndCounters = new Float32Array(buffer, byteOffset, previousAndSideLength);
let vertexPositionsOffset = 0,
indicesOffset = 0,
uvOffset = 0,
@@ -113,7 +122,7 @@ export class GreasedLineMesh extends GreasedLineBaseMesh {
nextAndCountersOffset = 0;
for (const p of points) {
- const lengthArray = GreasedLineTools.GetLineLengthArray(p);
+ const lengthArray = GreasedLineTools.GetLineLengthArray(p, tempBuffer);
const totalLength = lengthArray[lengthArray.length - 1];
for (let j = 0, jj = 0; jj < p.length; j++, jj += 3) {
const baseOffset = vertexPositionsOffset + jj * 2;
@@ -142,8 +151,10 @@ export class GreasedLineMesh extends GreasedLineBaseMesh {
vertexPositionsOffset += currVertexPositionsOffsetLength;
indicesOffset += (p.length - 3) * 2;
- const previous = new Float32Array(positions.length);
- const next = new Float32Array(positions.length);
+ let byteOffset = lengthArray.byteLength;
+ const previous = new Float32Array(tempBuffer, byteOffset, positions.length);
+ byteOffset += previous.byteLength;
+ const next = new Float32Array(tempBuffer, byteOffset, positions.length);
const l = positions.length / 6;
let v;
if (GreasedLineMesh._CompareV3(0, l - 1, positions)) {
diff --git a/packages/dev/core/src/Misc/greasedLineTools.ts b/packages/dev/core/src/Misc/greasedLineTools.ts
index 2fdbc9a6cc..a05130198f 100644
--- a/packages/dev/core/src/Misc/greasedLineTools.ts
+++ b/packages/dev/core/src/Misc/greasedLineTools.ts
@@ -270,10 +270,11 @@ export class GreasedLineTools {
/**
* Gets the the length from the beginning to each point of the line as array.
* @param data array of line points
+ * @param buf optional pre-allocated buffer to reduce memory pressure
* @returns length array of the line
*/
- public static GetLineLengthArray(data: number[]): Float32Array {
- const out = new Float32Array(data.length / 3);
+ public static GetLineLengthArray(data: number[], buf?: ArrayBuffer): Float32Array {
+ const out = buf ? new Float32Array(buf, 0, data.length / 3) : new Float32Array(data.length / 3);
let length = 0;
for (let index = 0, pointsLength = data.length / 3 - 1; index < pointsLength; index++) {
let x = data[index * 3 + 0];
Testing
Just copy-paste code after const {GreasedLineTools, GreasedLineMesh} = BABYLON;
to any playground to test it.