Project

General

Profile

Bug #7088

Lazily initialize activeBundle inside RandomAccessQuery

Added by Alexandru Lungu over 3 years ago. Updated over 3 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
reviewer:
production:
No
env_name:
topics:

History

#1 Updated by Alexandru Lungu over 3 years ago

There is relevant activity when building an activeBundle in general, mostly related to FQL composition (createBundle, buildSortClause, preprocessWhere).

RandomAccessQuery.execute uses the ffCache (if exists) when the bundle key is FIRST, LAST or UNIQUE (+ other safety conditions). In the best case, we have a cache hit and we can retrieve the record from the session cache or hydrate. Therefore, I don't see any usage of activeBundle in this case, so we can avoid the creation of the FQLs if we can resolve the query through ffCache.

It may be safe to retrieve activeBundle through a getter which lazily sets it depending on the activeBundleKey. This way, it will be set only when needed. Furthermore, activating (e.g. using activateLast), activeBundle can be set on null to suggest the fact that it should be reassigned.

This way, having a ffCache for a RandomAccessQuery converted from a stand-alone FIND FIRST tt WHERE [...] can bypass the creation of activeBundle altogether.

#2 Updated by Eric Faulhaber over 3 years ago

This makes sense. Although the cost currently is mitigated to some degree by caching in FQLHelper, there is still work to create a key, check the cache, do some substitution parameter processing, etc. So, I agree with your premise. In terms of prioritizing this work, are you finding this is a hotspot?

#3 Updated by Alexandru Lungu over 3 years ago

I've done a slim test with ~40,000 find queries. ~13.000 of them used ffCache. The total time spent on activation was 8ms (out of which 2ms were spent for the finds resolved by ffCache). This makes this the optimization look very weak.

Eric Faulhaber wrote:

This makes sense. Although the cost currently is mitigated to some degree by caching in FQLHelper, there is still work to create a key, check the cache, do some substitution parameter processing, etc. So, I agree with your premise. In terms of prioritizing this work, are you finding this is a hotspot?

I was not hoping just to avoid the FQLHelper cache look-up and bundle building, but to avoid the whole helper and FQLPreprocessor work. Simply doing a lazy activeBundle initialization is not enough. Most of the important API of RAQ (first, unique, last, next, previous) require the helper before using the ffCache.

Now I realize that this task should have covered a larger scope: "avoid any FQL work (preprocessing) if ffCache is to be used". This is achievable as most (or even all) of the getHelper calls are used for very specific isolated use-cases:
  • all RAQ API check getHelper().getFQLPreprocessor().isFindByRowid() to eventually transform into unique (maybe it can be refactored? or delayed?)
  • initialize uses getHelper().getFQLPreprocessor().isFindByRowid() to do logging (can be omitted)
  • unique uses getHelper() to check isFindTemplate or fqlPreprocessor.getFindByRowid(values) < 0 (very rare cases)
  • ffCache uses where string inside the cache key. However, it also retrieves the query properties (from the helper) for the cache key: is this part of lazy-hydration? can we make ffCache purely independent upon the helper?

Having all that ~13.000 fast-find queries avoid any FQL work should result in more that 2ms performance increase.

Also available in: Atom PDF