make it faster (webassembly) #5
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#5
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
now its little bit too slow
remarks
remark 2
Performance Analysis & Improvement Strategy
After thorough analysis of the codebase, here are the identified bottlenecks and the implementation plan:
Identified Bottlenecks
1. Grid Rendering (canvas.js:46-82) — HIGH IMPACT
drawGrid()creates individualKonva.Circlenodes for every dot. At 8K resolution (7680x4320) with GRID_SIZE=20, that's potentially ~83,000 circle nodes being created, destroyed, and redrawn on every zoom/pan/resize.gridLayer.destroyChildren()+ recreate on every call — GC pressure.2. No Viewport Culling (objects.js / app.js) — HIGH IMPACT
object.listloads ALL board objects from SQLite and renders ALL of them as Konva nodes regardless of viewport.3. Full Board Sync (sync.js:547-616) — MEDIUM-HIGH IMPACT
syncFromServer()fetches ALL objects viaobject.list, then iterates ALL local objects to reconcile.saveAll()serializes ALL objects and sends one giantobject.batch_update.object.batch_updatehandler (object.rs:126-196) locks the Mutex and does a SELECT+UPDATE per object (N+1 query pattern).4. SQLite Single Mutex (main.rs:16-17) — MEDIUM IMPACT
pub db: std::sync::Mutex<rusqlite::Connection>— single connection, synchronous lock.batch_updateholds the lock for the entire loop of N objects with N SELECT + N UPDATE queries.5. WebSocket Message Volume (sync.js / ws.rs) — MEDIUM IMPACT
6. Connector Re-computation (connectors.js) — LOW-MEDIUM IMPACT
dragmoveandtransformlisteners on both endpoints.closestAnchor()does 16 distance comparisons per connector per frame.getAnchorPoints()callsgetAbsolutePosition()+ coordinate transforms each time.Implementation Plan (Priority Order)
Phase 1: Grid Performance (immediate, biggest visual impact)
sceneFuncthat draws dots directly on the 2D canvas context.Phase 2: Viewport Culling
Phase 3: Delta Sync
object.list_sinceRPC method that accepts a timestamp and returns only changed objects.saveAll()to only send dirty objects.updated_atindex for efficient filtered queries.Phase 4: SQLite Connection Pool + Transaction Batching
Mutex<Connection>withr2d2_sqliteconnection pool.batch_updatein a SQLite transaction.UPDATE ... SET ... WHERE id = ?without re-reading each object (partial updates).Phase 5: WebSocket Optimization
Starting implementation on branch
development_5.Implementation Progress — Performance Improvements
Branch:
development_5| Commit:ed01544Changes Made
1. Grid Rendering (~83K nodes → 1 node)
Konva.Circlenodes for each grid dot with a single customKonva.ShapeusingsceneFuncbeginPath()/fill()call2. Viewport Culling & Debounced Redraws
requestAnimationFrame— only redraws when viewport actually changesisInViewport(x, y, w, h)helper for future object-level cullingonViewportChange()listener system for modules that need viewport-aware behavior3. WebSocket Message Batching
{type:'batch', messages:[...]}messages instead of N individual sends4. Remote Cursor Presence
5. SQLite Transaction Batching
batch_updatehandler now wraps all updates in a singleBEGIN IMMEDIATE/COMMIT/ROLLBACKtransactionpartial_update_object()function usingCOALESCEfor efficient partial updates without re-reading each object (eliminates N SELECTs)Files Changed
canvas.js— grid rendering, viewport trackingsync.js— WS batching, cursor presence, image serializationqueries.rs—partial_update_object()with COALESCEobject.rs— transaction-wrapped batch_updateRemaining Opportunities