You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Incremental performance improvements targeting hot paths in the vehicle/entity systems and pathfinding:
gridFinders.ts: Convert SPORTS_TYPES, RELAXATION_TYPES, ACTIVE_RECREATION_TYPES, and ENTERABLE_BUILDING_TYPES from arrays to Sets for O(1) .has() lookups instead of O(n) .includes(). Backward-compatible array exports are preserved.
utils.ts: Fix O(n²) BFS path reconstruction in findPathOnRoads — previously stored parent coordinates and did a linear search to find the parent's queue index on each step. Now stores the parent queue index directly (BFS_PARENT_IDX), making reconstruction O(path length).
vehicleSystems.ts:
Replace forEach with for loops in drawCars, drawBuses, drawEmergencyVehicles to avoid closure allocation per entity per frame.
Remove [...array] spread copies in updateCars and updateBuses — iterate the original ref array directly.
Add viewport culling to drawCars (was missing; buses/emergency vehicles already had it).
Hoist skipTypes array in isVehicleBehindBuilding to a module-level VEHICLE_SKIP_BUILDING_TYPES Set to avoid re-allocation every call.
Review & Testing Checklist for Human
Verify drawCars viewport culling margin (20px) is sufficient. Buses use 60/80px and emergency vehicles use 40/60px margins. Cars are smaller, but check that cars near the viewport edge don't visibly pop in/out during panning.
Verify updateCars/updateBuses direct iteration is safe. The spread copy was removed — confirm no code path during the loop body modifies carsRef.current or busesRef.current itself (adding/removing elements). Mutating individual car/bus properties is fine.
Test pathfinding still works correctly — place buildings far apart, verify emergency vehicles and buses can still navigate to them. The BFS reconstruction change is the most algorithmically significant edit.
Visual smoke test — play the game for a few minutes at various zoom levels. Confirm all vehicle types (cars, buses, emergency vehicles) render correctly and no entities disappear unexpectedly.
Notes
All pre-existing lint errors/warnings are unchanged (19 errors, 12 warnings — none introduced by this PR).
The SPORTS_TYPES, RELAXATION_TYPES, ACTIVE_RECREATION_TYPES array exports are kept for backward compatibility in case external consumers iterate them.
Improves simulation performance by speeding up hot paths in pathfinding and vehicle rendering. Uses Set lookups, reduces per-frame allocations, and makes BFS path reconstruction O(path length).
Performance
Converted recreation/enterable building arrays to Sets for O(1) .has() checks; kept array exports for iteration.
Made BFS path reconstruction O(path length) by storing the parent queue index instead of coordinates.
Reduced per-frame allocations in vehicle systems by replacing forEach with for loops and iterating original arrays (no spread copies).
Added viewport culling to drawCars (20px margin) and hoisted occlusion skip types to a module-level Set.
Written for commit 26557e5. Summary will update on new commits.
- vehicleSystems.ts: Replace forEach with for loops to avoid closure allocation per iteration
- vehicleSystems.ts: Remove array spread copies in updateCars/updateBuses (iterate directly)
- vehicleSystems.ts: Add viewport culling to drawCars to skip off-screen vehicles
- vehicleSystems.ts: Use module-level VEHICLE_SKIP_BUILDING_TYPES Set for occlusion checks
- gridFinders.ts: Convert SPORTS_TYPES, RELAXATION_TYPES, ACTIVE_RECREATION_TYPES, ENTERABLE_BUILDING_TYPES to Sets for O(1) lookups
- utils.ts: Fix O(n²) BFS path reconstruction by storing parent queue index directly instead of parent coordinates
Co-Authored-By: Andrew Milich <milichab@gmail.com>
We reviewed changes in 50f5e1d...26557e5 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
The reason will be displayed to describe this comment to others. Learn more.
Unexpected function declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable
It is considered a best practice to avoid 'polluting' the global scope with variables that are intended to be local to the script. Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior. It is mostly useful for browser scripts.
The reason will be displayed to describe this comment to others. Learn more.
Unexpected function declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable
It is considered a best practice to avoid 'polluting' the global scope with variables that are intended to be local to the script. Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior. It is mostly useful for browser scripts.
The reason will be displayed to describe this comment to others. Learn more.
Unexpected function declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable
It is considered a best practice to avoid 'polluting' the global scope with variables that are intended to be local to the script. Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior. It is mostly useful for browser scripts.
The reason will be displayed to describe this comment to others. Learn more.
Variable name is too small
Short variable names affect code readability and complicate code refactoring, because of the difficulty in searching and replacing such short characters.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Incremental performance improvements targeting hot paths in the vehicle/entity systems and pathfinding:
SPORTS_TYPES,RELAXATION_TYPES,ACTIVE_RECREATION_TYPES, andENTERABLE_BUILDING_TYPESfrom arrays to Sets for O(1).has()lookups instead of O(n).includes(). Backward-compatible array exports are preserved.findPathOnRoads— previously stored parent coordinates and did a linear search to find the parent's queue index on each step. Now stores the parent queue index directly (BFS_PARENT_IDX), making reconstruction O(path length).forEachwithforloops indrawCars,drawBuses,drawEmergencyVehiclesto avoid closure allocation per entity per frame.[...array]spread copies inupdateCarsandupdateBuses— iterate the original ref array directly.drawCars(was missing; buses/emergency vehicles already had it).skipTypesarray inisVehicleBehindBuildingto a module-levelVEHICLE_SKIP_BUILDING_TYPESSet to avoid re-allocation every call.Review & Testing Checklist for Human
drawCarsviewport culling margin (20px) is sufficient. Buses use 60/80px and emergency vehicles use 40/60px margins. Cars are smaller, but check that cars near the viewport edge don't visibly pop in/out during panning.updateCars/updateBusesdirect iteration is safe. The spread copy was removed — confirm no code path during the loop body modifiescarsRef.currentorbusesRef.currentitself (adding/removing elements). Mutating individual car/bus properties is fine.Notes
SPORTS_TYPES,RELAXATION_TYPES,ACTIVE_RECREATION_TYPESarray exports are kept for backward compatibility in case external consumers iterate them.Link to Devin session: https://app.devin.ai/sessions/0ac3bedf903a4d1b8a552966e05e346a
Requested by: @amilich
Summary by cubic
Improves simulation performance by speeding up hot paths in pathfinding and vehicle rendering. Uses Set lookups, reduces per-frame allocations, and makes BFS path reconstruction O(path length).
.has()checks; kept array exports for iteration.forEachwithforloops and iterating original arrays (no spread copies).drawCars(20px margin) and hoisted occlusion skip types to a module-levelSet.Written for commit 26557e5. Summary will update on new commits.