Muahahaha! Why is my code so slow? I just bit a byte! Caching & Performance In ColdFusion Presented By Denard Springle NVCFUG June 2011
Download
Report
Transcript Muahahaha! Why is my code so slow? I just bit a byte! Caching & Performance In ColdFusion Presented By Denard Springle NVCFUG June 2011
Muahahaha!
Why is my
code so
slow?
I just bit a
byte!
Caching & Performance
In ColdFusion
Presented By Denard Springle
NVCFUG June 2011
Programming For Speed
• Write OOP Applications
• OOP applications run faster and perform better than procedural coded
applications. OOP application’s use of encapsulation allows only those
functions which need to be fired to fire, and those that don’t… don’t.
• Java, the underlying engine behind ColdFusion, is a true Object Oriented
language. OO in ColdFusion has been developed to map as much as
possible to the Java model that underlies the ColdFusion engine. This
allows CF code to execute faster when written in an OO fashion.
O… O…
It also makes for happy developers, managers and
Who?
customers.
Programming For Speed
• Exit As Quickly As Possible
• Logic in applications should always be written to exit as quickly as possible
under all circumstances.
• Programmers have a tendency to write logic that checks for error
conditions passively (at the end) rather than actively (at the beginning).
This is a time honored tradition and one that is continually perpetuated in
coding books. Stop it! Always check for error conditions first and plan the
fastest exit strategy for all code. The less code that has to execute, the
faster your application will run.
Where’s
the
Exit?!
Programming For Speed
• Limit Nested Loops
• Nested loops are sometimes unavoidable, but they should be avoided
whenever possible.
• Nested looping is both a blessing and a curse to developers. On the one
hand it offers much needed functionality to iterate over multiple sets of
inter-related data points. On the other hand, it kills servers. There are
often alternatives to nested loops that developers ignore (mapping your
data into a struct, for example) and many developers simply abuse the
I’m
ability to nest loops without realizing the implications
Loopy!
for the performance of the application.
Programming For Speed
• Know Your ColdFusion
• ColdFusion offers a number of handy functions which should be avoided
like the plague.
• ColdFusion is great. It gives us things like inline if (IIF) which one would
logically assume runs as quickly as an if-then-else, but that’s a poor
assumption. There are a number of functions in ColdFusion that don’t
operate on the premise many developers think they do (structFind(),
<cfmodule>, incrementValue(), etc.). As such, avoiding the processor
intensive functions for those that behave better is always
a preferred choice (e.g. struct.key, <cfinclude>, a=a+1).
Uhh...
Programming For Speed
• Test Execution Speed
• The most often overlooked data point in testing is execution speed.
• Testing your code for execution speed is key to understanding which
functions take too long. Database queries, math intensive reporting and
internet protocol requests are no brainers for taking a long time and are
often suspect enough to improve application performance significantly.
There are other, less obvious, suspects to consider however – locking
shared scope variables, for example. Using GetTickCount() at the
Faster!
beginning and end of your functions will help you isolate
Faster!
problem areas and keep you from pulling out hair.
Programming For Speed
• Use Stored Procedures
• Stored procedures take away much of the overhead involved with dealing
with database queries.
• Stored procedures take a tremendous load off of your ColdFusion server
and place it squarely in the hands of your database server. Understand
that this is literally a transfer of CPU and memory load from your
application server to your database server. Stored procedures execute
faster on most database servers than a query does from ColdFusion so it is
typically a win/win situation.
I should
store
*this* guy!
Cashing In On Cache
• Use Caching
• Caching is a fancy way of saying – keep this just as it is and give it to
anyone who asks for it.
• For performance benefits, nothing beats caching. Caching of pages and
queries, and indeed with ORM, allows you to provide quicker
responsiveness for both static and dynamic* content. Pages and queries
(e.g. ‘US States’ table in a DB) that never change should always be cached.
ColdFusion doesn’t have to process the page or the query again until the
cache expires, providing instant-on access to pages and
Cash?!
critical data (e.g. reporting).
* dynamic content that changes infrequently
Cashing In On Cache
• Page Caching
•
<cfcache timespan="#CreateTimespan(1, 0, 0, 0)#" directory="e:/temp/page_cache“>
• You tell ColdFusion to cache the page results by putting a cfcache tag on
your ColdFusion page before code that outputs text. The tag lets you
specify the following information:
– Whether to cache the page results on the server, the client system, or
both. The default is both.
– The directory on the server in which to store the cached pages.
Oh,
*Cache*
– The time span that indicates how long the page lasts
until it is automatically flushed.
Cashing In On Cache
• Partial Page Caching
• <cfsavecontent variable=“SESSION.myVar”></cfsavecontent>
• One handy but not very obvious way to use <cfsavecontent> is in the
Application or Session scope of your application (typically in
OnApplicationStart and/or OnSessionStart). By saving infrequently
changing but frequently presented complex data in this way you can
significantly decrease individual page load times. Because of the overhead
of locking shared scope variables, use this technique only if the processing
overhead of generating the output is more than the
processing overhead of locking the shared scope.
Cashing In On Cache
• Query Caching
•
<cfquery datasource=“myds" name=“qGetStates"
cachedWithin="#CreateTimeSpan(0,1,0,0)#">
• The cfquery tag cachedWithin attribute tells ColdFusion to save the results
of a database query for a specific period of time. This way, ColdFusion
accesses the database on the first page request, and does not query the
database on further requests until the specified time expires. Using the
cachedWithin attribute can significantly limit the overhead of accessing
databases that do not change rapidly. This technique is useful if the
Day, Hour,
Minute,
database contents only change at specific, known times,
Second!
or the query does not require up-to-date results.
(e.g. Google Adwords reports are delayed 1 hr.)
Cashing In On Cache
• Flushing The Page Cache
• <cfcache action=“flush” [directory="e:/temp/page_cache“]>
• You can use the cfcache tag with the action="flush" attribute to
immediately flush one or more cached pages. You can optionally specify
the directory that contains the cached pages to be flushed and a URL
pattern that identifies the pages to flush. If you do not specify a URL
pattern, all pages in the directory are flushed. The URL pattern can include
asterisk (*) wildcards to specify parts of the URL that can vary. If you
have a ColdFusion function that updates data that you
FLUSH!
use in cached pages, that function should include a
cfcache tag that flushes all pages that use the data.
Cashing In On Cache
• Flushing The Query Cache
•
<cfquery datasource=“myds" name=“qGetStates"
cachedWithin="#CreateTimeSpan(0,0,0,0)#">
• One of the first hurdles most developers face implementing query caching
is how to undo the cache. Often in testing phases one discovers the
database table didn’t have all the data it needed or needs a new field (or
two) ‘manager special’ but one already has a cached query and doesn’t
understand why they’re always getting the same results. I know it seems
obvious, but it really isn’t when you first play with query caching ;)
That’s
what
Setting your cachedWithin timespan to nothing (0,0,0,0)
she said!
flushes the cached query and immediately calls the
database for your precious missing data! w00t!
Cashing In On ORM Cache
• ORM and Caching – Session and Secondary Level Caches
• Cache data of a persistent object
– <cfcomponent persistent="true" schema="APP" table="Artists" cachename="artist"
cacheuse="read-only">
•
Cache the association data of a persistent object
– <cfproperty name="art" fieldtype="one-to-many" cfc="CArt" fkcolumn="ArtID"
cachename="ArtistArts" cacheuse="read-only">
•
Cache query data
– availableArts = ORMExecuteQuery("from CArt where issold=0", {}, false,
{cacheable=true, cachename="availableArtsQuery"});
• See the Developing ColdFusion 9 Applications guide /
ColdFusion ORM / Performance optimization / Caching
section for full details of ORM caching techniques.
Nom
Nom
Nom
Additional Resources
• ORM and Caching – Session and Secondary Level Caches
• Optimizing ColdFusion Applications
• There is no blog post for ColdFusion tags to avoid!!
• Performance tuning ColdFusion servers
We hope
you enjoyed
this!
w00t!