Professional Documents
Culture Documents
Performance Profiling in Salesforce
Performance Profiling in Salesforce
Profiling in Force.com
In this guide, you can learn about both the Force.com performance profiling tools
and their associated methodologies, which have been informed by recommendations
from salesforce.com Customer Support and our own engineering teams. For
example, along with using functional unit testing to verify that your application is
working as designed, salesforce.com recommends using performance profiling so
that your application can handle the volumes of data and the complex sharing
configurations that might grow along with the size and success of your organization.
If you’re a Force.com architect or developer, or an experienced Salesforce
administrator, then these kinds of tips can help you properly code your application
and maximize the value that it delivers to your users.
Note: This guide is intended for readers who have experience coding Apex and
Visualforce, and who have a basic understanding of the Force.com multitenant
architecture.
Debug logs
A debug log records database operations, system processes, and errors that occur
when you execute a transaction. The system generates a debug log for a user every
time that user executes a transaction that is included in the filter criteria. The level of
detail each log contains can be adjusted. Although the debug log files appear as
plain text, it is difficult to interpret their raw log lines. This guide shows you how to
use the Developer Console to analyze those lines effectively while performance
profiling.
Workbench
Workbench is a powerful, Web-based suite of tools available from the Developer
Force community. Designed for administrators and developers, this tool allows you
to describe, query, manipulate, and migrate both data and metadata in
salesforce.com organizations directly in their Web browser interface. Workbench
also provides many advanced features for testing and troubleshooting the Force.com
APIs. This guide uses Workbench to demonstrate how you can easily run queries
through the API and get the information you need for performance profiling.
1. Define the scope of the task. Split business scenarios into a subset of
operations, functionalities or simply by pages.
2. For each task, measure the performance of the application (e.g., a Visualforce
page) and identify potential bottlenecks.
Iterate on the performance profiling steps with larger data volumes and with users
who have various different sharing settings so that you can gauge performance
impacts as comprehensively as possible.
<apex:column headerValue="Stage
4
Name" value="{!ar.StageName}"/>
<apex:column headerValue="Total
5
Amount" value="{!ar.Amount}"/>
<apex:column headerValue="Number of
6
Orders" value="{!ar.Total}"/>
7 </apex:pageBlockTable>
8 </apex:pageBlock>
9 </apex:page>
02 {
0
4 public salesAggregate()
05 {
07 FROM Opportunity
10 GROUP BY StageName
11 ];
12 }
14 {
19 lstResult.add(objOppAgg);
20 }
21 return lstResult;
22 }
23 class OppAgg
24 {
30 Total = (Integer)ar.get('Total');
31 StageName = (String)ar.get('StageName');
32 Amount = (Decimal)ar.get('Amount');
33 }
34 }
35 }
In different cases, you might also see that the Visualforce page is taking a long time
to render. If you ever have this type of transaction, identify coding anti-patterns by
referring to Best Practices for Improving Visualforce Performance, which has a list of
Visualforce performance pitfalls that many of our customers fall into.
Step 2: Identify what the executed event is doing.
Once you’ve identified that the database event is taking a significant amount of the
overall request time, the next step is to identify what this transaction is doing. Open
the Execution Log panel and select “Filter” to get the information needed to identify
the bottleneck(s). For this example, filter by Category to show only events related to
“DB,” as shown in this screenshot.
Tip: You can customize the Execution Log panel’s columns by hovering over any of
the existing columns and clicking the small pull-down icon, as shown below.
Because this example is very simple, you can see only a few log lines, the top of
which shows the SOQL SELECT statement being executed, and the last of which
shows the resulting row count. You have now identified a SOQL statement that
needs to be reviewed and tuned.
Note: If you have multiple log lines, you can use the timestamp to identify the lines
that align with the timeline you are focusing on. You can also follow the next step to
evaluate the duration of each request.
Step 3: Review performance benchmarks.
From the Stack Tree panel, click the Performance Tree tab and expand the tree.
This tab will give you a breakdown of the corresponding duration in milliseconds, the
heap size, and the iterations for each component executed for your request. If you
have multiple units, work your way down your list, starting with the event that has the
longest duration.
Tip: By clicking the unit that appears to cause the bottleneck (have the longest
duration) on the Performance Tree tab, you can automatically apply a filter to the
Execution Log and spot the gap in timestamps. Disable the filter and look at the
events that fall in this gap.
Looking at the statistics shown in the Performance Tree, verify that they match what
appears in the Execution Log. Then take a note of the duration, heap size, and
number of iterations. Use these metrics as benchmarks for both the tests that you
run with different conditions and the tests that you run after tuning your Visualforce
code.
Step 4: Test for scale.
Repeat the same steps with larger volumes of data and with different users (e.g., a
user with limited data visibility vs. an administrator with access to all data).
Once you start adding tens of thousands of records, you might discover that the
execution duration becomes longer. (The previous sample code would eventually hit
governor limits, such as “System.LimitException: Too many query rows: 50001.”) By
using the Developer Console, you can inspect how close you are to hitting various
Force.com governor limits—or how far over those limits you already are. The
following example shows some limit-related Visualforce errors that you might
receive.
Now you have discovered that you need to add logic, such as pagination or filtering,
to your application to handle larger sets of data and to ultimately provide your users
with good performance experience.
Look for large number of soft-deleted rows and purge them to achieve optimal query
performance. (Also refer to Best Practices for Deployments with Large Data
Volumes and the Large Data Volumes Trailhead module.)
Note: You can also refer to the Storage Usage menu to look at the objects’ record
counts. (From Setup, click Manage Users | Users.) However, this page is processed
asynchronously. If you add or delete large number of records, the change might not
be immediately reflected in this page. Even more importantly, the data does not
reflect soft-deleted rows. When profiling performance, including the number of soft-
deleted rows in your base record count is important, as these rows can affect query
performance.
Step 6: Assess the selectivity of your query.
To profile the selectivity of each filtering condition, break up your WHERE clause and
run SELECT count() queries for each filter, as the figure above demonstrates. For
AND operators, combine the filters and assess selectivity of your query. For OR
operators, you must assess each filter’s selectivity separately. Make sure that you
have indexed the selective fields, and that you are following best practices for taking
full advantage of the Force.com query optimizer. If the query takes a very long time
or times out, this indicates that you have a performance bottleneck. To learn more
about the Force.com query optimizer, read this blog post and watch this webinar. To
learn more about its selectivity thresholds, see the Database Query & Search
Optimization Cheat Sheet.
• The use of indexes. For performance profiling at the query level, you cannot
determine if your SOQL request actually uses an index or not. However, you
can test and see how the query performs without the index by swapping your
query with a custom field that does not have any custom index on it. Once you
get your query’s baseline performance, you can create an index on that custom
field or switch back to the original field that has an index to evaluate the index’s
effects.
Next steps
The previous profiling steps can help you identify and evaluate the performance
bottlenecks of your application. It may require multiple iterations and you might also
need additional help to make your application perform and scale so that it meets
your business needs.
Salesforce.com Customer Support and our engineering team are equipped with tools
and standard processes that can add more insight to your performance profiling. For
example, if you discover that you do not see any application performance
improvements even after you hard-delete your records, you might want to request
salesforce.com Customer Support for a physical delete.
You can also go through salesforce.com Customer Support to reach our engineering
team, who can give you a Force.com query optimizer analysis. Based on the results
of the analysis, the team might suggest using selective filters and creating custom
indexes. The team can also analyze database-level statistics and possible create
skinny tables.
Note: To take advantage of these services, you must qualify for developer support.
Summary
Debug logs, the Developer Console, and Workbench are tools that you can use to
proactively identify performance bottlenecks and compare test results.
Understanding best practices for optimizing performance is important—but when
you’re trying to build scalable, well-performing applications—applying those best
practices in your implementation is even more important.
Related resources
• Apex Testing on Trailhead
• Workbench