The current schema traversal mechanism copies the ArrayDeque with all path specs and traverse specs. This creates huge allocations that are immediately garbage collected. The problem is acute in services like voyager-api where the anti-abuse filter uses this mechanism to traverse all schemas referenced directly by any rest.li resource. A sample JFR for example showed 124GB of allocs in ~3 minutes, which caused service startup performance to be materially affected.
This PR optimizes this mechanism by maintaining a single ArrayList internally and using integer limits to keep track of position in the list. It also changes the return type to List instead of ArrayDeque and returns an immutable list to avoid callers from modifying it.
The current schema traversal mechanism copies the ArrayDeque with all path specs and traverse specs. This creates huge allocations that are immediately garbage collected. The problem is acute in services like voyager-api where the anti-abuse filter uses this mechanism to traverse all schemas referenced directly by any rest.li resource. A sample JFR for example showed 124GB of allocs in ~3 minutes, which caused service startup performance to be materially affected.
This PR optimizes this mechanism by maintaining a single ArrayList internally and using integer limits to keep track of position in the list. It also changes the return type to List instead of ArrayDeque and returns an immutable list to avoid callers from modifying it.