50 Ways Avoid Find Fix Aspnet Issues
50 Ways Avoid Find Fix Aspnet Issues
1
ANTHONY JEREMY
DANG JARRELL
KEVIN IAN
GRIFFIN DUNKERLY
DAVID TED
HANEY JARDINE
TROY HUNT ANTHONY
ANTHONY MOORER
VAN DER JULIE
HOORN BELLER
MICHAEL GREGORY
SORENS WHATLEY
MATTHEW SHAWN
K BINNS
DAVE BRUCE
WARD NORTON
NICK STEPHEN
HARRISON KEANE
2
Foreword
Michaela Murray,
.NET Tools Division at Red Gate Software.
[email protected]
Contents
Foreword 3
Caching is a last resort 6
Remove unused View Engines 7
Use Microsoft’s PDBs to debug or profile external 8
assemblies or libraries
A selection of tips 10
Make sure paging is conducted at the database layer 13
For a snappy user experience, always validate on the 14
client
Always perform validation on the server as well 15
Review what client scripts you are using 16
Reduce memory leaks dramatically with the 16
“using” statement
Reduce the data sent across the network 17
Avoid running sites in debug mode 18
When in production, carefully consider what you 19
need to log
A selection of tips 20
Use the startMode attribute to reduce the load time 22
for your ASP.NET site
4
Don’t underestimate the value of the UI when tackling 23
performance problems
Throw hardware at the problem, not developers 24
Don’t assume that problems can only arise from 25
business logic
Before tackling any website performance issue, first 26
verify the problem isn’t on the client
Static collections 27
Know your loops 28
Seven handy ViewState tips 29
Avoid using session state 38
Take advantage of .NET 4.5 async constructs 39
StringBuilder is NOT the answer for all string 40
concatenation scenarios; String.Join could be
ORM Tips 42
Database Performance Tips for Developers 45
T-SQL Tips 46
Index Tips 48
Free eBooks from Red Gate 49
Tools from Red Gate 50
5
1
Caching is a last resort
Anthony Dang
@anthonydotnet
CACHING
BREAK GLASS
6
2
Remove unused View Engines
Kevin Griffin
@1kevgriff, www.kevgriffin.com
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(
newRazorViewEngine());
7
3
Use Microsoft’s PDBs to debug
or profile external assemblies
or libraries
David Haney
www.haneycodes.net, www.linkedin.com/in/davidahaney
8
Just go to Tools –> Options –> (expand) Debugging
–> Symbols, and select the Microsoft Symbol Servers
as your source for Symbols.
9
A selection of tips
Troy Hunt
Microsoft MVP
4
Make sure HTTP compression is turned on for
any uncompressed content. HTML in particular
compresses significantly, and in this era of mobile
friendliness and slow 3G connections, that’s
essential.
5
Always set the CacheControlMaxAge attribute in
web.config to a high number (a year is good). You
don’t want people pulling down the same static
content they did last week. It’ll also save on the
bandwidth you’re paying for.
10
6
Make use of the OutputCache annotation on MVC
controllers. If the server can serve from memory,
rather than going to disk or database, that’s a
good win.
7
Always profile your ORM database hits with SQL
Profiler during development. ORMs get away from
you very quickly. Before you know it, you’ve run a
query 2000 times in a loop, when you could have
retrieved all your data with a single database hit.
8
Watch out for lazy loading in ORMs. You shouldn’t
lazy load any entities that could be retrieved with a
single database hit.
11
9
Implement different database queries in different
contexts. In the API and on a webpage, you’ll
inevitably require different entity properties, so
don’t load things you don’t need just because it’s
convenient to reuse a query.
10
Get MiniProfiler and configure it to always run when
you hit your site (just don’t enable it for the general
public). You’ll get detailed execution times and a big
red warning if the same database query is running
multiple times.
12
11
Make sure paging is conducted at
the database layer
Anthony van der Hoorn
@anthony_vdh
13
12
For a snappy user experience,
always validate on the client
Simon Elliston Ball
@sireb
14
13
Always perform validation on the
server as well
Anthony van der Hoorn
@anthony_vdh
15
14
Review what client scripts you
are using
Anthony van der Hoorn
@anthony_vdh
15
Reduce memory leaks dramatically
with the “using” statement
Michael Sorens
www.linkedin.com/in/michaelsorens
16
16
Reduce the data sent across the
network
Matthew K
@mudnug
stop{}
17
17
Avoid running sites in debug mode
Dave Ward
@Encosia
18
18
When in production, carefully
consider what you need to log
Anthony van der Hoorn
@anthony_vdh
19
A selection of tips
Nick Harrison
@neh123us
19
Including height and width in <img /> tags will allow
your page to render more quickly, because space can
be allocated for the image before it is downloaded.
20
Add script references at the bottom of the page,
because asynchronous downloads halt when a script
reference is reached. Style sheets and images can be
downloaded asynchronously.
21
Use a content delivery network (CDN) for hosting
images and scripts. They may be cached and it will
reduce load on your server.
20
22
Use image sprites to retrieve smaller images in one
download.
23
Use AJAX to retrieve components asynchronously
that may not be needed immediately, such as the
content of a collapsed panel, content behind a tab,
and so on.
24
Make sure you’ve removed HTTP modules that
aren’t being used (Windows authentication, for
example), and that you’ve disabled services such as
FTP and SMTP, if you’re not using them.
21
25
Use the startMode attribute to
reduce the load time for your
ASP.NET site
Jeremy Jarrell
@jeremyjarrell
22
26
Don’t underestimate the value of
the UI when tackling performance
problems
Jeremy Jarrell
@jeremyjarrell
23
27
Throw hardware at the problem, not
developers
Jeremy Jarrell
@jeremyjarrell
24
28
Don’t assume that problems can
only arise from business logic
Jeremy Jarrell
@jeremyjarrell
25
29
Before tackling any website
performance issue, first verify the
problem isn’t on the client
Jeremy Jarrell
@jeremyjarrell
26
30
Static collections
Ian Dunkerly
@IDDesignsX
27
31
Know your loops
Ian Dunkerly
@IDDesignsX
28
Seven handy ViewState tips
Ted Jardine
@ovalsquare
32
Every time I have to deal with a classic ASP.NET Web
Forms application, one of the first things I look at
is the resulting source, to check whether the DOM
is a complete mess and whether the ViewState is an
enormous, unnecessary blob of ugliness. Usually,
they indicate what kind of mess will be found
further down the stack.
29
Inadvertently using ViewState when it’s not
necessary substantially increases the amount
of data going back and forth, and can lead to a
greater prevalence of invalid ViewState exceptions;
the bigger the blob, the more likely it could be
interrupted in transmission and not be posted back
in entirety in a post.
33
Unless you’re tracking a Text_Changed event, you
don’t need ViewState enabled on TextBoxes and
similar controls. Classic ASP.NET automatically
repopulates TextBox.Text values upon postback,
even without ViewState enabled. Turn it off on each
TextBox with EnableViewState= “false” on each one.
You can do this for other controls like labels, but
unless you’re setting their values after the page’s load
event, you won’t reduce the size of the ViewState.
30
34
The same goes for most implementations of
Repeaters, ListViews, and so on. These are usually
the biggest culprits and they can be ugly. The
advantage of ViewState with these is avoiding having
to populate values again in a postback. If you’re
convinced that it’s worth passing ViewState back
and forth again and again to save your app the extra
database hit…well…you’re probably wrong. Save the
database hit (if you need to) with some caching and
disable that dang ViewState on that Repeater!
31
35
If you’re re-binding data anyway, or just toggling one
property on postback (asp:Panel anyone?), turn off
that ViewState! Please!
32
36
If you do need ViewState, understand the page
lifecycle and bind your data appropriately. A control
loads its ViewState after Page_Init and before
Page_Load, i.e. server controls don’t start tracking
changes to their ViewState until the end of the
initialization stage. Any changes to ViewState mean
a bigger ViewState, because you have the before
value and the after value. So, if you’re changing or
setting a control’s value, set it before ViewState is
being tracked, if possible.
33
37
You may think it’s impossible to turn off ViewState
on a DropDownList, even if you re-bind it on every
postback. But with a tiny bit of elbow grease you can
keep ViewState enabled and avoid passing all your
option values back and forth. This is particularly
worthwhile for DropDownLists with a big ListItem
collection. One way is to turn off ViewState and bind
the select value manually to the actual posted value,
like so:
34
However, you may prefer something I came across
more recently. Instead of binding your DropDown-
List in the typical Page_Load or Page_Init, bind it in
the control’s Init event:
35
38
Make it your habit to turn off ViewState on every
control by default, and only turn it on when you
need it. If a page doesn’t need ViewState anywhere,
turn it off at the page level. You do all that work
to reduce requests, combine and compress static
references, and make sure your code is as clean as
possible - don’t ruin it with a ViewState monster!
36
/// <summary>
/// BasePage providing cross-site functionality
for pages that should not have ViewState enabled.
/// </summary>
public class BasePageNoViewState : Page // Or of
course, inherit from your standard BasePage, which in
turn inherits from Page
{
protected override void SavePageStateToPersistence
Medium(object viewState)
{
}
protected override object
LoadPageStateFromPersistenceMedium()
{
return null;
}
protected override void OnPreInit(EventArgs e)
{
// Ensure that ViewState is turned off for
every page inheriting this BasePage
base.EnableViewState = false;
base.OnPreInit(e);
}
}
}
}
37
39
Avoid using session state
Anthony van der Hoorn
@anthony_vdh
38
40
Take advantage of .NET 4.5 async
constructs
Anthony van der Hoorn
@anthony_vdh
39
41
StringBuilder is NOT the answer for
all string concatenation scenarios;
String.Join could be
Ted Jardine
@ovalsquare
40
Instead, use String.Join, which is typically more
performant than spinning up a StringBuilder
instance for a limited number of strings. It’s my
go-to concat option:
The first variable of " " can just be set to "" when you
don’t want a delimiter.
41
ORM Tips
Anthony Moorer, Julie Beller, and Gregory
Whatley
42
Avoid following the ‘Hello World’ examples provided
with your ORM tool that turns it into an Object to
Object Mapping. Database storage is not the same as
objects for a reason. You should still have a relational
storage design within a relational storage engine
such as SQL Server.
42
43
Parameterized queries are exactly the same as stored
procedures in terms of performance and memory
management. Since most ORM tools can use either
stored procedures or parameterized queries, be sure
you’re coding to these constructs and not
hard-coding values into your T-SQL queries.
44
Create, Read, Update, and Delete (CRUD) queries
can all be generated from the ORM tool without
the need for intervention. But, the Read queries
generated are frequently very inefficient. Consider
writing a stored procedure for complex Read queries.
43
45
Since the code generated from the ORM can
frequently be ad hoc, ensure that the SQL Server
instance has ‘Optimize for Ad Hoc’ enabled. This will
store a plan stub in memory the first time a query is
passed, rather than storing a full plan. This can help
with memory management.
46
Be sure your code is generating a parameter size
equivalent to the data type defined within table in
the database. Some ORM tools size the parameter to
the size of the value passed. This can lead to serious
performance problems.
44
Database Performance
Tips for Developers
As a developer you may or may not need to go into
the database and write queries or design tables and
indexes, or help determine configuration of your
SQL Server systems. But if you do, these tips should
help to make that a more pain free process.
45
T-SQL Tips
Shawn Binns and Bruce Norton
47
SELECT * is not necessarily a bad thing, but it’s a
good idea to only move the data you really need to
move and only when you really need it, in order to
avoid network, disk, and memory contention on
your server.
46
48
For small sets of data that are infrequently updated
such as lookup values, build a method of caching
them in memory on your application server rather
than constantly querying them in the database.
49
Ensure your variables and parameters are the
same data types as the columns. An implicit or
explicit conversion can lead to table scans and slow
performance.
47
Index Tips
Stephen Keane and Gregory Whatley
Indexing tables is not an exact science. It requires some trial
and error combined with lots of testing to get things just right.
Even then, the performance metrics will change over time as
you add more and more data.
50
You get exactly one clustered index on a table.
Ensure you have it in the right place. First choice
is the most frequently accessed column, which
may or may not be the primary key. Second choice
is a column that structures the storage in a way
that helps performance. This is a must for
partitioning data.
51
Performance is enhanced when indexes are placed
on columns used in WHERE, JOIN, ORDER BY,
GROUP, and TOP. Always test to ensure that the
index does help performance.
48
More free eBooks from Red Gate
Chris Farrell and Nick Harrison take you from the very
basics of memory management, all the way to how the OS
handles its resources, to help you write the best code you
can.
49
About Redgate
Redgate is the leading provider of software
solutions for Compliant Database DevOps.
We’ve specialized in database software for
over 20 years.
www.redgate.com
Compliant
Database DevOps