As mentioned in a prior blog post, we have eliminated the highly unloved script statement limit. As a general rule, this will allow you to run more logic within a single transaction. I hope you are all getting used to your larger digs and trying to figure out what you are going to do with all those extra statements.
One of the benefits to going away from statement counting is a performance lift. We don’t need to do that pesky “i++” call after every single statement. While incrementing a counter isn’t very expensive, it’s non-zero, and it’s multiplied by the billions every single day here in the cloud. Less overhead means faster execution.
The Loose End
This leaves us with one loose end – Limits.getScriptStatements().
Some of you have never heard of this. If that’s you, you’re in the clear! Feel free to return to cranking out awesome Apex code.
Others of you may have used this in your code as a backstop against hitting the ole’ statement limit. Perhaps you wrote something like this:
This is nice-looking code! It served a valid purpose, and served it well. It’s also no longer going to do what it used to do.
As I mentioned, we are no longer counting script statements, because that was taking up actual time and it is no longer used by us internally. As such, the Limit.getScriptStatements() method is undefined.
What Should We Say?
We had to return some value for this method, despite it being undefined. This is because you’ve used it in your nice-looking code, and we want it to compile. We had two good options for a return value for this method: we could return zero, or we could return MAX_INT.
Returning zero was a bad option. Let’s say your nice-looking code looked like this instead:
This code is as pretty as the code above, and it will now also not work. However, if we chose to return zero for the limit call, this loop would be like that Titanic song: it would go on and on. That song was terrible, and so is an infinite loop – you don’t want either of them to happen to you. (Note: any opinions on Celine Dion songs are my own and do not reflect Salesforce’s official stance on Celine Dion.)
The alternative is to return a value that is larger than what you thought the limit would be. This will terminate the loop earlier than you might want, but at least the code will terminate. This means less infinite looping and less load on our service and thus faster operation for everyone. However, it appears that there are places where developers have wrapped their entire code in this type of flow control. In these cases, no code is ever going to execute, causing an aging Mick Jagger to start prancing around singing “Start me up!” (Again, any opinions on an aging Mick Jagger are my own and do not reflect Salesforce’s official stance on the aging process of English rock people.)
Since returning either of these options is bad, we are going to make a change to the return value. We are going to convert your cpu usage against the limit into an equal ratio of script statements against the limit. We are essentially going to mimic the statement counting by using the cpu usage. Since the cpu timeout is our backstop that replaced script counting for service protection, this is the closest we can get to giving you a fake value that is not dangerous or terminal.
Please keep in mind that this number is not what it says it is. It is NOT the number of statements. It is a representation of what the statement count might have been, relative to your limit. It will, in nearly every situation, undercount the number of statements done. The intention with this mimicry is to allow your code to probably do what it used to do without an immediate failure.
Your Mission, Should You Choose To Accept It…
The purpose of this clever hack is to buy you a little time. Given that the method’s return value is wrong, and isn’t what you think it is, you should look through your code and do your best to remove calls to this statement. I can’t fix your code for you – there is too much of it!! But I trust you to do the needful.
You can still do flow control in a very similar way! We have replaced script statement counting with a CPU timeout, so you can track towards that instead of towards statements. The flow control that I first mentioned could very quickly be rewritten as follows:
In the end, regardless of what we chose, you are going to look at your code and say, “Dang, I don’t need this anymore, let me get rid of this!” Or perhaps, “Dang, I should be doing the same thing, but checking the CPU timer!” Or even, “Dang, that is some good-looking code!” Either way, you will be safer removing the call to the getScriptStatements method and replacing it with whatever is relevant to your custom logic.