From 08ba8a7687be2405970c1e0b48ef38a40c09e8c5 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Thu, 11 Jan 2024 01:56:28 +0300 Subject: [PATCH] Fix GC pauses! --- README.md | 3 ++ client/index.html | 32 +++++++-------- client/webgl_geometry.js | 88 ++++++++++++++++++++++++---------------- 3 files changed, 73 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 39782fd..26378f7 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Release: - Textured quads (pictures, code already written in older version) - Resize and move pictures (draw handles) - Further investigate GC pauses in Firefox + * Bugs + + GC stalls!!! + - Stroke previews get connected when drawn without panning on touch devices - Debug - Restore ability to limit event range * Listeners/events/multiplayer diff --git a/client/index.html b/client/index.html index 5f4e2c9..9e3c3b5 100644 --- a/client/index.html +++ b/client/index.html @@ -7,22 +7,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
diff --git a/client/webgl_geometry.js b/client/webgl_geometry.js index af33102..1b7a305 100644 --- a/client/webgl_geometry.js +++ b/client/webgl_geometry.js @@ -76,33 +76,18 @@ function rdp_find_max(state, zoom, stroke, start, end) { return result; } -function geometry_write_instances(state, context) { - if (state.segments_from.cap < context.clipped_indices.count + 1) { - state.segments_from.cap = round_to_pow2(context.clipped_indices.count + 1, 4096); - state.segments_from.data = new Uint32Array(state.segments_from.cap); - } - - if (state.segments.cap < state.coordinates.size / 2) { - state.segments.cap = round_to_pow2(state.coordinates.size, 4096); - state.segments.data = new Uint32Array(state.segments.cap); - } - - state.segments_from.count = 0; - state.segments.count = 0; - - state.stats.rdp_max_count = 0; - state.stats.rdp_segments = 0; - - let fast_path_count = 0; - let slow_path_count = 0; - - const stack = []; +function do_lod(state, context) { + let stack = new Array(4096); for (let i = 0; i < context.clipped_indices.count; ++i) { const stroke_index = context.clipped_indices.data[i]; const stroke = state.events[stroke_index]; const point_count = (stroke.coords_to - stroke.coords_from) / 2; + if (point_count > 4096) { + stack = new Array(round_to_pow2(point_count, 4096)); + } + // Basic CSR crap state.segments_from.data[i] = state.segments.count; @@ -113,22 +98,37 @@ function geometry_write_instances(state, context) { let segment_count = 2; state.segments.data[state.segments.count++] = 0; - - stack.length = 0; - stack.push({'type': 0, 'start': 0, 'end': point_count - 1}); - - while (stack.length > 0) { - const entry = stack.pop(); - - if (entry.type === 1) { - state.segments.data[state.segments.count++] = entry.value; + + let head = 0; + // Using stack.push() allocates even if the stack is pre-allocated! + + stack[head++] = 0; + stack[head++] = 0; + stack[head++] = point_count - 1; + + while (head > 0) { + const end = stack[--head]; + const value = start = stack[--head]; + const type = stack[--head]; + + if (type === 1) { + state.segments.data[state.segments.count++] = value; } else { - const max = rdp_find_max(state, state.canvas.zoom, stroke, entry.start, entry.end); + const max = rdp_find_max(state, state.canvas.zoom, stroke, start, end); if (max !== -1) { segment_count += 1; - stack.push({'type': 0, 'start': max, 'end': entry.end}); - stack.push({'type': 1, 'value': max}); - stack.push({'type': 0, 'start': entry.start, 'end': max}); + + stack[head++] = 0; + stack[head++] = max; + stack[head++] = end; + + stack[head++] = 1; + stack[head++] = max; + stack[head++] = -1; + + stack[head++] = 0; + stack[head++] = start; + stack[head++] = max; } } } @@ -140,6 +140,26 @@ function geometry_write_instances(state, context) { } } } +} + +function geometry_write_instances(state, context) { + if (state.segments_from.cap < context.clipped_indices.count + 1) { + state.segments_from.cap = round_to_pow2(context.clipped_indices.count + 1, 4096); + state.segments_from.data = new Uint32Array(state.segments_from.cap); + } + + if (state.segments.cap < state.coordinates.size / 2) { + state.segments.cap = round_to_pow2(state.coordinates.size, 4096); + state.segments.data = new Uint32Array(state.segments.cap); + } + + state.segments_from.count = 0; + state.segments.count = 0; + + state.stats.rdp_max_count = 0; + state.stats.rdp_segments = 0; + + do_lod(state, context); state.segments_from.data[context.clipped_indices.count] = state.segments.count; state.segments_from.count = context.clipped_indices.count + 1;