ColdFusion MX Coding Guidelines - Appendix: Performance Techniques
Release 3.0.2 (10/17/2003)
« Globalization | Contents
»
Appendix: Performance Techniques
Do not optimize unless you know you have a performance problem! In general,
readability is more important than performance.
The biggest performance optimizations come from architectural and algorithmic
changes, e.g., caching. Poorly written database queries can kill a server -
use a query analyzer to sanity check your SQL and take advantage of cfquery
's caching functionality where appropriate.
Performance under load is often very
different to 'straight-line' performance - a change
that
makes
a
loop
run twice
as fast
when you're testing
a single request may not have the same effect when a hundred users are hitting
your site. Use load testing tools to identify bottlenecks and then think
carefully about how to restructure the code to improve performance under load.
Having said all that, here are some code-level "do's" and "don'ts".
These techniques are usually version-specific and most of these have been verified
on CFMX. For the most part they are only important for very performance-sensitive
code such as frequently called tags.
Performance "Do's"
The following are 'positive' recommendations, e.g., "Do xyz..." or
"Do xyz instead of...".
Use compareNoCase() for comparing two values
Use compareNoCase()
or compare()
instead of the is
not
operator to compare two items. They are significantly faster. Remember that
these functions return 0 if the values match, so they correspond to is
not
.
Example: <cfif compareNoCase(x, "a")>
Not: <cfif x is not "a">
Note: This has been verified for CFMX.
Use listFindNoCase() for OR comparisons
Use listFindNoCase()
or listFind()
instead of the is
and or
operators to compare one item to multiple items. They are much
much faster (order of magnitude for 5+ options).
Example: <cfif listFindNoCase("a,b,c", x)
Not: <cfif x is "a" or x is "b" or x is "c">
Note: This has been verified for CFMX.
Use arrays instead of lists - in general
In CFMX, lists suffer from the generally slow string processing in Java which
means that list manipulation can be slower than in CF5. In general, it is better
to work with arrays of items instead of lists of items: listGetAt()
is not an efficient way to work with individual items in a data set! However,
see the list vs array caveat in the Don't section below.
Note: This has been verified for CFMX.
Use cfqueryparam to increase query performance
You can use cfqueryparam
to optimize a query that looks something
like this:
SELECT
*
FROM
TABLE_NAME
WHERE
COLUMN = #variable#
If this query is executed repeatedly with different values for variable
then using a SQL 'bind' variable will be faster. cfqueryparam creates these
'bind' variables:
SELECT
*
FROM
TABLE_NAME
WHERE
COLUMN = <cfqueryparam cfslqtype="cf_sql_xxx" value="#variable#">
This allows the optimizer to compile the query once and reuse it every time
the query is executed. It is also more secure since it prevents rogue SQL from
being passed into a query (because it validates the type of the data).
Note: This has been verified for CFMX.
Use blockFactor to increase query performance
Adding blockFactor
to a query can significantly improve performance.
To add blockFactor
, examine the data that is being returned. Determine
the maximum size (in bytes) of each row. Take that size and determine how many
times that number would divide into 32k. That number is your blockFactor
,
but be aware that the max blockFactor
is 100. So, if for example you
were getting 200 bytes per row, you could easily fit over 100 rows into the
32k buffer that CF 'grabs' at one time.
If you know at runtime that you will have less then 100 rows returned, for
example you're writing a query that either returns 0 or 1 rows, do not bother
adding the blockFactor
attribute.
Note: This has been verified for CFMX.
Performance "Don'ts"
The following are 'negative' recommendations, e.g., "Don't do xyz...".
Don't use evaluate()
Avoid evaluate()
unless there is no other way to write your code!
Don't use iif()
Always use cfif
/cfelse
instead of iif()
. It is significantly
faster and more readable.
Don't use structFind()
Always use struct.key
or struct[key]
instead of structFind(struct,
key)
. They are significantly faster and more readable.
Don't slavishly convert lists to arrays
Even though manipulating an array is generally faster than manipulating a list
in CFMX, if you simply need to iterate over a list of items and process each
one in turn the faster construct is <cfloop list="#itemList#"
index="x"> ... </cfloop>
. Don't convert itemList
to an array and then loop over that - it's not worth it because it probably
won't be faster.
Don't use cfmodule
It's slower than a CFC method invocation, it's slower and uglier than using
a custom tag with a prefix, it's even slightly slower than a regular custom
tag invocation. Better options exist: use a CFC (preferred), use cfimport
and
invoke a custom tag (always preferable to invoking a custom tag via cfmodule
)
or even simply including a file.
Don't use incrementValue()
Always use x = x + 1
instead of x = incrementValue(x)
. It
is more readable and slightly faster.
Note: In situations where x + 1
is not legal, incrementValue(x)
will be more readable than creating a temporary variable to hold x + 1
and then using the temporary variable.
Don't use WDDX for hardcoded data
It is always faster to cfinclude
a CFML file that defines a datastructure
than it is to deserialize a WDDX packet of that datastructure somewhat faster
if the packet is in memory, and significantly faster if the WDDX packet is
read with cffile
. Use this technique if the datastructure can
be hardcoded (i.e., don't ship .wddx
files, ship .cfm
files).
The Site-wide Variables technique
is a good example of this.
Note: Complex or frequently changing configuration data is best implemented
using an appropriately designed XML file.
« Globalization | Contents »
Source: http://livedocs.macromedia.com/wtg/public/coding_standards/performance.html