Skip to content

Optimization: Improve JSONParse Big O Efficiency #8

@Sam-Cousins-WEX

Description

@Sam-Cousins-WEX

JSONParse.java
JSONParseOptimised.java
JSONParsePerformanceTest.java

Problem Description

The JSONParse library's get() and exists() methods currently have a time complexity of O(D * N), where D is the depth of the path and N is the number of children per node.

This inefficiency arises because at each step of the path traversal, the code calls asMap() or asList(). These methods iterate over all children of the current node and wrap them in new JSONParse instances, even though only one specific child is needed for the next step.

For large JSON objects or arrays (e.g., 2,000+ items), this results in significant CPU overhead and can easily hit Apex CPU limits.

Proposed Solution

Optimize the get() and exists() methods to access the underlying Map<String, Object> or List<Object> directly.

  • Instead of wrapping all siblings, we only instantiate a JSONParse wrapper for the specific target child needed for the next step.
  • This reduces the time complexity to O(D) (linear with respect to path depth, constant with respect to number of siblings).

Changes Implemented

JSONParse.cls

  • get(String path):

    • Removed calls to asMap() and asList().
    • Added direct casting of value to Map<String, Object> or List<Object>.
    • Implemented direct lookup: currentNode = new JSONParse(currentMap.get(key)) or currentList.get(index).
    • Preserved all original exception handling (NotAnArrayException, NotAnObjectException, MissingKeyException, ListException).
  • exists(String path, Boolean notNull):

    • Applied similar optimizations to avoid unnecessary wrapping during existence checks.

Verification & Performance Results

Functional Correctness

Existing unit tests in JSONParseTests.cls pass, confirming that the optimization preserves all functional behavior and exception handling contracts.

Performance Benchmarks

A new test class JSONParsePerformanceTest.cls was created to compare the original implementation against the optimized one.

Test Setup:

  • Data: JSON Object/Array with 2,000 items.
  • Iterations: 200 get() calls.
  • Comparison: JSONParse (Old) vs. JSONParseOptimised (New).

Results:

Scenario Pattern Result
Large Object Varying Keys 295.5x Faster (5023ms vs 17ms)
Large Object Same Key 377.4x Faster (6038ms vs 16ms)
Large Array Varying Indices 238.4x Faster (4052ms vs 17ms)
Large Array Same Index 376.5x Faster (4142ms vs 11ms)

Artifacts

  • JSONParse.cls: Original implementation.
  • JSONParseOptimised.cls: Copy of optimized implementation for side-by-side testing.
  • JSONParsePerformanceTest.cls: Benchmark tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions