Tuga it 2016 improving your application performance

Preview:

Citation preview

Improving your application performance

Nuno CanecoTuga IT – 21-05-2016

TUGA IT 2016

LISBON, PORTUGAL

BioSoftware Engineer for 13+ years

The purpose

Share lesson

s learne

d

Project facts• Team: 5 devs + 1 team leader + 1 tester• Duration: 18x 2-week sprints

• 165 KLOC(1): 27KLOC are automated tests

Central SystemWeb Application

• .NET 4.5• ASP.NET MVC 4• WCF• SQL Server

POSWindows App

InspectionMobile Application

• .NET 4• WPF• WCF• SQL Server Compact

• Windows Mobile 6.5• .NET 3.5 Compact• Win Forms• WCF• SQL Server Compact

(1) KLOC = 1.000 lines of code

We questioned ourselves

Will the users complain?

Will it handle data in PROD?

Will it be fast enough?Will the database

perform?

DEMO!

#1: Prepare the database• INDEXES:

– Choose the indexes wisely– Use multi-column indexes

• Pay attention to the order of the columns – Use Filtered Indexes– Use Included Columns

• Use Stored Procedures for the most data intensive features– And spend some time optimizing those!

• Avoid unnecessary LOCKs– Use WITH(NOLOCK) on tables that allow READ UNCOMMITED

#2: Fine tune the PROD database

• FILEGROUPS:– Separate tables and indexes into different FILEGROUPS

– Isolate large tables on different FILEGROUPS

• Hard drives:– Allocate fastest harddrives to indexes and mission critical tables

– Make sure the tempdb is on the fastest storage possible

Entity Framework

#3: Learn about Entity Framework• Use Stored Procedures for critical reads

• Use Complex Types for Slim classes– Results for Search or List operations

• LINQ clauses: Beware the order// SELECT * FROM [Table] ; Count is performed in memoryWhere().ToList().Count()

VS

// SELECT COUNT(*) FROM [Table]Where().Count()

#4: Beware of lazy loadingusing (var context = new DbContext()){

// SELECT * from Messages WHERE ID = @messageIdvar message = context.Messages.SingleOrDefault(m => m.ID == messageId);// SELECT * FROM User WHERE ID = @message.ToUserFKvar toUser = message.ToUser;

// Now imagine this on a loop...}

Vs

using (var context = new DbContext()){

// SELECT * FROM Messages INNER JOIN Users ON (...)var message = context.Messages

.Include("ToUser")

.SingleOrDefault(m => m.ID == messageId);}

#5: Use SQL Parameters on queries

• Use SqlParameters on ADO.NET queries– Avoid string concatenation to build query

string command = String.Format("SELECT * FROM Message WHERE FromUserFK = {0}", fromUserId);

Vs

SqlCommand command = new SqlCommand("SELECT * FROM Message WHERE FromUserFK = @fromUserFk", connection);command.Parameters.AddWithValue("@fromUserFK", fromUserId);

#6: Use cache• Store data in Cache– Reference tables– Read-mostly data– Recently read data

• Choose the most appropriate caching platform:– Local Cache: MemCache– Distributed Cache: Redis Cache, ...

• BUT...– Measure the cost of querying the cache

#7: RAM is cheap, but...• Avoid unnecessary data loads– Especially large data blocks

• stateless objects should always be singleton

• Optimize your code– Avoid the ‘+’ to concatenate strings Use StringBuilder() or String.Format() instead

– Optimize the loops– Avoid expensive operations– Beware of serialization

#8: Mind the Logger• Logging to Database causes LOCKs

And potential Exceptions on the application code

• Logging to disk causes contentionUnless configured otherwise

Log4net:<appender>

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /></appender>

#8: Mind the Loggerstring[] operationResult = (...);

logger.Debug("The result of this long running is {0}", string.Join(operationResult,";"));

VS

if(logger.IsDebugEnabled){ logger.Debug(" The result of this long running is {0}", string.Join(operationResult,";"));}

string.Join() will always be executed, even if DEBUG is

disabled

#9: Misc.• Class mapping– Auto mapping (reflection) vs Manual mapping

• Exception handling– Minimize catch() statements– Exceptions must flow as much as possible– Only catch exceptions on methods in case of adding some value to it:RetryHandle the error and proceed× Logging and rethrow

At the end of the day

ScalabilityPerformance

Features & User ExperienceCosts of technical choices

Dev effort and timeSolution Architecture

IT HardwareBenefits of technical choices

Questions

?

Thank you!

/nunocaneco

nuno.caneco@gmail.com