Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this class also helpful for caching DescribeFieldResults - and how? #88

Closed
rsoesemann opened this issue Oct 5, 2015 · 9 comments
Closed

Comments

@rsoesemann
Copy link
Contributor

Even if there are no describe limits in Apex anymore I realized that repeated getDescribe() is really expensive time-wise. I therefore planned to use this class to get some caching just to find out that there it only seems to care about DescribeSObject scenarios.

Is this intentional or do I get something wrong?

@afawcett
Copy link
Contributor

@capeterson is the original author.

Though i'm pretty sure it does care about caching field describes as well, or at least i thought it did?

Also, i would assume one of the reasons the limits got dropped is SF felt that such calls are now cheap enough, meaning they must have optimised it internally for us. So curious, do you have evidence that suggests its really expensive, have you profiled it?

@rsoesemann
Copy link
Contributor Author

Let's see what @capeterson answers.

Regarding Describe profiling. I have a batch that runs over many record and checks certain things for field and value. Until now I thought Describes are cheap and so I repeatedly did a getDescribe(), because there is no way to store a FieldDescribe map between batch execute()s.

This dramatically slowed down my batch and I just created a simple loop which does nothing 10.000 time and another one that does 10.000 field describes. 1sec to 12sec increase!

@krisgreene
Copy link

I too wondered about this when I switched over to piggybacking off fflib_SObjectDescribe instead of my own describe caching mechanism. Didn't see anything for caching the field results. I assumed that perhaps the platform was caching the results and it was unnecessary? Given your testing @up2go-rsoesemann it would seem to not be the case.

@afawcett
Copy link
Contributor

Yes most interesting, sounds like it might be worth adding this to the class then... @capeterson

@daveespo
Copy link
Contributor

While we were working on #105, I also spent some time profiling fflib_SObjectDescribe and agree with @up2go-rsoesemann -- describes are just plain slow

In our tests, we saw that the initial describe of an SObject (the one that fflib_SObjectDescribe caches) is erratic .. sometimes 20ms, sometimes 130ms ... and describing each field on that object costs ~0.5ms (which adds up if you're using a lot of 'wide' Selectors in your transaction)

Run #1 on NA8
06:01:38.24 (105099499)|USER_DEBUG|[75]|DEBUG|Iterations: 41
06:01:38.24 (105179754)|USER_DEBUG|[76]|DEBUG|Splits Elapsed:3
06:01:38.24 (105243558)|USER_DEBUG|[77]|DEBUG|First Describe:23
06:01:38.24 (105310440)|USER_DEBUG|[78]|DEBUG|Describe Elapsed:30

Run #2 on NA8
06:14:41.18 (89087571)|USER_DEBUG|[75]|DEBUG|Iterations: 41
06:14:41.18 (89178027)|USER_DEBUG|[76]|DEBUG|Splits Elapsed:3
06:14:41.18 (89249553)|USER_DEBUG|[77]|DEBUG|First Describe:35
06:14:41.18 (89322238)|USER_DEBUG|[78]|DEBUG|Describe Elapsed:45

Run #1 on NA9
09:20:35.18 (182266270)|USER_DEBUG|[75]|DEBUG|Iterations: 41
09:20:35.18 (182326587)|USER_DEBUG|[76]|DEBUG|Splits Elapsed:2
09:20:35.18 (182398875)|USER_DEBUG|[77]|DEBUG|First Describe:129
09:20:35.18 (182476244)|USER_DEBUG|[78]|DEBUG|Describe Elapsed:140

The code for this test is up in our SelectorPerformance test class. You can replicate the above output with

SelectorPerformance.describe()

@afawcett
Copy link
Contributor

Thanks @daveespo good confirmation, its clear we need to cache these things then here.

@daveespo
Copy link
Contributor

I don't think that I can volunteer to profile this any time soon, but I'd be curious if using Platform Cache (user session cache, not org cache) makes any improvement

For ISVs, Platform Cache is kind of a mess between allocating a partition and making sure the admin in the subscriber org allocates space for your partition .. but if the perf benefits are significant, maybe it's worth the extra manual setup

@afawcett
Copy link
Contributor

Sorry for the lag on this one....

Yeah platform cache might help, but it kind of feels like a poor solution to push the cost of this to the customer. Also if you put it in the platform cache you may run into problems getting it out in a timely fassion without impacting your users, since there are no hooks to clean the cache when admins make changes to the config. How acute this problem would be will vary of course, but could be frustrating.

How about something fflib_SObjectDescribeFactory that helps cache this per request if that helps, maybe make it pluggable to support Platform Cache backed cache rather than 'statics' if the developer wants broader caching.

wimvelzeboer added a commit to wimvelzeboer/fflib-apex-common that referenced this issue Jul 23, 2020
Note: the provided unit test will currently fail due to a bug in fflib-apex-mocks. I raise PR apex-enterprise-patterns#88 to have that fixed.
@daveespo
Copy link
Contributor

daveespo commented Jun 8, 2023

Since this issue was filed, some platform improvements were made to Describe to both address bugs and improve performance.

Additionally, if you're using native User Mode or System Mode introduced in #419 , you won't spend as many CPU cycles building the SOQL query (QueryFactory and Selectors)

Lastly, I'll say that on my day-job project, we resorted to caching the resolved SOQL query in Platform Cache in order to save some CPU cycles and it does have measurable improvement (YMMV depending on the 'width' of your Selectors and relationships traversed) -- but it's not without issues .. see #411

@daveespo daveespo closed this as not planned Won't fix, can't repro, duplicate, stale Jun 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants