Closed txshtkckr closed 3 months ago
JProfiler "Hot Spots" analysis showing it taking 50% of the CPU time in the test I ran.
Another snapshot taken with that change in place. Hashing cost drops dramatically:
Thanks for reporting the issue, analysis and fix.
While profiling the validator locally, I found that a non-trivial amount of time was spent calculating hash codes for JsonNodePath objects. This is comparatively expensive for longer paths because it has to recurse the linked list of parents back to the root, incorporating all of their values at each step. One way to improve this is to adopt the same space/time trade-off that the String class uses, which is to cache non-
0
hash values in a non-volatile
field to optimistically skip recalculating what should be a stable value. In theString
class, we see that pattern done like this:This is thread-safe in spite of the variable not being marked
volatile
because the value is calculated deterministically from immutable state. If we are unlucky and the0
value is seen due to the unsafe publishing of the calculated value, we just pay the price of recalculating it, a penalty which will typically be seen at most once per thread and worthwhile to skipvolatile
access. ForJsonNodePath
, the equivalent code looks like this:Note: Including the
parent != null
check is possible and probably okay. I didn't do it because it would change the current hash value of a root path, which currently depends ontype
, to0
for all root paths regardless oftype
.