Skip to content

Refactor utility functions for performance and maintainability#1

Merged
rjrodger merged 2 commits into
mainfrom
claude/analyze-performance-issues-yTg0K
Mar 24, 2026
Merged

Refactor utility functions for performance and maintainability#1
rjrodger merged 2 commits into
mainfrom
claude/analyze-performance-issues-yTg0K

Conversation

@rjrodger

Copy link
Copy Markdown
Contributor

Summary

This PR refactors several utility functions in src/util.ts to improve performance, code clarity, and maintainability. The changes focus on optimizing recursive operations, replacing array lookups with Set-based checks, and improving the circular reference detection algorithm.

Key Changes

  • Refactored dive() function: Extracted the recursive logic into a new diveInternal() helper function that uses an explicit prefix array parameter instead of manipulating array indices. This eliminates the need for unshift() operations and reduces array allocations.

  • Added hasOwnKeys() utility: Introduced a new helper function to check if an object has enumerable properties, replacing the Object.keys(child).length === 0 check for better performance.

  • Optimized order_sort() function: Converted key_order array lookups to use a Set for O(1) lookup performance instead of O(n) array includes checks.

  • Optimized order_exclude() and order_include() functions: Replaced Array.includes() calls with Set.has() for better performance when filtering items.

  • Improved decircular() function: Refactored to use a shared path array that is mutated during traversal (with push/pop) instead of creating new arrays at each recursion level. This reduces memory allocations and improves performance for deeply nested objects.

  • Minor fix in entity() function: Changed Object.entries().map() to Object.entries().forEach() since the return value was not being used.

  • Added comprehensive tests: Added test cases for stringify() and decircular() functions to ensure correctness of the refactored code.

Implementation Details

The diveInternal() refactoring maintains the same behavior while improving efficiency by:

  • Passing the accumulated path as a parameter instead of reconstructing it
  • Using a for-of loop instead of reduce for better readability
  • Avoiding array mutations on the result paths

The decircular() optimization uses a closure-scoped path array that is mutated during traversal, significantly reducing garbage collection pressure for large object graphs.

https://claude.ai/code/session_017xSbcASVkxy5qHKKzn7kKi

claude added 2 commits March 24, 2026 15:30
- Refactor dive() to build paths top-down, eliminating O(n) unshift in
  recursion and stack-overflow-prone spread push on large arrays
- Refactor decircular() to use mutable push/pop path instead of creating
  new arrays per key per recursion level
- Convert .includes() to Set.has() in order_sort/exclude/include for
  O(1) lookups instead of O(n*m)
- Change entity() .map() to .forEach() to avoid throwaway array allocation
- Add tests for stringify() and decircular()

https://claude.ai/code/session_017xSbcASVkxy5qHKKzn7kKi
@rjrodger rjrodger merged commit 54ec603 into main Mar 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants