I have a simple Contact trigger in a sandbox org that is exhibiting some serious performance issues. After doing some debugging it looks like the issue boils down to accessing the items inside Trigger.new
list. I mean literally just doing o = Trigger.new[i]
appears to be really slow.
For example, this code runs reasonably quickly (processing 1000 updates in about 30 seconds):
trigger MyTrigger on Contact (after insert, after update, before delete) {
if (Trigger.isUpdate) {
for (Integer i = 0; i < Trigger.new.size(); i++) {
Integer dummy = 0;
}
}
}
Results from bulk data load (coming from the bulk job details page):
Total Processing Time (ms): 29370
API Active Processing Time (ms): 27229
Apex Processing Time (ms): 28852
However, this code takes about six minutes to run:
trigger MyTrigger on Contact (after insert, after update, before delete) {
if (Trigger.isUpdate) {
for (Integer i = 0; i < Trigger.new.size(); i++) {
SObject o = Trigger.new[i];
}
}
}
Results from bulk data load:
Total Processing Time (ms): 321264
API Active Processing Time (ms): 319187
Apex Processing Time (ms): 893650
If I record the time required to execute SObject o = Trigger.new[i]
using System.currentTimeMillis()
I see a lot of times around 400 milliseconds.
What's going on here? Does it really take that long to access an element in a list? Is there any way around this? I thought maybe I could convert it to an actual array but apparently toArray()
is not a method that the Salesforce version of List
supports.
I also find it odd the the Apex Processing Time
value is greater than the Total Processing Time
value but maybe that's a separate issue.
Update 1
This is pure speculation, but this org has a lot of customizations on the Contact record, including several formula fields. I'm wondering if, as a performance optimization, you aren't working with a "live" Contact record in the trigger until you access it from the Trigger.new
list. Maybe it's taking a while to pull the Contact record out of Salesforce's database and compute all the formula fields on the fly. Just a theory...
Update 2
Somebody suggested that I try this:
trigger MyTrigger on Contact (after insert, after update, before delete) {
if (Trigger.isUpdate) {
for (Integer i = 0; i < Trigger.new.size(); i++) {
if (Trigger.new[i] == null) {
}
}
}
}
So the code is still access the List
it's just not assigning it to anything. Doing this does address the performance issue (though it's not useful code). Not 100% sure why that is, something about the assignment to a variable is causing the issue. Maybe a copy of some sort is occurring? Anyway, it's another data point.