Upload
truongtram
View
265
Download
20
Embed Size (px)
Citation preview
ASP.NETCore1.0HighPerformance
TableofContents
ASP.NETCore1.0HighPerformanceCreditsForewordAbouttheAuthorAcknowledgmentsAbouttheReviewerwww.PacktPub.com
eBooks,discountoffers,andmoreWhysubscribe?
PrefaceWhatthisbookcoversWhatyouneedforthisbookWhothisbookisforConventionsReaderfeedbackCustomersupport
DownloadingtheexamplecodeErrataPiracyQuestions
1.WhyPerformanceIsaFeaturePerformanceasafeatureCommonclassesofperformanceproblems
LanguageconsiderationsTypesofperformanceproblems
WhenperformancemattersSlowerissometimesbetter
WhyissuesaremissedMeasuring
ThebenefitsofplanningaheadUnderstandinghardware
StorageaccessspeedsScalingapproachchanges
ToolsandcostsToolsLookingatsomealternativetools
Thenew.NETSummary
2.MeasuringPerformanceBottlenecksTools
SQL
SQLServerProfilerExecutingasimplequery
MiniProfilerApplicationprofiling
GlimpseUsingGlimpse
IDEMonitoringHTTP
BrowsersChromeFirefox
FiddlerNetwork
MicrosoftMessageAnalyzerWireshark
RollyourownScience
RepeatabilityOnlychangeonething
Summary3.FixingCommonPerformanceProblems
LatencyAsynchronousoperations
SimpleasynchronoustoolsBackgroundqueuingHangfire
SelectN+1problemsEfficientpagingStaticsitegenerators
PragmaticsolutionswithhardwareAdesktopexampleWebapplications
OversizedimagesImageresolutionImageformat
Summary4.AddressingNetworkPerformance
InternetprotocolsTCP/IP
Slow-startHTTP
HeadersHTTPmethodsStatuscodes
EncryptionKeyexchangeDelaydiagnosticsPerformancetweaks
HTTP/2WebSockets
CompressionLosslesscompressionalgorithmsBundlingandminification
BundlingMinificationChangesinASP.NETCore
ImageoptimizationPNGJPEGOtherimageformatsResizingimages
CachingBrowserServerProxyserversbetweenyouandyourusers
CDNsSummary
5.OptimizingI/OPerformanceInput/output
CategoriesofI/ODisksVirtualfilesystemsDatabasesAPIs
NetworkdiagnosticstoolsPingTracertNslookupBuildyourown
SolutionsBatchingAPIrequestsEfficientDBoperations
DatabasetuningReporting
AggregatesSampling
InsertingdataGUIDs
AdvancedDBtopicsSimulationandtestingSummary
6.UnderstandingCodeExecutionandAsynchronousOperationsGettingstartedwiththecoreprojects
.NETCoreASP.NETCore
KestrelDatastructures
ListsDictionariesCollectionbenchmarksBloomfilters
HashingandchecksumsHashingbenchmarks
SerializationSIMDCPUinstructionsParallelprogramming
TaskParallelLibraryParallelLINQParallelbenchmarkingParallelprogramminglimitations
PracticestoavoidReflectionRegularexpressionsStringconcatenationintightloopsDynamictypingSynchronousoperationsExceptions
Summary7.LearningCachingandMessageQueuing
WhycachingishardWebcaching
CachingbackgroundHTTPheadersCachebusting
ServiceworkersServiceworkerexample
WebandproxyserversIISVarnish
WorkingwithacontentdeliverynetworkWhennottocache
Applicationlayercaching
RedisDatabaseresultsetcaching
MessagequeuingCoffeeshopanalogyMessagequeuingstylesCommonmessagingpatterns
UnicastPub/sub
RabbitMQQueuingframeworksandlibraries
Summary8.TheDownsidesofPerformance-EnhancingTools
ManagingcomplexityUnderstandingcomplexityComplexityreduction
FrameworksArchitecture
MonolithversusmicroservicesArchitecturecomparison
RefactoringAcultureofhighperformance
AblamelesscultureIntellectualdishonestySlowdowntogofasterFromthegroundupSharedvalues
ThepriceofperformanceDistributeddebugging
LoggingErrorloggingApplicationInsightsIntegratedloggingCentralizedlogging
StatisticsManagingstalecachesSummary
9.MonitoringPerformanceRegressionsProfilingandmeasurementTesting
AutomatedtestingContinuousintegrationSlowtestingFixingperformanceregressionsLoadtesting
RealismRealisticenvironmentsRealisticworkloads
FeatureswitchingExperimentingforscienceA/BtestingUserinterfacetesting
WebUItestingtoolsAutomatingUIperformancetests
StayingalertDevOps
DevOpstoolingProvisioningMonitoring
HostingSummary
10.TheWayAheadReviewingwhatwelearnedFurtherreading
GoingnativeProcessorarchitectureHardwareishardMachinelearningBigdataandMapReduceOrleansCustomtransportsAdvancedhashing
LibraryandframeworksupportThefutureSummary
ASP.NETCore1.0HighPerformance
ASP.NETCore1.0HighPerformanceCopyright©2016PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:June2016
Productionreference:1170616
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
Birmingham
B32PB,UK.
ISBN978-1-78588-189-3
www.packtpub.com
Credits
Author
JamesSingleton
CopyEditor
PriyankaRavi
Reviewer
JasonDeOliveira
ProjectCoordinator
SuzanneCoutinho
CommissioningEditor
EdwardGordon
Proofreader
SafisEditing
AcquisitionEditor
ChaitanyaNair
Indexer
MariammalChettiyar
ContentDevelopmentEditor
MerintThomasMathew
Graphics
KirkD'Penha
TechnicalEditor
KunalChaudhari
ProductionCoordinator
MelwynDsa
Foreword
"Themostamazingachievementofthecomputersoftwareindustryisitscontinuingcancellationofthesteadyandstaggeringgainsmadebythecomputerhardwareindustry."
--HenryPetroski
Weliveintheageofdistributedsystems.Computershaveshrunkfromroom-sizedindustrialmainframestoembeddeddevicesthataresmallerthanathumbnail.However,atthesametime,thesoftwareapplicationsthatwebuild,maintain,anduseeverydayhavegrownbeyondmeasure.Wecreatedistributedapplicationsthatrunonclustersofvirtualmachinesscatteredallovertheworld,andbillionsofpeoplerelyonthesesystems,suchase-mail,chat,socialnetworks,productivityapplications,andbanking,everyday.We'reonline24hoursaday,sevendaysaweek,andwe'rehookedoninstantgratification.Agenerationago,we'dhappilywaituntilaftertheweekendforachequetoclear,orallow28daysfordelivery.Today,weexpectinstantfeedback,andwhyshouldn'twe?Themodernwebisreal-time,immediate,on-demand,builtonpacketsofdataflashingaroundtheworldatthespeedoflight,andwhenitisn't,wenotice.We'veallhadthatsinkingfeeling...youknow,whenyou'vejustputyourcreditcardnumberintoapagetobuysomeexpensiveconcerttickets,andthesitetakesjustalittletoolongtorespond.Performanceandresponsivenessareafundamentalpartofdeliveringgreatuserexperienceinthedistributedage.However,foraworkingdevelopertryingtoshipyournextfeatureontime,performanceisoftenoneofthemostchallengingrequirements.Howdoyoufindthebottlenecksinyourapplicationperformance?Howdoyoumeasuretheimpactofthoseproblems?Howdoyouanalyzethem,designandtestsolutionsandworkarounds,andmonitortheminproductionsothatyoucanbeconfidentthattheywon'thappenagain?
Thisbookhastheanswers.Inside,JamesSingletonpresentsapragmatic,in-depth,andbalanceddiscussionofmodernperformanceoptimizationtechniques,andhowtoapplythemtoyour.NETandwebapplications.Startingfromthepremisethatweshouldtreatperformanceasacorefeatureofoursystems,JamesshowshowyoucanuseprofilingtoolssuchasGlimpse,MiniProfiler,Fiddler,andWiresharktotrackdownthebottlenecksandbugsthatcauseyourperformanceproblems.Headdressesthescientificprinciplesbehindeffectiveperformancetuning,monitoring,instrumentation,andtheimportanceofusingaccurateandrepeatablemeasurementswhenyoumakechangestoarunningsystemtotryandimproveperformance.
Thisbookgoesontodiscussalmosteveryaspectofmodernapplicationdevelopment:databasetuning,hardwareoptimisations,compressionalgorithms,networkprotocols,andobject-relationalmappers.Foreachtopic,Jamesdescribesthesymptomsofcommonperformanceproblems,identifiestheunderlyingcausesofthosesymptoms,andthendescribesthepatternsandtoolsthatyoucanusetomeasureandfixtheseunderlyingcausesinyourownapplications.There'sin-depthdiscussionofhigh-performancesoftwarepatternssuchasasynchronousmethodsandmessagequeues,accompaniedbyreal-worldexamplesshowingyouhowtoimplementthesepatternsinthelatestversionsofthe.NETframework.Finally,Jamesshowshowyoucannotonlyloadtestyour
applicationsasapartofyourreleasepipeline,butyoucancontinuouslymonitorandmeasureyoursystemsinproduction,lettingyoufindandfixpotentialproblemslongbeforetheystartupsettingyourendusers.
WhenIworkedwithJameshereatSpotlight,heconsistentlydemonstratedaremarkablebreadthofknowledge,fromASP.NETtoArduinos,fromResharpertoresistors.Oneday,he'dbuildreactivefrontendinterfacesinASP.NETandJavaScript,thenexthe'dcreatebuildmonitorsbywiringmicrocontrollersintoStarWarstoys,orworkingouthowtoconnectthebathroomdoorlocktotheintranetsothatourbicyclingemployeescouldseefromtheirdeskswhentheofficeshowerwasfree.AfterJamesmovedonfromSpotlight,I'vebeenfollowinghisworkwithCleanwebandComputing4KidsEducation.He'soneofthoseraredeveloperswhoreallyunderstandsthesocialandenvironmentalimplicationsoftechnology—thatwhetherit'sdeliveringgreatuserinteractionsorjustsavingelectricity,improvingyoursystems'performanceisagreatwaytodelightyourusers.Withthisbook,Jameshasdistilledyearsofhands-onlessonsandexperienceintoatrulyexcellentall-roundreferencefor.NETdeveloperswhowanttounderstandhowtobuildresponsiveandscalableapplications.It'sagreatresourcefornewdeveloperswhowanttodevelopaholisticunderstandingofapplicationperformance,butthecoverageofcutting-edgetechniquesandpatternsmeansit'salsoidealformoreexperienceddeveloperswhowanttomakesurethey'renotgettingleftbehind.Buyit,readit,shareitwithyourteam,andlet'smakethewebabetterplace.
DylanBeattie
Systemsarchitect
RESTevangelist,technicalspeaker
Co-organizeroftheLondon.NETUserGroup
AbouttheAuthorJamesSingletonisaBritishsoftwaredeveloper,engineer,andentrepreneur,whohasbeenwritingcodesincethedaysoftheBBCMicro.Hisformaltrainingisinelectricalandelectronicengineering,yethehasworkedprofessionallyin.NETsoftwaredevelopmentfornearlyadecade.
HeisactiveintheLondonstart-upcommunityandhelpsorganizeCleanwebLondoneventsforenvironmentallyconscioustechnologists.HerunsCleanwebJobs,whichaimstohelpgetdevelopers,engineers,managers,anddatascientistsintorolesthatcanhelptackleclimatechangeandotherenvironmentalproblems.Healsodoespublicspeaking,andhehaspresentedtalksatmanylocalusergroups,includingattheHackerNewsLondonmeetup.
Jamesholdsafirstclassdegree(withhonors)inelectronicengineeringwithcomputing,andhehasdesignedandbuilthisownbasicmicroprocessoronanFPGAalongwithacustominstructionsettorunonit.HeisalsoaScience,Technology,Engineering,andMathematics(STEM)ambassador,whoencouragesyoungpeopletostudythesefields.
Jamescontributestoandisinfluencedbymanyopensourceprojects,andregularlyusesalternativetechnologies,suchasPython,Ruby,andLinux.HeisenthusiasticaboutthedirectionthatMicrosoftistaking.NETinandtheirembracingofopensourcepractices.
Heisparticularlyinterestedinhardware,environmental,anddigitalrightsprojectsandiskeenonsecurity,compression,andalgorithms.Whennothackingoncode,orwritingforbooksandmagazines,heenjoyswalking,skiing,rockclimbing,traveling,brewing,andcraftbeer.
Jameshasgainedvariedskillsfromworkinginmanydiverseindustriesandroles,fromhighperformancestockexchangestovideoencodingsystems.Hehasworkedasabusinessanalyst,consultant,tester,developer,andtechnicalarchitect.Hehasawiderangeofknowledge,gainedfrombigcorporatestostartups,andalotofplacesinbetween.Hehasfirst-handexperienceofthebestandworstwaysofbuildinghighperformancesoftware.
Youcanreadhisblogatunop.uk.
AcknowledgmentsIwouldliketothankallofmyfriendsandfamilyforbeingsosupportivewhileI'vebeenworkingonthisbook.Iwouldespeciallyliketothankmydadforgettingmeintotechnologyatayoungage,andLouforherlimitlessenthusiasmandpositivity.IwouldalsoliketothankDylanforwritingtheforewordtothisbook.
Writingabookismuchharderworkthanmostpeopleprobablyimagine,andIcouldn'thavedoneitwithouttheconstantencouragement.ManysacrificesneededtobemadeandIthankeveryonefortheirunderstanding.SorryforalltheeventsthatI'vehadtomissandtoanyonewhoI'veforgottentothankhere.
IwouldalsoliketoacknowledgeRadioParadiseforkeepingmesanefromthenoiseoftheinconsiderateconstructorsnextdoor.Finally,IapologizeinadvancetomyBritish(orAussie,Kiwi,Canadian,andsoon)readersforanyoftheless-correctlyspelledwordsusedinthisbook.
AbouttheReviewerJasonDeOliveiraworksasCTOforMEGAInternational(http://www.mega.com),aSoftwareCompanyinParis(France)thatprovidesModelingToolsforEnterpriseArchitecture,EnterpriseGovernanceRisk,andComplianceManagement.HeisanexperiencedManagerandSeniorSolutionsArchitectwithhighskillsinSoftwareArchitectureandEnterpriseArchitecture.
Helovessharinghisknowledgeandexperienceviahisblog,byspeakingatconferences,writingtechnicalbooks,writingarticlesinthetechnicalpress,givingsoftwarecoursesasMCT,andcoachingco-workersinhiscompany.HefrequentlycollaborateswithMicrosoft,andyoucanfindhimquiteoftenattheMicrosoftTechnologyCenter(MTC)inParis.
Microsoftawardedhimin2011withtheMicrosoft®MostValuableProfessional(MVPC#)AwardforhisnumerouscontributionstotheMicrosoftcommunity.MicrosoftseekstorecognizethebestandbrightestfromtechnologycommunitiesaroundtheworldwiththeMVPAward.Theseexceptionalandhighly-respectedindividualscomefrommorethan90countries,servetheirlocalonlineandofflinecommunities,andhaveanimpactworldwide.Jasonisveryproudtobeoneofthem.
Pleasefeelfreetocontacthimviahisblogifyouneedanytechnicalassistanceorwanttodiscusstechnicalsubjects(http://www.jasondeoliveira.com).
Jasonhasworkedonthefollowingbooks:
.NET4.5ExpertProgrammingCookbook(English)WCF4.5Multi-tierServicesDevelopmentwithLINQtoEntities(English).NET4.5ParallelExtensionsCookbook(English)WCF4.5Multi-layerServicesDevelopmentwithEntityFrameworkThirdEdition(English)VisualStudio2013:Concevoir,développeretgérerdesprojetsWeb,lesgéreravecTFS2013(French)
Iwouldliketothankmylovelywife,Orianne,andmybeautifuldaughters,JuliaandLéonie,forsupportingmeinmyworkandforacceptinglongdaysandshortnightsduringtheweekandsometimesevenduringtheweekend.Mylifewouldnotbethesamewithoutthem!
www.PacktPub.com
eBooks,discountoffers,andmoreDidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusatcustomercare@packtpub.comformoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www2.packtpub.com/books/subscription/packtlib
DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt'sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt'sentirelibraryofbooks.
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
PrefaceMicrosofthasreleasedanewopensourceandcross-platformwebapplicationframework,calledASP.NETCore.Itrunsontopof.NETCore,whichisalsoopensource,andisprimarilyusedwiththeC#programminglanguage.YouarenolongertiedtousingWindowswithASP.NET,andyoucannowdeveloponaMacanddeploytoLinux.Thisnewplatformalsooffersmuchhigherperformance.
Intoday'sworld,awebapplicationthatonlyperformswellonadeveloper'sworkstationandfailstodeliverhigh-performanceinproduction,isunacceptable.Thewaythatwebapplicationsarenowdeployedatscalehaschanged,anddevelopmentpracticesmustadapttotakeadvantageofthis.Byreadingthisbook,you'lllearnaboutthemodernwayofmakinghigh-performancewebapplications,andhowtodothiswithASP.NETCore.
Thisbookaddresseswebapplicationperformance-improvementtechniquesfrombothageneralstandpoint(HTTP,HTTPS,HTTP/2,TCP/IP,databaseaccess,compression,I/O,assetoptimization,caching,messagequeuing,andotherconcerns)andfromaC#,ASP.NETCore,and.NETCoreperspective.Thisincludesdelvingintothedetailsofthelatestframeworksanddemonstratingsoftwaredesignpatternsthatimproveperformance.
Wewillhighlightcommonperformancepitfalls,whichcanoftenoccurunnoticedondeveloperworkstations,alongwithstrategiestodetectandresolvetheseissuesearly.Byunderstandingandaddressingchallengesupfront,youcanavoidnastysurpriseswhenitcomestodeploymenttime.
Wewillintroduceperformanceimprovementsalongwiththetrade-offsthattheyentail.Wewillstrikeabalancebetweenprematureoptimizationandinefficientcodebytakingascientificandevidence-basedapproach,focusingonthebigproblemsandavoidingchangesthathavelittleimpact.
Weassumethatyouunderstandtheimportanceofperformanceforwebapplications,butwewillrecapwhyit'scrucial.However,youmaynothavehadanyspecificoractionableadvice,orhavemuchexperienceofperformanceproblemsoccurringinthewild.
Byreadingthisbook,you'llunderstandwhatproblemscanoccurwhenwebapplicationsaredeployedatscaletodistributedinfrastructure,andknowhowtoavoidormitigatetheseissues.Youwillgainexperienceofhowtowritehigh-performanceapplicationswithouthavingtolearnaboutissuesthehardway,possiblylateatnight.
You'llseewhat'snewinASP.NETCore,whyit'sbeenrebuiltfromthegroundup,andwhatthismeansforperformance.Youwillunderstandthefutureof.NETCoreandhowyoucannowdeveloponanddeploytoWindows,MacOSX,andLinux.You'llappreciatetheperformanceofnewfeaturesinASP.NETCore,includingupdatestotheRazorviewengine,andyouwillbeawareofcrossplatformtools,suchasVisualStudioCode.
WhatthisbookcoversLet'stakealookatwhattopicswe'llbecoveringthroughoutthebook.
Chapter1,WhyPerformanceIsaFeature,discussesthebasicpremiseofthisbookandshowsyouwhyyouneedtocareabouttheperformanceofyoursoftware.Responsiveapplicationsarevital,andit'snotsimplyenoughtohavefunctionalitywork,italsoneedstobequick.
Thinkofthelasttimeyouheardsomeonecomplainingaboutanapporwebsite,andit'slikelytheywereunhappywiththeperformance.Poorperformancedoesn'tonlymakeusersunhappy,italsoaffectsyourbottom-line.There'sgooddatatosuggestthatfastperformanceincreasesengagementandimprovesconversionrates,whichiswhyit'srewardedbysearchengines.
Chapter2,MeasuringPerformanceBottlenecks,tellsyouthattheonlywayyoucansolveperformanceproblemsistocarefullymeasureyourapplication.Withoutknowingwhereaproblemlies,yourchanceofsolvingitisextremelyslim,andyouwon'tevenknowwhetheryou'veimprovedmattersormadethingsworse.
Wewillhighlightafewwaysofmanuallymonitoringperformanceandsomehelpfultoolsthatyoucanusetomeasurestatistics.You'llseehowtogaininsightsintothedatabase,application,HTTP,andnetworklevelsofyoursoftwaresothatyouknowwhatisgoingoninternally.We'llalsoshowyouhowtobuildyourownbasictimingcodeandcovertheimportanceoftakingascientificapproachtotheresults.
Chapter3,FixingCommonPerformanceProblems,looksatsomeofthemostfrequentperformancemistakes.We'llshowyouhowtofixsimpleissuesacrossarangeofdifferentapplicationareas,forexample,howtooptimizemediawithimageresizingorencoding,SelectN+1problems,andasynchronousbackgroundoperations.
Wewillalsotalkalittleaboutusinghardwaretoimproveperformanceonceyouknowwherethebottleneckslie.Thisapproachbuysyousometimeandallowsyoutofixthingsproperlyatareasonablepace.
Chapter4,AddressingNetworkPerformance,digsintothenetworkinglayerthatunderpinsallwebapplications.We'llshowyouhowremoteresourcescanslowdownyourappanddemonstratewhatyoucandoaboutmeasuringandaddressingtheseproblems.
Wewilllookatinternetprotocols,includingTCP/IP,HTTP,HTTP/2,andWebSockets,alongwithaprimeronencryptionandhowallofthesecanalterperformance.We'llcovercompressionoftextualandimage-basedassets,includingsomeexoticimageformats.Finally,wewillintroducecachingatthebrowser,server,proxy,andContentDeliveryNetwork(CDN)levels,showingyousomeofthebasics.
Chapter5,OptimizingI/OPerformance,focusesoninput/outputandhowthiscannegatively
affectperformance.Wewilllookatdisks,databases,andremoteAPIs,manyofwhichusethenetwork,particularlyifvirtualized.We'llcoverbatchingyourrequestsandoptimizingdatabaseusagewithaggregatesorsampling,aimingtoreducethedataandtimerequired.
Duetonetworking'subiquityincloudenvironments,we'llspendconsiderabletimeonnetworkdiagnostics,includingpinging,routetracing,andlookinguprecordsinthedomainnamesystem.You'lllearnhowlatencycanbedrivenbyphysicaldistance,orgeography,andhowthiscancauseproblemsforyourapplication.We'llalsodemonstratehowtobuildyourownnetworkinginformationgatheringtoolsusing.NET.
Chapter6,UnderstandingCodeExecutionandAsynchronousOperations,jumpsintotheintricaciesofC#codeandlooksathowitsexecutioncanalterperformance.We'lllookatthevariousopensourceprojectsthatmakeupASP.NETCoreand.NETCore,includingKestrel—ahigh-performancewebserver.
Wewillexaminetheimportanceofchoosingthecorrectdatastructuresandlookatvariousexamplesofdifferentoptions,suchaslistsanddictionaries.We'llalsolookathashing,serialization,andperformsomesimplebenchmarking.
Youwilllearnsometechniquesthatcanspeedupyourprocessingbyparallelizingit,suchasSingleInstructionMultipleData(SIMD)andparallelextensionsprogrammingwiththeTaskParallelLibrary(TPL)andParallelLINQ(PLINQ).You'llalsoseesomepracticesthatarebestavoided,duetotheirperformancepenalties,suchasreflectionandregularexpressions.
Chapter7,LearningCachingandMessageQueuing,initiallylooksatcaching,whichiswidelyregardedasdifficult.You'llseehowcachingworksfromaHTTPperspectiveinbrowsers,webservers,proxies,andCDNs.Youwilllearnaboutcachebusting(orbreaking)toforceyourchangesandusingthenewJavaScriptserviceworkersinmodernbrowserstogainfinercontrolovercaching.
Additionally,we'llexaminecachingattheapplicationanddatabaselevelsinyourinfrastructure.Wewillseethebenefitsofin-memorycaches,suchasRedis,andhowthesecanreducetheloadonyourdatabase,lowerlatency,andincreasetheperformanceofyourapplication.
Wewillinvestigatemessagequeuingasawaytobuildadistributedandreliablesystem.We'lluseanalogiestoexplainhowasynchronousmessagepassingsystemsworkandshowyousomecommonstylesofmessagequeuing,includingunicastandpub/sub.
Wewillalsoshowyouhowmessagequeuingcanbeusefultoaninternalcachinglayerbybroadcastingcacheinvalidationdata.You'lllearnaboutmessagebrokers,suchasRabbitMQ,andvariouslibrariestointeractwiththemfrom.NET.
Chapter8,TheDownsidesofPerformance-EnhancingTools,concentratesonthenegativesofthetechniquesthatwewillhavecoveredbecausenothingcomesforfree.We'lldiscussthevirtuesofvariousmethodstoreducecomplexity,useframeworks,anddesigndistributedarchitecture.We
willalsocoverprojectcultureandseehowhigh-performanceisnotsimplyaboutcodebutaboutpeopletoo.
We'lllookintopossiblesolutionstotackletheproblemofdistributeddebuggingandseesomeavailabletechnologiestocentrallymanageapplicationlogging.We'llhaveabriefintroductiontostatisticssothatyoucanmakesenseofyourperformancemetrics,andwewilltouchuponmanagingcaches.
Chapter9,MonitoringPerformanceRegressions,againtakesalookatatmeasuringperformance,butinthiscase,fromanautomationandContinuousIntegration(CI)perspective.We'llreiteratetheimportanceofmonitoringandshowhowyoucanbuildthisintoyourdevelopmentworkflowtomakeitroutineandalmosttransparent.Youwillseehowitispossibletoautomatealmostanytypeoftesting,fromsimpleunittestingtointegrationtesting,andevencomplexbrowserUserInterface(UI)testing.
We'llshowyouhowyoucanmakeyourtestsmorerealisticandusefulusingtechniques,suchasblue-greendeploymentandfeatureswitching.YouwilldiscoverhowtoperformA/Btestingoftwoversionsofawebpagewithsomeverybasicfeatureswitchingandafewoptionsforfunhardwaretokeeppeopleengagedintestresults.We'llalsocoverDevOpspracticesandcloudhosting,bothofwhichmakeCIeasiertoimplementandcomplementitnicely.
Chapter10,TheWayAhead,brieflysumsupthelessonsofthebookandthenhasalookatsomeadvancedtopicsthatyoumayliketoreadmoreabout.Wewillalsotrytopredictthefutureforthe.NETCoreplatformsandgiveyousomeideastotakefurther.
WhatyouneedforthisbookYouwillneedadevelopmentenvironmenttofollowthecodeexamplesinthisbook,eitherVisualStudioCommunity2015orVisualStudioCodeifyou'renotonWindows.Youcanalsouseyourtexteditorofchoiceandthedotnetcommandlinetool.IfyouuseVisualStudio,thenyoushouldalsoinstallthe.NETCoreSDKandtoolingandthelatestNuGetextension.
Forsomeofthechapters,youwillalsoneedSQLServer2014Express.Youcanuse2016too,particularlyifyouareonLinux.However,youcanalsouseAzureandrunagainstaclouddatabase.
Thereareothertoolsthatwewillcover,butwewillintroducetheseastheyareused.Thedetailedsoftware/hardwarelistisuploadedalongwiththecodefiles.
WhothisbookisforThisbookismainlyaimedatASP.NETandC#developers,butdevelopersusedtootheropensourceplatformsmayalsobeinterestedin.NETCore.YoushouldhaveexperiencewiththeMVCframeworkforweb-applicationdevelopmentandbelookingtodeployapplicationsthatwillperformwellonlive-productionenvironments.Thesecanbevirtualmachinesorhostedbyacloud-serviceprovider,suchasAWSorAzure.
ConventionsInthisbook,youwillfindanumberoftextstylesthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestylesandanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:"ThefetchfunctionisthemodernversionofanXMLHttpRequest."
Ablockofcodeissetasfollows:
varclient=newSmtpClient();
HostingEnvironment.QueueBackgroundWorkItem(ct=>
client.SendMailAsync(message));
Anycommand-lineinputoroutputiswrittenasfollows:
tracertec2.ap-southeast-2.amazonaws.com
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,forexample,inmenusordialogboxes,appearinthetextlikethis:"IfyouselectCacheStorage,youwillseethecontentsofthecache."
Note
Warningsorimportantnotesappearinaboxlikethis.
Tip
Tipsandtricksappearlikethis.
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook-whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.Tosendusgeneralfeedback,[email protected],andmentionthebook'stitleinthesubjectofyourmessage.Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesforthisbookfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
Youcandownloadthecodefilesbyfollowingthesesteps:
1. Loginorregistertoourwebsiteusingyoure-mailaddressandpassword.2. HoverthemousepointerontheSUPPORTtabatthetop.3. ClickonCodeDownloads&Errata.4. EnterthenameofthebookintheSearchbox.5. Selectthebookforwhichyou'relookingtodownloadthecodefiles.6. Choosefromthedrop-downmenuwhereyoupurchasedthisbookfrom.7. ClickonCodeDownload.
YoucanalsodownloadthecodefilesbyclickingontheCodeFilesbuttononthebook'swebpageatthePacktPublishingwebsite.Thispagecanbeaccessedbyenteringthebook'snameintheSearchbox.PleasenotethatyouneedtobeloggedintoyourPacktaccount.
Oncethefileisdownloaded,pleasemakesurethatyouunziporextractthefolderusingthelatestversionof:
WinRAR/7-ZipforWindowsZipeg/iZip/UnRarXforMac7-Zip/PeaZipforLinux
ThecodebundleforthebookisalsohostedonGitHubathttps://github.com/PacktPublishing/ASP.NET-Core-1.0-High-PerformanceWealsohaveothercodebundlesfromourrichcatalogofbooksandvideosavailableathttps://github.com/PacktPublishing/.Checkthemout!
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks-maybeamistakeinthetextorthecode-wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.
Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.
PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusatcopyright@packtpub.comwithalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.
QuestionsIfyouhaveaproblemwithanyaspectofthisbook,[email protected],andwewilldoourbesttoaddresstheproblem.
Chapter1.WhyPerformanceIsaFeatureThisisanexcitingtimetobeaC#developer.Microsoftisinthemiddleofoneofthebiggestchangesinitshistory,anditisembracingopensourcesoftware.TheASP.NETand.NETframeworksarebeingrebuiltfromthegrounduptobecomponentized,cross-platform,andopensource.
ASP.NETCore1.0and.NETCore1.0(previouslycalledASP.NET5and.NETCore5)embracemanyideasfrompopularopensourceprojects,suchasGo'sabilitytoproduceastatically-linked,standalonebinary.Youcannowcompileasinglenativeexecutablethatisfreeofanyexternaldependenciesandrunitonasystemwithout.NETinstalled.
TheASP.NETModelViewController(MVC)webapplicationframework,whichisnowpartofASP.NETCore1.0,borrowsheavilyfromRubyonRailsandMicrosoftiskeeninpromotingtools,suchasNode.js,Grunt,gulp,andYeoman.ThereisalsoTypeScript,whichisastatically-typedversionofJavaScriptthatwasdevelopedatMicrosoft.
Byreadingthisbook,youwilllearnhowtowritehigh-performancesoftwareusingthesenew.NETCoretechnologies.You'llbeabletomakeyourwebapplicationsresponsivetoinputandscalabletodemand.
We'llfocusonthelatestCoreversionsof.NET.Yet,manyofthesetechniquesalsoapplytopreviousversions,andtheywillbeusefulforwebapplicationdevelopmentingeneral(inanylanguageorframework).
Understandinghowallofthesenewframeworksandlibrariesfittogethercanbeabitconfusing.We'llpresentthevariousavailableoptionswhilestillusingthenewesttechnology,guidingyoudownthepathtohigh-speedsuccess,andavoidingperformancepitfalls.
Afterfinishingthisbook,youwillunderstandwhatproblemscanoccurwhenwebapplicationsaredeployedatscale(todistributedinfrastructure)andknowhowtoavoidormitigatetheseissues.Youwillgaintheexperienceofhowtowritehigh-performanceapplicationswithoutlearningaboutissuesthehardway.
Inthischapter,wewillcoverthefollowingtopics.
PerformanceasafeatureThecommonclassesofperformanceissuesBasichardwareknowledgeMicrosofttoolsandalternativesNew.NETnamingandcompatibility
PerformanceasafeatureYoumayhavepreviouslyheardaboutthepracticeoftreatingperformanceasafirst-classfeature.Traditionally,performance(alongwiththingssuchassecurity,availabilityanduptime)wasonlyconsideredaNon-FunctionalRequirement(NFR)andusuallyhadsomearbitrarymade-upmetricsthatneededtobefulfilled.Youmayhaveheardtheterm"performant"before.Thisisthequalityofperformingwelland,often,iscapturedinrequirementswithoutquantification,providingverylittlevalue.Itisbettertoavoidthissortofcorporatejargonwhencorrespondingwithclientsorusers.
Usingtheoutdatedwaterfallmethodofdevelopment,theseNFRswereinevitablyleftuntiltheend,anddroppedfromanover-budgetandlateprojectinordertogetthefunctionalrequirementscompleted.Thisresultedinasubstandardproductthatwasunreliable,slow,andofteninsecure(asreliabilityandsecurityarealsooftenneglectedNFRs).Thinkabouthowmanytimesyou'refrustratedatsoftwarethatlagsbehindinrespondingtoyourinput.Perhaps,youusedaticket-vendingmachineoraself-servicecheckoutthatisunresponsivetothepointofbeingunusable.
Thereisabetterway.Bytreatingperformanceasafeatureandconsideringitateverystageofyouragiledevelopmentprocess,youcangetusersandcustomerstoloveyourproduct.Whensoftwarerespondsquickerthanausercanperceive,itisadelighttouse,andthisdoesn'tslowthemdown.Whenthereisnoticeablelag,thenusersneedtoadjusttheirbehaviortowaitforthemachineinsteadofworkingattheirownpace.
Computershaveincredibleamountsofprocessingpowertoday,andtheynowpossessmanymoreresourcesthantheydidevenjustafewyearsago.So,whydowestillhavesoftwarethatisnoticeablyslowatresponding,whencomputersaresofastandcancalculatemuchquickerthanpeoplecan?Theanswertothisispoorlywrittensoftwarethatdoesnotconsiderperformance.Whydoesthishappen?Thereasonisthatoftenthesignsofpoorperformancearenotvisibleindevelopment,andtheyonlyappearwhendeployed.However,ifyouknowwhattolookfor,thenyoucanavoidtheseproblemsbeforereleasingyoursoftwaretotheproductionenvironment.
Thisbookwillshowyouhowtowritesoftwarethatisajoytouseandneverkeepstheuserwaitingoruninformed.Youwilllearnhowtomakeproductsthatuserswillloveinsteadofproductsthatfrustratethemallthetime.
CommonclassesofperformanceproblemsLet'stakealookatsomecommonareasofperformanceproblemsandseewhethertheymatterornot.Wewillalsolearnwhyweoftenmisstheseissuesduringdevelopment.
LanguageconsiderationsPeopleoftenfocusonthespeedoftheprogramminglanguagethatisused.However,thisoftenmissesthepoint.Thisisaverysimplisticviewthatglossesoverthenuancesoftechnologychoices.Itiseasytowriteslowsoftwareinanylanguage.
Withthehugeamountsofprocessingspeedthatisavailabletoday,relatively"slow"interpretedlanguagescanoftenbefastenough,andtheincreaseindevelopmentspeedisworthit.Itisimportanttounderstandtheargumentsandthetrade-offsinvolvedevenifbyreadingthisbookyouhavealreadydecidedtouseC#and.NET.
Thewaytowritethefastestsoftwareistogetdowntothemetalandwriteinassembler(orevenmachinecode).Thisisextremelytimeconsuming,requiresexpertknowledge,andtiesyoutoaparticularprocessorarchitectureandinstructionset;therefore,werarelydothisthesedays.Ifthishappens,thenit'sonlydoneforverynicheapplications(suchasvirtualrealitygames,scientificdatacrunching,andsometimesembeddeddevices)andusuallyonlyforatinypartofthesoftware.
Thenextlevelofabstractionupiswritinginalanguage,suchasGo,C,orC++,andcompilingthecodetorunonthemachine.Thisisstillpopularforgamesandotherperformance-sensitiveapplications,butyouoftenhavetomanageyourownmemory(whichcancausememoryleaksorsecurityissues,suchasbufferoverflows).
Alevelaboveissoftwarethatcompilestoanintermediatelanguageorbytecodeandrunsonavirtualmachine.ExamplesofthisareJava,Scala,Clojure,and,ofcourse,C#.Memorymanagementisnormallytakencareof,andthereisusuallyaGarbageCollector(GC)totidyupunusedreferences(GoalsohasaGC).Theseapplicationscanrunonmultipleplatforms,andtheyaresafer.However,youcanstillgetneartonativeperformanceintermsofexecutionspeed.
Abovetheseareinterpretedlanguages,suchasRuby,Python,andJavaScript.Theselanguagesarenotusuallycompiled,andtheyarerunline-by-linebyaninterpreter.Theyusuallyrunslowerthanacompiledlanguage,butthisisoftennotaproblem.Amoreseriousconcerniscatchingbugswhenusingdynamictyping.Youwon'tbeabletoseeanerroruntilyouencounterit,whereasmanyerrorscanbecaughtatcompiletimewhenusingstatically-typedlanguages.
Itisbesttoavoidgenericadvice.YoumayhearanargumentagainstusingRubyonRails,citingtheexampleofTwitterhavingtomigratetoJavaforperformancereasons.Thismaywellnotbeaproblemforyourapplication,andindeedhavingthepopularityofTwitterwouldbeaniceproblemtohave.AbiggerconcernwhenrunningRailsmaybethelargememoryfootprint,makingitexpensivetorunoncloudinstances.
Thissectionisonlytogiveyouataste,andthemainlessonisthatnormally,languagedoesn'tmatter.Itisnotusuallythelanguagethatmakesaprogramslow,it'spoordesignchoices.C#offersanicebalancebetweenspeedandflexibilitythatmakesitsuitableforawiderangeofapplications,especiallyserver-sidewebapplications.
TypesofperformanceproblemsTherearemanytypesofperformanceproblems,andmostofthemareindependentoftheprogramminglanguagethatisused.Alotoftheseresultfromhowthecoderunsonthecomputer,andwewillcovertheimpactofthislateroninthechapter.
Wewillbrieflyintroducecommonperformanceproblemshereandwillcovertheminmoredetailinlaterchaptersofthisbook.Issuesthatyoumayencounterwillusuallyfallintoafewsimplecategories,includingthefollowing:
Latency:MemorylatencyNetworklatencyDiskandI/OlatencyChattiness/handshakes
Bandwidth:ExcessivepayloadsUnoptimizeddataCompression
Computation:WorkingontoomuchdataCalculatingunnecessaryresultsBruteforcingalgorithms
Doingworkinthewrongplace:SynchronousoperationsthatcouldbedoneofflineCachingandcopingwithstaledata
Whenwritingsoftwareforaplatform,youareusuallyconstrainedbytworesources.Thesearethecomputationprocessingspeedandaccessingremote(totheprocessor)resources.
Processingspeedisrarelyalimitingfactorthesedays,andthiscouldbetradedforotherresources,forexample,compressingsomedatatoreducethenetworktransfertime.
Accessingremoteresources,suchasmainmemory,disk,andthenetworkwillhavevarioustimecosts.Itisimportanttounderstandthatspeedisnotasinglevalue,andithasmultipleparameters.Themostimportantofthesearebandwidthand,crucially,latency.
Latencyisthelagintimebeforetheoperationstarts,whereasbandwidthistherateatwhichdataistransferredoncetheoperationstarts.Postingaharddrivehasaveryhighbandwidth,butitalsohasveryhighlatency.Thiswouldmakeitveryslowtosendlotsoftextfilesbackandforth,butperhaps,thisisagoodchoicetosendalargebatchof3Dvideos(dependingontheWeissmanscore).Amobilephonedataconnectionmaybebetterforthetextfiles.
Althoughthisisacontrivedexample,thesameconcernsareapplicabletoeverylayerofthecomputingstackoftenwithsimilarordersofmagnitudeintimedifference.Theproblemisthatthe
differencesaretooquicktoperceive,andweneedtousetoolsandsciencetoseethem.
Thesecrettosolvingperformanceproblemsisingainingadeeperunderstandingofthetechnologyandknowingwhathappensatthelowerlevels.Youshouldappreciatewhattheframeworkisdoingwithyourinstructionsatthenetworklevel.It'salsoimportanttohaveabasicgraspofhowthesecommandsrunontheunderlyinghardware,andhowtheyareaffectedbytheinfrastructurethattheyaredeployedto.
Whenperformancematters
Performanceisnotalwaysimportantineverysituation.Learningwhenperformancedoesanddoesn'tmatterisanimportantskilltoacquire.Ageneralruleofthumbisthatiftheuserhastowaitforsomethingtohappen,thenitshouldperformwell.Ifthisissomethingthatcanbeperformedasynchronously,thentheconstraintsarenotasstrict,unlessanoperationissoslowthatittakeslongerthanthetimewindowforit;forexample,anovernightbatchjobonanoldfinancialservicesmainframe.
Agoodexamplefromawebapplicationstandpointisrenderinguserviewversussendinge-mail.Itisacommon,yetnaïve,practicetoacceptaformsubmissionandsendane-mail(orworse,manye-mails)beforereturningtheresult.Yet,unlikeadatabaseupdate,ane-mailisnotsomethingthathappensalmostinstantly.Therearemanystagesoverwhichwehavenocontrolthatwilldelayane-mailinreachingauser.Therefore,thereisnoneedtosendane-mailbeforereturningtheresultoftheform.Youcandothisofflineandasynchronouslyaftertheresultoftheformsubmissionisreturned.
Theimportantthingtorememberhereisthatitistheperceptionofperformancethatmattersandnotabsoluteperformance.Itcanbebettertonotdosomework(oratleastdeferit)ratherthanspeeditup.
Thismaybecounterintuitive,especiallyconsideringhowindividualcomputeroperationscanbetooquicktoperceive.However,themultiplyingfactorisscale.Oneoperationmayberelativelyquick,butmillionsofthemmayaccumulatetoavisibledelay.Optimizingthesewillhaveacorrespondingeffectduetothemagnification.Improvingcodethatrunsinatightlooporforeveryuserisbetterthanfixingaroutinethatrunsonlyonceaday.
Slowerissometimesbetter
Insomesituations,processesaredesignedtobeslow,andthisisessentialtotheiroperationandsecurity.Agoodexampleofthis,whichmaybehitinprofiling,ispasswordhashingorkeystretching.Asecurepasswordhashingfunctionshouldbeslowsothatthepassword,which(despitebeingbadpractice)mayhavebeenreusedonotherservices,isnoteasilyrecovered.
Weshouldnotusegenerichashingfunctions,suchasMD5,SHA1,andSHA256,tohashpasswordsbecausetheyaretooquick.SomebetteralgorithmsthataredesignedforthistaskarePBKDF2andbcrypt,orevenArgon2fornewprojects.Alwaysremembertouseauniquesaltperpasswordtoo.Wewon'tgointoanymoredetailshere,butyoucanclearlyseethatspeeding
uppasswordhashingwouldbebad,andit'simportanttoidentifywheretoapplyoptimizations.
Whyissuesaremissed
Oneofthemainreasonsthatperformanceissuesarenotnoticedindevelopmentisthatsomeproblemsarenotperceivableonadevelopmentsystem.Issuesmaynotoccuruntillatencyincreases.Thismaybebecausealargeamountofdatawasloadedintothesystemandretrievingaspecificrecordtakeslonger.Thismayalsobebecauseeachpieceofthesystemisdeployedtoaseparateserver,increasingthenetworklatency.Whenthenumberofusersaccessingaresourceincreases,thenthelatencywillalsoincrease.
Forexample,wecanquicklyinsertarowintoanemptydatabaseorretrievearecordfromasmalltable,especiallywhenthedatabaseisrunningonthesamephysicalmachineasthewebserver.Whenawebserverisononevirtualmachineandthebigdatabaseserverisonanother,thenthetimetakenforthisoperationcanincreasedramatically.
Thiswillnotbeaproblemforonesingledatabaseoperation,whichappearsjustasquicktoauserinbothcases.However,ifthesoftwareispoorlywrittenandperformshundredsoreventhousandsofdatabaseoperationsperrequest,thenthisquicklybecomesslow.
Scalethisuptoalltheusersthatawebserverdealswith(andallofthewebservers)andthiscanbearealproblem.Adevelopermaynotnoticethatthisproblemexistsifthey'renotlookingforit,asthesoftwareperformswellontheirworkstation.Toolscanhelpinidentifyingtheseproblemsbeforethesoftwareisreleased.
Measuring
Themostimportanttakeawayfromthisbookistheimportanceofmeasuring.Youneedtomeasureproblemsoryoucan'tfixthem.Youwon'tevenknowwhenyouhavefixedthem.Measurementisthekeytofixingperformanceissuesbeforetheybecomenoticeable.Slowoperationscanbeidentifiedearlyon,andthentheycanbefixed.
However,notalloperationsneedoptimizing.It'simportanttokeepasenseofperspective,butyoushouldunderstandwherethechokepointsareandhowtheywillbehavewhenmagnifiedbyscale.We'llcovermeasuringandprofilinginthenextchapter.
ThebenefitsofplanningaheadByconsideringperformancefromtheverybeginning,itischeaperandquickertofixissues.Thisistrueformostproblemsinsoftwaredevelopment.Theearlieryoucatchabug,thebetter.Theworsttimetofindabugisonceitisdeployedandthenbeingreportedbyyourusers.
Performancebugsarealittledifferentwhencomparedtofunctionalbugsbecauseoften,theyonlyrevealthemselvesatscale,andyouwon'tnoticethembeforealivedeploymentunlessyougolookingforthem.Youcanwriteintegrationandloadteststocheckperformance,whichwewillcoverlaterinthisbook.
UnderstandinghardwareRememberthatthereisacomputerincomputerscience.Itisimportanttounderstandwhatyourcoderunsonandtheeffectsthatthishas,thisisn'tmagic.
StorageaccessspeedsComputersaresofastthatitcanbedifficulttounderstandwhichoperationisaquickoperationandwhichisaslowone.Everythingappearsinstant.Infact,anythingthathappensinlessthanafewhundredmillisecondsisimperceptibletohumans.However,certainthingsaremuchfasterthanothersare,andyouonlygetperformanceissuesatscalewhenmillionsofoperationsareperformedinparallel.
Therearevariousdifferentresourcesthatcanbeaccessedbyanapplication,andaselectionofthesearelisted,asfollows:
CPUcachesandregisters:L1cacheL2cacheL3cache
RAMPermanentstorage:
LocalSolidStateDrive(SSD)LocalHardDiskDrive(HDD)
Networkresources:LocalAreaNetwork(LAN)RegionalnetworkingGlobalinternetworking
VirtualMachines(VMs)andcloudinfrastructureservicescouldaddmorecomplications.Thelocaldiskthatismountedonamachinemayinfactbeasharednetworkdiskandrespondmuchslowerthanarealphysicaldiskthatisattachedtothesamemachine.Youmayalsohavetocontendwithotherusersforresources.
Inordertoappreciatethedifferencesinspeedbetweenthevariousformsofstorage,considerthefollowinggraph.Thisshowsthetimetakentoretrieveasmallamountofdatafromaselectionofstoragemediums:
Thisgraphhasalogarithmicscale,whichmeansthatthedifferencesareverylarge.Thetopofthegraphrepresentsonesecondoronebillionnanoseconds.SendingapacketacrosstheAtlanticOceanandbacktakesroughly150milliseconds(ms)or150millionnanoseconds(ns),andthisismainlylimitedbythespeedoflight.Thisisstillfarquickerthanyoucanthinkabout,anditwillappearinstantaneous.Indeed,itcanoftentakelongertopushapixeltoascreenthantogetapackettoanothercontinent.
ThenextlargestbaristhetimethatittakesaphysicalHDDtomovethereadheadintopositionto
startreadingdata(10ms).Mechanicaldevicesareslow.
ThenextbardownishowlongittakestorandomlyreadasmallblockofdatafromalocalSSD,whichisabout150microseconds.ThesearebasedonFlashmemorytechnology,andtheyareusuallyconnectedinthesamewayasaHDD.
Thenextvalueisthetimetakentosendasmalldatagramof1KB(1kilobyteor8kilobits)overagigabitLAN,whichisjustunder10microseconds.Thisistypicallyhowserversareconnectedinadatacenter.Notehowthenetworkitselfisprettyquick.Thethingthatreallymattersiswhatyouareconnectingtoattheotherend.Anetworklookuptoavalueinmemoryonanothermachinecanbemuchquickerthanaccessingalocaldrive(asthisisaloggraph,youcan'tjuststackthebars).
ThisbringsusontomainmemoryorRAM.Thisisfast(about100nsforalookup),andthisiswheremostofyourprogramwillrun.However,thisisnotdirectlyconnectedtotheCPU,anditisslowerthantheondiecaches.RAMcanbelarge,oftenlargeenoughtoholdallofyourworkingdataset.However,itisnotasbigasdiskscanbe,anditisnotpermanent.Itdisappearswhenthepowerislost.
TheCPUitselfwillcontainsmallcachesfordatathatiscurrentlybeingworkedon,whichcanrespondinlessthan10ns.ModernCPUsmayhaveuptothreeorevenfourcachesofincreasingsizeandlatency.Thefastest(lessthan1nstorespond)istheLevel1(L1)cache,butthisisalsousuallythesmallest.IfyoucanfityourworkingdataintothesefewMBorKBincaches,thenyoucanprocessitveryquickly.
ScalingapproachchangesFormanyyears,thespeedandprocessingcapacityofcomputersincreasedatanexponentialrate.ThiswasknownasMoore'sLaw,namedafterGordonMooreofIntel.Sadly,thiseraisnoMoore(sorry).Single-coreprocessorspeedshaveflattenedout,andthesedaysincreasesinprocessingabilitycomefromscalingouttomultiplecores,multipleCPUs,andmultiplemachines(bothvirtualandphysical).Multithreadedprogrammingisnolongerexotic,itisessential.Otherwise,youcannothopetogobeyondthecapacityofasinglecore.ModernCPUstypicallyhaveatleastfourcores(evenformobiles).Addinatechnologysuchashyper-threading,andyouhaveatleasteightlogicalCPUstoplaywith.Naïveprogrammingwillnotbeabletofullyutilizethese.
Traditionally,performance(andredundancy)wasprovidedbyimprovingthehardware.Everythingranonasingleserverormainframe,andthesolutionwastousefasterhardwareandduplicateallcomponentsforreliability.Thisisknownasverticalscaling,andithasreachedtheendofitslife.Itisveryexpensivetoscalethiswayandimpossiblebeyondacertainsize.Thefutureisindistributed-horizontalscalingusingcommodityhardwareandcloudcomputingresources.Thisrequiresthatwewritesoftwareinadifferentmannerthanwedidpreviously.Traditionalsoftwarecan'ttakeadvantageofthisscalinglikeitcaneasilyusetheextracapabilitiesandspeedofanupgradedcomputerprocessor.
Therearemanytrade-offsthathavetobemadewhenconsideringperformance,anditcansometimesfeellikemoreofablackartthanascience.However,takingascientificapproachandmeasuringresultsisessential.Youwilloftenhavetobalancememoryusageagainstprocessingpower,bandwidthagainststorage,andlatencyagainstthroughput.
Anexampleisdecidingwhetheryoushouldcompressdataontheserver(includingwhatalgorithmsandsettingstouse)orsenditrawoverthewire.Thiswilldependonmanyfactors,includingthecapacityofthenetworkandthedevicesatbothends.
ToolsandcostsLicensingofMicrosoftproductshashistoricallybeenaminefieldofcomplexity.Youcanevensitforanofficialexamonitandgetaqualification.Microsoft'srecentmovetowardopensourcepracticesisveryencouraging,asthebiggestbenefitofopensourceisnotthefreemonetarycostbutthatyoudon'thavetothinkaboutthelicensingcosts.Youcanalsofixissues,andwithapermissivelicense(suchasMIT),youdon'thavetoworryaboutmuch.Thetimecostsandcognitiveloadofworkingoutlicensingimplicationsnowandinthefuturecandwarfthefinancialsumsinvolved(especiallyforasmallcompanyorstartup).
ToolsDespitethenew.NETframeworkbeingopensource,manyofthetoolsarenot.SomeeditionsofVisualStudioandSQLServercanbeveryexpensive.Withthenewlicensingpracticeofsubscriptions,youwillloseaccessifyoustoppaying,andyouarerequiredtosignintodevelop.Previously,youcouldkeepusingexistingversionslicensedfromaMicrosoftDeveloperNetwork(MSDN)orBizSparksubscriptionafteritexpiredandyoudidn'tneedtosignin.
Withthisinmind,wewilltrytosticktothefree(community)editionsofVisualStudioandtheExpressversionofSQLServerunlessthereisafeaturethatisessentialtothelesson,whichwewillhighlightwhenitoccurs.Wewillalsouseasmanyfreeandopensourcelibraries,frameworks,andtoolsaspossible.
TherearemanyalternativeoptionsforlotsofthetoolsandsoftwarethataugmentstheASP.NETecosystem,andyoudon'tjustneedtousethedefaultMicrosoftproducts.ThisisknownastheALT.NET(alternative.NET)movement,whichembracespracticesfromtherestoftheopensourceworld.
LookingatsomealternativetoolsForversioncontrol,gitisaverypopularalternativetoTeamFoundationServer(TFS).Thisisintegratedintomanytools(includingVisualStudio)andservices,suchasGitHuborGitLab.Mercurial(hg)isalsoanoption.However,githasgainedthemostdevelopermindshare.VisualStudioOnlineoffersbothgitandTFSintegration.
PostgreSQLisafantasticopensourcerelationaldatabase,anditworkswithmanyObjectRelationalMappers(O/RMs),includingEntityFramework(EF)andNHibernate.Dapperisagreat,andhigh-performance,alternativetoEFandotherbloatedO/RMs.ThereareplentyofNoSQLoptionsthatareavailabletoo;forexample,RedisandMongoDB.
OthercodeeditorsandIntegratedDevelopmentEnvironments(IDEs)areavailable,suchasVisualStudioCodebyMicrosoft,whichalsoworksonAppleMacOSX.ASP.NETCore1.0(previouslyASP.NET5)runsonLinux(onMonoandCoreCLR).Therefore,youdon'tneedWindows(althoughNanoServermaybeworthinvestigating).
RabbitMQisabrilliantopensourcemessagequeuingserverthatiswritteninErlang(whichWhatsAppalsouses).ThisisfarbetterthanMicrosoftMessageQueuing(MSMQ),whichcomeswithWindows.Hostedservicesarereadilyavailable,forexample,CloudAMQP.
TheauthorhasbeenalongtimeMacuser(sincethePowerPCdays),andhehasrunLinuxserverssincewellbeforethis.It'spositivetoseeOSXbecomepopularandtoobservetheriseofLinuxonAndroidsmartphonesandcheapcomputers,suchastheRaspberryPi.YoucanrunWindows10onaRaspberryPi2and3,butthisisnotafulloperatingsystemandonlymeanttorunInternetofThings(IoT)devices.HavingusedWindowsprofessionallyforalongtime,developinganddeployingwithMacandLinux,andseeingwhatperformanceeffectsthisbringsisaninterestingopportunity.
Althoughnotopensource(oralwaysfree),itisworthmentioningJetBrainsproducts.TeamCityisaverygoodbuildandContinuousIntegration(CI)serverthathasafreetier.ReSharperisanawesomepluginforVisualStudio,whichwillmakeyouabettercoder.They'realsoworkingonaC#IDEcalledProjectRiderthatpromisestobegood.
ThereisaproductcalledOctopusDeploy,whichisextremelyusefulforthedeploymentof.NETapplications,andithasafreetier.Regardingcloudservices,AmazonWebServices(AWS)isanobviousalternativetoAzure,eveniftheAWSWindowssupportleavessomethingtobedesired.Therearemanyotherhostsavailable,anddedicatedserverscanoftenbecheaperforasteadyloadifyoudon'tneedthedynamicscalingofthecloud.
Muchofthisisbeyondthescopeofthisbook,butyouwouldbewisetoinvestigatesomeofthesetools.Thepointisthatthereisalwaysachoiceabouthowtobuildasystemfromthehugerangeofcomponentsavailable,especiallywiththenewversionofASP.NET.
Thenew.NETThenewASP.NETandthe.NETFrameworkthatitreliesuponwererewrittentobeopensourceandcross-platform.ThisworkwascalledASP.NET5whileindevelopment,butthishassincebeenrenamedtoASP.NETCore1.0toreflectthatit'sanewproductwithastrippeddownsetoffeatures.Similarly,.NETCore5isnow.NETCore1.0,andEntityFramework7isnowEntityFrameworkCore1.0.
ThewebapplicationframeworkthatwascalledASP.NETMVChasbeenmergedintoASP.NETCore,althoughit'sapackagethatcanbeaddedlikeanyotherdependency.ThelatestversionofMVCis6and,alongwithWebAPI2,thishasbeencombinedintoasingleproduct,calledASP.NETCore.MVCandWebAPIaren'tnormallyreferredtodirectlyanymoreastheyaresimplyNuGetpackagesthatareusedbyASP.NETCore.NotallfeaturesareavailableinthenewCoreframeworksyet,andthefocusisonserver-sidewebapplicationstostartwith.
Allthesedifferentnamescanbeperplexing,butnamingthingsishard.AvariationofPhilKarlton'sfamousquotegoeslikethis:
"ThereareonlytwohardthingsinComputerScience:cacheinvalidation,namingthings,andoff-by-oneerrors."
We'velookedatnaminghere,andwe'llgettocachinglateroninthisbook.
Itcanbealittleconfusingunderstandinghowalloftheseversionsfittogether.Thisisbestexplainedwithadiagramlikethefollowing,whichshowshowthelayersinteract:
ASP.NETCore1.0canrunagainsttheexisting.NETFramework4.6orthenew.NETCore1.0framework.Similarly,.NETCorecanrunonWindows,MacOSX,andLinux,buttheold.NETonlyrunsonWindows.
ThereisalsotheMonoframework,whichhasbeenomittedforclarity.Thiswasaprevious
projectthatallowed.NETtorunonmultipleplatforms.MonowasrecentlyacquiredbyMicrosoft,anditwasopensourced(alongwithotherXamarinproducts).Therefore,youshouldbeabletorunASP.NETCoreusingMonoonanysupportedoperatingsystem.
.NETCorefocusesonweb-applicationdevelopmentandserver-sideframeworks.Itisnotasfeaturefilledastheexisting.NETFramework.Ifyouwritenative-graphicaldesktopapplications,perhapsusingWindowsPresentationFoundation(WPF),thenyoushouldstickwith.NET4.6.
Asthisbookismainlyaboutweb-applicationdevelopment,wewillusethelatestCoreversionsofallsoftware.Wewillinvestigatetheperformanceimplicationsofvariousoperatingsystemsandarchitectures.Thisisparticularlyimportantifyourdeploymenttargetisacomputer,suchastheRaspberryPi,whichusesaprocessorwithanARMarchitecture.Italsohaslimitedmemory,whichisimportanttoconsiderwhenusingamanagedruntimethatincludesgarbagecollection,suchas.NET.
SummaryLet'ssumupwhatwecoveredinthisintroductorychapterandwhatwewillcoverinthenextchapter.Weintroducedtheconceptoftreatingperformanceasafeature,andwecoveredwhythisisimportant.Wealsobrieflytouchedonsomecommonperformanceproblemsandwhyweoftenmisstheminthesoftwaredevelopmentprocess.We'llcovertheseinmoredetaillateroninthisbook.
Weshowedtheperformancedifferencesbetweenvarioustypesofstoragehardware.Wehighlightedtheimportanceofknowingwhatyourcoderunsonand,crucially,whatitwillrunonwhenyourusersseeit.Wetalkedabouthowtheprocessofscalingsystemshaschangedfromwhatitusedtobe,howscalingisnowperformedhorizontallyinsteadofvertically,andhowyoucantakeadvantageofthisinthearchitectingofyourcodeandsystems.
Weshowedyouthetoolsthatyoucanuseandthelicensingimplicationsofsomeofthem.Wealsoexplainedthenewworldof.NETandhowtheselatestframeworksfitinwiththestableones.Wetoucheduponwhymeasurementisvitallyimportant.Inthenextchapter,we'llexpandonthisandshowyouhowtomeasureyoursoftwaretoseewhetherit'sslow.
Chapter2.MeasuringPerformanceBottlenecksMeasurementisthemostcrucialaspectofbuildinghighperformancesystems.Youcan'tchangewhatyoucan'tmeasure,becauseyouwon'tknowwhateffectyourchangehashad,ifany.Withoutmeasuringyourapplicationyouwon'tknowifit'sperformingwell.
Ifyouonlygobywhenyoursoftwarefeelsslowthenyouhaveleftittoolate.Youarereactivelyfixingaproblemratherthanproactivelyavoidingone.Youmustmeasuretoachievegoodperformanceeventhoughit'sthefeelthatmatterstoauser.
Somebooksleavemeasurement,analysis,andprofilinguntiltheend.Yetthisisthefirstthingthatshouldbeconsidered.It'seasytofixthewrongproblemandoptimizeareasthatarenothavingperformancedifficulties.
Inthischapterwewillcoverthefollowingtopics.
StructuredQueryLanguage(SQL)databaseprofilingSQLServerProfilerMiniProfiler
WebapplicationprofilingGlimpseIntegratedDevelopmentEnvironment(IDE)profilers
HTTPmonitoringBrowserdevelopertoolsFiddlerproxy
NetworkmonitoringMicrosoftmessageanalyzerWireshark
Scientificmethodandrepeatability
Thischapterwillshowyouhowtomeasureifthereareperformanceissuesandwheretheyareoccurring.Wewilldescribethetoolsthatcangiveyouthisinformationanddemonstratehowtousethemeffectivelyandcorrectly.We'llalsoshowyouhowtorepeatyourexperimentsconsistentlysothatyoucantellifyouhavefixedaproblemonceyou'veidentifiedit.
Wewillcovermeasurementagaintowardstheendofthebook,buttherewe'llfocusoncontinuousautomatedmonitoringtoavoidregressions.Thischapterwillfocusmoreonmanualtestingtoidentifypotentialperformanceproblemsduringdevelopmentanddebugging.
ToolsGooddebuggingtoolsareessentialindiscoveringwhereproblemslie.Youcanwriteyourowncrudetimingcodeandwewillshowyouhow.However,purposebuilttoolsaremuchnicertoworkwith.
Manyofthetoolsinthischapterhelpexamineareasexternaltoyourcode.Wewillcoverprofilingofcodetoo,butit'shardtoidentifyproblemsthiswayunlesstheworkispurelycomputational.Slowdownsoftenhappenbecauseofactionsyourappinitiatesoutsideofitsimmediatestack,andthesecanbehardtodebugbysimplysteppingthroughthecode.
Movingthroughyourprogramline-by-lineslowsdownexecutionsomuchthatitcanbedifficulttoidentifywhichlinesarefastandwhichareslow.Thesameapproachtakenforfixingfunctionalbugscannotalwaysbeappliedtofixperformanceissues.
Oneoftheproblemswithadoptinganewframework(suchasASP.NETCore)earlyisthatitcantakeawhilefortheexistingtoolstobeupdatedtoworkwithit.Wewillpointoutwhenthisisthecasebutthesecompatibilityproblemsshouldimproveovertime.Asmanyofthetoolsareopensource,youcouldhelpoutandcontributetothecommunity.
SQLFirstoffwewillcoverSQLrelatedissues,soifyou'renotusingarelationaldatabasethenyoucanskipthisbit,perhapsifyou'reusingaNoSQLstoreoradocumentdatabaseinstead.Relationaldatabasesareaverymaturetechnologyandareflexibleintheiruses.However,itisessentialtohaveabasicknowledgeoftheSQLsyntaxandhowdatabasesworkinordertousethemeffectively.
ItcanbetemptingwhenusinganO/RMsuchasEntityFramework(EF)toignoreSQLandstayinaC#world,butacompetentdevelopershouldbeabletowriteahighperformanceSQLquery.Ignoringtherealitiesofhowadatabaseengineworkswilloftenleadtoperformanceissues.It'seasytowritecodewithanO/RMthat'stoochattywiththedatabaseandissuesfartoomanyqueriesforanoperation.Nothavingthecorrectindexesonatablewillalsoresultinpoorperformance.
Duringdevelopmentyoumaynotnoticethesemistakes,unlessyouusetoolstoidentifytheinefficienteventsoccurring.Herewewillshowyouacoupleofwaysofdoingthis.
SQLServerProfiler
SQLServerProfilerisatoolthatallowsyoutoinspectwhatcommandsarebeingexecutedonyourSQLServerdatabase.Ifyouhavethemanagementtoolsinstalledthenyoushouldalreadyhaveitonyourmachine.
1. IfyouareusingMicrosoftSQLServer,thenSQLServerProfilercanbeaccessedfromtheToolsmenuofSQLServerManagementStudio(SSMS).
2. LoadSQLServerProfilerandconnecttothedatabasethatyouareusing.NameyourtraceandselecttheTuningprofiletemplate.
3. ClickRunandyoushouldseethatthetracehasbegun.Youarenowreadytorunyourcodeagainstthedatabasetoseewhatqueriesit'sactuallyexecuting.
Executingasimplequery
AsatestyoucanexecuteasimpleselectquerywithManagementStudioandtheprofilewindowshouldbefloodedwithentries.Locatethequerythatyoujustexecutedamongthenoise.Thisis
easierifitstartswithacomment,asshowninthefollowingscreenshot.
TheDurationcolumnshowsthetimetakenforthequeryinmilliseconds(ms).Inthisexample,selectingthetop1000rowsfromatablecontainingoveramillionentriestook246ms.Thiswouldappearveryquick,almostinstantaneous,totheuser.Modifyingthequerytoreturnallrowsmakesitmuchslower,asshowninthefollowingscreenshot:
Thequeryhasnowtakenover13seconds(13455ms)tocomplete,whichisnoticeablyslow.Thisisanextremeexample,butitisquiteacommonmistaketorequestmoredatathanneededandtofilterorsortitinapplicationcode.Thedatabaseisoftenmuchbettersuitedtothistaskandisusuallythecorrectlocationtoselectthedatayouwant.
WewillcoverspecificSQLmistakesandremediesinthefollowingchapters.However,thefirststepisknowinghowtodetectwhatisgoingonwiththecommunicationbetweenyourapplicationandthedatabase.Ifyoucan'tdetectthatyourappismakinginefficientqueriesthenitwillbedifficulttoimproveperformance.
MiniProfiler
MiniProfilerisanexcellentopensourcetoolfordebuggingdataqueries.ItsupportsSQLdatabasesandsomeNoSQLdatabases,suchasMongoandRaven.ItcameoutofStackExchange,thepeoplewhoruntheStackOverflowQ&Asite.Itembedsawidgetintoyourwebpagesthatshowsyouhowlongtheytaketogettheirdata.ItalsoshowsyoutheSQLqueriesandwarnsyouaboutcommonmistakes.AlthoughMiniProfilerstartedwith.NET,itisalsoavailableforRuby,Go,andNode.js.
ThebiggestbenefitofMiniProfileroverSQLServerProfileristhatit'salwaysthere.Youdon'tneedtoexplicitlygolookingforSQLproblemsandsoitcanhighlightissuesmuchearlier.It'sevenagoodideatorunitinproduction,onlyvisibletologgedinadmins.Thisway,everytimeyouworkonthewebsiteyouwillseehowthedataaccessisperforming.Makesureyoutestfortheperformanceimpactsofthisbeforedeployingitthough.
UnfortunatelyMiniProfilerdoesn'tyetsupportASP.NETCore1.0.ItreliesontheSystem.Weblibraryanddoesn'ttieintotheOpenWebInterfacefor.NET(OWIN)stylelifecycleusedbythenewframework.HopefullyitwillsoonsupportASP.NETCore(andmaydobythetimeyoureadthis)asit'saveryusefultool.
Tip
Ifyou'reusingasupportedversionofASP.NETthenMiniProfilerishighlyrecommended.ASP.NETCoresupportisplanned,sokeepaneyeonANCLAFS.comforthelatestsupportdetails.
Duetotheselimitations,wewon'tcoverMiniProfilerintoomuchdetailbutyoucangetmoreinformationatminiprofiler.com.IfyouareusingapreviousversionofASP.NETthenyoucaninstallitintoyourprojectwiththeNuGetpackagemanager.TypeInstall-PackageMiniProfilerintothepackagemanagerPowerShellconsolewindowinVisualStudio.Thenfollowtherestofthesetupinstructionsfromthewebsite.
ApplicationprofilingOftenyouwillwantabreakdownofwhereallthetimeisbeingtakenupwithinyourapplication.Therearevarioustoolsavailableforthisandwewillcoveracoupleofthemhere.
Glimpse
Glimpseisafantasticopensourceadd-onforyourwebapplication.LikeMiniProfiler,itaddsawidgettoyourwebpagessothatyoucanseeproblemsasyounavigatearoundandworkonyoursite.Itprovidesinformationsimilartoyourbrowserdevelopertoolsbutalsodelvesinsideyourserversideapplicationtoshowyouatraceofwhatactionsaretakingthemosttime.
Glimpseisavailablefromgetglimpse.comandyoucaninstallitwithNuGetforthewebframeworkandO/RMyou'reusing.ForASP.NETCorewewillneedtouseGlimpseversion2.Thisiscurrentlyabetaprerelease,butbythetimeyoureadthisitmaybestable.
UsingGlimpse
InstallingGlimpseisreallysimple,thereareonlythreesteps.
1. InstallwithNuGet.2. AddlinestoStartup.cs.3. Buildandruntheapp.
Let'shavealookatthesesteps.
Installingthepackage
Right-clickonyourwebapplicationprojectintheSolutionExplorerandselectManageNuGetPackages...toopenthegraphicalpackagemanagerwindow.SearchforGlimpse,selectit,andthenclickontheInstallbutton.IfyouwanttoinstallthebetaversionofGlimpse2,thenmakesuretheIncludeprereleasecheckboxisselected:
Addcode
YouneedtoaddthreesnippetsofcodetoyourStartup.csfile.Intheusingdirectivesatthetopofthefile,addthefollowing:
usingGlimpse;
IntheConfigureServicesfunction,addthefollowing:
services.AddGlimpse();
IntheConfigurefunction,addthefollowing:
app.UseGlimpse();
Runningyourwebapplication
BuildandrunyourwebapplicationbypressingF5.Ifyouencounteraduplicatetypeerrorwhenrunningthensimplycleanthesolutionanddoafullrebuild.Youmayneedtoapplymigrationstothedatabase,butthisisjustabuttonclickinthebrowser.However,ifyouaddthistoanexistingprojectwithdata,thenyoushouldtakemorecare.
YoushouldthenlookatyourwebapplicationwiththeGlimpsebaratthebottomofthebrowserwindow,whichlookslikethefollowingscreenshot.Thebarisonelongstrip,butithasbeenbrokenupinthisscreenshottodisplayitmoreclearly:
Note
Thefirstpageloadmaytakemuchlongerthansubsequentones,soyoushouldrefreshformorerepresentativedata.However,wewon'tworryaboutthisforthepurposesofthisdemo.
MouseovereachsectionintheGlimpsetoolbartoexpanditformoreinformation.Youcanminimizeandrestoreeachsection(HTTP,HOST,orAJAX)byclickingonitstitle.
Ifyouusedthedefaultwebapplicationtemplate(andlefttheauthenticationasthedefaultindividualuseraccounts),thenyoucanregisteranewusertocausetheapplicationtoperformsomedatabaseoperations.YouwillthenseesomevaluesintheDBqueriesfield,asshowninthe
followingscreenshot:
ClickontheGlimpselogotoseeahistoryofallthepagerequests.SelectonetoviewthedetailsandexpandtheSQLqueriesbyclickingonthem,whichisdisplayedinthefollowingscreenshot:
GlimpseshowsyouhowmuchtimeisspentineachlayerofyourapplicationandexactlywhichSQLqueriesarebeingrun.Inthiscase,EFCore1.0generatestheSQL.
Glimpseisveryusefultotrackdownwhereperformanceproblemslie.Youcaneasilyseehow
longeachpartofthepagepipelinetakesandidentifyslowparts.
IDE
UsingtheprofilingtoolsthatarebuiltintoVisualStudio(VS)canbeveryinformativetounderstandtheCPUandmemoryusageofyourcode.Youcanalsoseethetimetakenforcertainoperations.
Whenrunningyourapplication,openthediagnostictoolswindowinVS,asshowninthefollowingscreenshot:
YoucanseetheCPUandmemoryprofiles,includingtheautomaticGarbageCollectioneventsthatareusedtofreeupmemory(themarkerjustpriortomemoryusedecreasing).Youwillbeabletoseebreakpointeventsand,ifyouhavetheenterpriseversionofVS,IntelliTraceeventsaswell.
Note
IntelliTraceisonlyavailableintheenterpriseeditionofVisualStudio.However,youcanstillusetheperformanceanddiagnostictoolsinthefreecommunityedition.
IfyouhaveIntelliTrace,thenyoucanfinditintheVSoptions,asshowninthefollowing
screenshot.However,thediagnostictoolsarestillusefulwithoutthispremiumfeature:
Whenyouputinabreakpointandyourcodehitsit,thenVSwilltellyouhowlongitwassincethepreviousevent.Thisisshownintheeventslistandalsooverlaidnearthebreakpoint.
Tip
Youcan'tinstallthecommunityeditionandenterpriseeditionofVisualStudioonthesamemachine.UseaVirtualMachine(VM),forexample,withHyper-VorVirtualBox,ifyouwishtorunboth.
AlternativestoVStoolsareRedgateANTSandTelerikJustTrace.JetBrainsalsohavedotTraceanddotMemory.However,allofthesetoolscanbequiteexpensiveandwewon'tcoverthemhere.
MonitoringHTTPWhendealingwithawebapplication,youwillnormallyuseHTTPastheapplicationprotocol.It'sveryusefultoknowwhatrequestsoccurbetweenthebrowsersandyourservers.
Browsers
Mostmodernbrowsershaveexcellentdevelopertools,whichincludeanetworktabtomonitorrequeststoandresponsesfromthewebserver.YoucannormallyaccessthedevtoolsbypressingF12.Thesearehandytoviewthewebtrafficandyoucanstillseeencryptedcommunicationswithoutmessingaboutwithcertificates.
ThedevtoolsinbothChromeandFirefoxaresuperb.We'llfocusonthenetworkandtimingcomponent,butwehighlyrecommendthatyoulearnallofthefeatures.Ifyouknowhowtogetthebestoutofthem,thenwebdevelopmentismucheasier.
Chrome
ThenetworkdevtoolsinChromeareveryuseful.Theyprovideagoodvisualizationoftherequesttimings,andyoucanthrottletheconnectiontoseehowitbehavesovervariousdifferentinternetconnections.Thisisparticularlyimportantformobiledevices.
AselectionofnetworkrequestsfromtheChromedevtoolsareshowninthefollowingscreenshot.Additionalcolumnsareavailableifyouright-clickontheHeadersbar:
Youcandisablethecachewithasimplecheckboxsothatthebrowserwillalwaysloadassetsfreshfromyourwebserver.Youcanalsoclickonaresourceformoreinformationandthetimingtabisveryusefultoprovideabreakdownoftheconnectioncomponents,forexample,TimeToFirstByte(TTFB).Somebasictimingdetailsfromalocalwebserverareshowninthefollowingscreenshot:
Onalocalwebserver,thisbreakdownwon'tcontainmuchextrainformation,butonaremoteserveritwilldisplayotherthings,suchastheDomainNameSystem(DNS)hostnamelookup,andSSL/TLShandshake.Theseadditionalcomponentsareshowninthenextscreenshot:
Firefox
FirefoxhassimilardevtoolstoChromebutwithsomeaddedfeatures.Forexample,youcaneditarequestandresendittothewebserver.TheNetworktabpresentsthesamesortofinformationasChromedoes,asshowninthefollowingscreenshot:
Thedetailviewisalsoverysimilar,includingtheTimingstab.Thistabisshowninthefollowingscreenshot:
Fiddler
Sometimes,browsertoolsaren'tenough.Perhaps,youaredebugginganativeapplication,backendwebclient,ormobilebrowser.FiddlerisafreedebuggingproxythatcancaptureallHTTPtrafficbetweentheclientandserver.Withalittlebitofwork,itcanalsointerceptHTTPStraffic.Fiddlerisavailableatwww.telerik.com/fiddler.
Asthisbookfocusesonwebdevelopmentwewon'tgointomoredetail.Thebrowserdevtoolsaresuitableformostworkthesedays.TheynowfulfilalargepartoftherolethatFiddlerusedtoplaybeforetheyacquiredthesamefeatures.FiddlerisstillthereifyouneeditanditcanbehandyifyourwebservercallsanexternalHTTPAPI.AlthoughthiscanalsooftenbedebuggeddirectlyinsideVS.
NetworkOccasionally,youwillneedtodebugatalowerlevelthanHTTPorSQL.Thisiswherenetworkmonitorsorpacketsnifferscomein.Perhaps,youwanttodebugaTabularDataStream(TDS)messagetoaSQLServerDBoraTLShandshaketoanSSLterminatingloadbalancer.OrmaybeyouwanttoanalyzeaSOAPwebserviceenvelopeorSimpleMailTransferProtocol(SMTP)e-mailconnectiontoseewhyit'snotworkingcorrectly.
MicrosoftMessageAnalyzer
MicrosoftMessageAnalyzersupersedesMicrosoftNetworkMonitor(Netmon)andisatooltocapturenetworktrafficonWindowssystems.Netmonrequiresyoutologoutandbackinagainafterinstallation,whereasWiresharkdoesn't.YoucanreadmoreaboutthesetwoMicrosofttoolsonline,but,forclarityandbrevity,wewillfocusonWiresharkforlow-levelnetworkmonitoring.
Wireshark
Wireshark(previouslycalledEthereal)isanopensourceandcross-platformpacketcaptureandnetworkanalysisapplication.Itisprobablythemostpopulartoolofitskindandhasmanyuses.YoucaninstallWiresharkwithoutneedingtorestartorlogoutwhichmakesitgreattodebugaliveproblemthat'shardtorecreate.YoucandownloadWiresharkfromwww.wireshark.organditrunsonWindows,MacOSX,andLinux.
Wiresharkisn'tparticularlyusefulforlocaldevelopmentasitonlycapturestrafficgoingoverthenetwork,nottolocalhost.TheonlythingyouarelikelytoseeifyourunitagainstalocalwebapplicationisVSreportingwhatyoudobacktoMicrosoft.
Tip
YoucanturnofftheCustomerExperienceImprovementProgram(CEIP)byclickingonthebuttonnexttothequicklaunchboxandselectingSettings....Bydefault,itison(it'snowopt-outratherthantheopt-inofpreviousproducts).
Clickonthefiniconbuttonatthetop-leftofWiresharktostartatrace.Thenperformsomenetworkactions,suchasloadingawebpagefromatestserver.Onceyoucapturesomepackets,clickonthestopbuttonandyoucanthenexaminethecollecteddataatyourleisure.
Note
AskyourITadministratorbeforerunningWireshark.ItcanoftenpickupsensitiveinformationoffoftheLAN,whichmaybeagainstyourITacceptableusepolicy.
ThefollowingscreenshotshowspartoftheresultsfromaWiresharkcapture.
TherecanbealotofnoisewhenusingWireshark.Youwillseelow-levelnetworkpackets,suchasAddressResolutionProtocol(ARP)traffic,whichyoucanfilteroutorignore.YoumayalsoseedatafromVoIPphonesandothernetworkeddevicesordatathatisintendedforothercomputersonthenetwork.
Selectthepacketthatyouareinterestedinfromthetoppane.Themiddlepanewilldisplaythecontentsofthepacket.Youcannormallyignorethelowerlayersofthenetworkstack,suchasEthernetandTCP/IP(presentedatthetopofthelist).
Divestraightintotheapplicationlayerthatislistedlast.IfthisisaprotocolthatWiresharkrecognizes,thenitwillbreakitdownintothefieldsthatit'smadeupof.
Thebottompanedisplaysahexdumpoftherawpacket.Thisisnotnormallyasusefulastheparseddatainthemiddlepane.
IfyouuseTLS/SSL(hint:youshould),thenyouwon'tseethecontentsofHTTPtraffic.Youwouldneedacopyoftheserver'sprivatekeytoseeinsidetheTLSconnection,whichwrapsandencryptstheHTTPapplicationdata.YouwillonlybeabletoseethedomainthatwasconnectedtoviatheDNSlookupandTLScertificate,notthefullURLoranypayloaddata.
UsingWiresharkisahugetopic,andtherearemanygreatresourcesavailabletolearnaboutit,bothonlineandoffline.Wewon'tgointomuchmoredetailherebecauseit'susuallynotnecessarytogodowntothislowlevelofnetworkscrutiny.However,thisisagoodtooltohaveinyourbackpocket.
RollyourownSometimes,youmaywanttowriteyourownperformancemeasurementcode.Makesurethatyouhaveexhaustedallotheroptionsandinvestigatedtheavailabletoolsfirst.
Note
Perhaps,youwanttorecordtheexecutiontimeofsomeprocesstowritetoyourlogs.MaybeyouwanttosendthistoasystemsuchasLogstashthenvisualizethechangesovertimewithKibana.BotharegreatopensourceproductsfromElastic,andtheystoredataintheElasticsearchsearchserver.Youcanreadmoreaboutbothofthesetoolsatelastic.co
Youcaneasilyrecordthelengthoftimeforataskbystoringthecurrenttimebeforeitstartsandcomparingthistothecurrenttimeafteritfinishes,butthisapproachhasmanylimitations.Theactofmeasuringwillaffecttheresulttosomeextent,andtheclockisnotaccurateforshortdurations.Itcanbeusefulforreallysloweventsifyouneedtosharestatesbetweenprocessesormultipleruns,but,tobenchmark,youshouldnormallyusetheStopwatchclass.
Tip
ItisusuallybesttostoretimestampsinCoordinatedUniversalTime(UTC),whichisotherwiseknownasGreenwichMeanTime(GMT),andnametimestampsinUTC.YouwillavoidmanyissueswithtimezonesanddaylightsavingifyouuseDateTimeOffset.UtcNow(oratleastDateTime.UtcNow).Namevariablesandcolumnstoindicatethis,forexample,TimestampUtc.
UseTimeSpanforlengthsoftime,but,ifyoumustuseprimitives(suchasintegers),thenincludetheunitsinthevariableorcolumnname.Forexample,DurationInMillisecondsorTimeoutInSeconds.Thiswillhelptoavoidconfusionwhenanotherdeveloper(oryourfutureself)comestousethem.
However,tobenchmarkquickoperations,youshoulduseaStopwatch.ThisclassisintheSystem.Diagnosticsnamespace.
Ifyoutrytomeasureasinglequickevent,thenyouwillnotgetaccurateresults.Awayaroundthisistorepeatthetaskmanytimesandthentakeanaverage.Thisisusefultobenchmark,butitisnotusuallyapplicabletorealapplications.However,onceyouidentifywhatworksquickestwithatest,thenyoucanapplyittoyourownprograms.
Let'sillustratethiswithasmallexperimenttotimehowlongittakestohashapasswordwiththePBKDF2algorithm(intheSystem.Security.Cryptographynamespace).Inthiscase,theoperationundertestisnotimportant,aswearesimplyinterestedinthetimingcode.ANaïveapproachmaylooklikethefollowingcode:
vars=Stopwatch.StartNew();
pbkdf2.GetBytes(2048);
s.Stop();
Console.WriteLine($"Testduration={s.ElapsedMilliseconds}ms");
Thiscodewilloutputadifferentvalueeverytimeitisrun,duetotheflawsinthemeasurementprocess.Abetterwaywouldbetorepeatthetestmanytimesandaveragetheoutput,likethefollowingcode:
vars=Stopwatch.StartNew();
for(varii=0;ii<tests;ii++)
{
pbkdf2.GetBytes(2048);
}
s.Stop();
varmean=s.ElapsedMilliseconds/tests;
Console.WriteLine($"{tests}runsmeanduration={mean}ms");
Thiscodewilloutputverysimilarresultseverytime.Thehigherthevalueoftests,themoreaccurateitwillbe,butthelongerthetestwilltake.
Note
Weusethenewconcisestring-formattingmethodhere,butyoucanusethetraditionaloverloadstoConsole.WriteLineifyouprefer.
Let'swriteaquickexampleapplicationthatdemonstratesthedifferencesbyrunningthesetwodifferentversionsmultipletimes.We'llextractthetwotestsintomethodsandcallthemeachafewtimes:
varpbkdf2=newRfc2898DeriveBytes("password",64,256);
SingleTest(pbkdf2);
SingleTest(pbkdf2);
SingleTest(pbkdf2);
Console.WriteLine();
vartests=1000;
AvgTest(pbkdf2,tests);
AvgTest(pbkdf2,tests);
AvgTest(pbkdf2,tests);
Console.WriteLine();
Console.WriteLine("Pressanykey...");
Console.ReadKey(true);
Theoutputwilllooksomethinglikethefollowingscreenshot.Youcanfindthefullapplicationlistinginthecodethataccompaniesthisbookifyouwanttorunitforyourself:
Youcanseethatthethreeindividualtestscangivewildlydifferentresultsandyettheaveragedtestsareidentical.
Tip
DetailedstepstodownloadthecodebundlearementionedinthePrefaceofthisbook.Pleasehavealook.ThecodebundleforthebookisalsohostedonGitHubathttps://github.com/PacktPublishing/ASP.NET-Core-1.0-High-Performance.Wealsohaveothercodebundlesfromourrichcatalogofbooksandvideosavailableathttps://github.com/PacktPublishing/.Checkthemout!
Yourresultswillvary.Thisisduetotheinherentvariabilityincomputersystems.EmbeddedsystemsthataretimesensitiveusuallyusearealtimeOS.Normalsoftwaresystemstypicallyrunonatime-sharingOS,whereyourinstructionscaneasilygetinterrupted,andVMsmaketheproblemevenworse.
Youwillgetdifferentresults,dependingonwhetheryoubuildindebugorreleasemodeandifyourunwithorwithoutdebugging.Releasemodewithoutdebugging(Ctrl+F5)isthefastest.
Thefollowingscreenshotshowsthesamebenchmarkingdemoapplicationrunningwithdebugging.Youcantellbecausethedotnetexecutableisshowninthetitlebarofthecommandprompt.Ifitranwithoutdebugging,thenthiswoulddisplaycmd.exe(onWindows),asinthepreviousscreenshot.
Note
UnittestingisveryvaluableandyoumayevenpracticeTest-DrivenDevelopment(TDD),butyoushouldbecarefulaboutincludingperformancetestsasunittests.Unittestsmustbequicktobevaluable,andteststhataccuratelymeasurethetimetakenforoperationsareoftenslow.Youshouldsetatimeoutonyourunitteststomakesurethatyoudon'twriteslowoneswithexternaldependencies.Youcanstilltestperformance,butyoushoulddoitintheintegrationtestingstagealongwithteststhathitanAPI,DB,ordisk.
ScienceWedealtwiththecomputerincomputersciencebyshowcasingsomehardwareinthepreviouschapter.Now,it'stimeforthesciencebit.
It'simportanttotakeascientificapproachifyouwishtoachieveconsistentlyreliableresults.Haveamethodologyortestplanandfollowitthesamewayeverytime,onlychangingthethingthatyouwanttomeasure.Automationcanhelpalotwiththis.
It'salsoimportanttoalwaysmeasureforyourusecaseonyoursystemswithyourdata.Whatworkedwellforsomeoneelsemaynotworkoutgreatforyou.
Wewilltalkmoreaboutscienceandstatisticslaterinthebook.Takingasimpleaveragecanbemisleadingbutit'sfinetouseitasagentleintroduction.ReadChapter8,TheDownsidesofPerformanceEnhancingTools,formoreonconceptssuchasmediansandpercentiles.
RepeatabilityResultsneedtoberepeatable.Ifyougetwildlydifferentresultseverytimeyoutest,thentheycan'tbereliedupon.Youshouldrepeattestsandtaketheaverageresulttonormalizeoutanyvariabilityintheapplicationorhardwareundertest.
Itisalsoimportanttoclearlyrecordtheunitsofmeasurement.Whenyoucompareanewvaluetoahistoricone,youneedtoknowthis.NASAfamouslylostaMarsprobebecauseofunitconfusion.
Onlychangeonething
Whentesting,youaimtomeasuretheimpactofasinglechange.Ifyouchangemorethanonethingatatime,thenyoucannotbesurewhichonehasmadethedifference.
Theaimistominimizetheeffectsofanyotherchangesapartfromtheoneyouareinterestedin.Thismeanskeepingexternalfactorsasstaticaspossibleandperformingmultipletests,takingtheaverageresult.
SummaryLet'ssumupwhatwecoveredaboutmeasurementinthischapterandwhatwe'llcoverinthenextchapter.Wecoveredtheimportanceofmeasurementinsolvingperformanceproblems.Withoutmeasuring,youcannothopetowritehigh-performancesoftware;youwillbecodinginthedark.
Wehighlightedsomeofthetoolsthatyoucanusetomeasureperformance.Weshowedyouhowtouseaselectionoftheseandhowtowriteyourown.
Wealsocoveredthevalueoftakingascientificapproachtomeasurement.Makingsurethatyourresultsarerepeatableandthatyourecordthecorrectunitsofmeasurementareimportantconcerns.
Inthenextchapter,wewilllearnhowtofixcommonperformanceproblems.Youwillgaintheskillstospeedupthelow-hangingfruitandmakeyourselflooklikeaperformancewizardtoyourcolleagues.Nolongerwillitbeacaseofitworkedintest,it'sanoperationsproblemnow.
Chapter3.FixingCommonPerformanceProblemsThischaptergetsintothemeatofoptimization,onceyouidentifyandlocateperformanceproblems.Itcoversaselectionofthemostcommonperformanceissuesacrossavarietyofareasandexplainssimplesolutionstosomeofthemistakespeopleoftenmake.Whenusingthesetechniques,you'lllooklikeawizardtoyourclientsandcolleaguesbyquicklyspeedinguptheirsoftware.
Topicscoveredinthischapterincludethefollowing:
NetworklatencySelectN+1problemsDiskI/OissuesonvirtualmachinesAsynchronousoperationsinawebapplicationPerformingtoomanyoperationsinonewebrequestStaticsitegeneratorsPragmaticsolutionswithhardwareShrinkingoverly-largeimages
Mostoftheproblemsinthischaptercenteronwhathappenswhenyouaddlatencytocommonoperationsorwhenthroughputisreducedfromwhatitwasindevelopment.ThingsthatworkedfineintestwheneverythingwasononephysicalmachinewithminimaldataarenownolongerquiteasspeedywhenyouhaveanAPIonadifferentcontinent,afulldatabaseonadifferentmachinetoyourwebserver,anditsvirtualdisksomewhereelseonthenetworkentirely.
Youwilllearnhowtoidentifyandfixissuesthatarenotalwaysapparentwheneverythingisrunningonasinglemachine.You'llseehowtoidentifywhenyourO/RMorframeworkbehavesbadlyandistoochattywiththedatabase,whichcaneasilyhappenifit'snotusedcorrectly.
Wewillseehowtoensurethatworkisperformedinthemostappropriateplace,andwe'lllookatsomewaysofkeepingyourimagessmallusingthecorrectresolutionandformat.Thesetechniqueswillensurethatyourapplicationisefficientandthatdataisnotsentoverthewireunnecessarily.
We'llalsodiscusshowtomitigateperformanceissueswithanalternativeapproachbyimprovingtheunderlyinghardwaretoreducethefactorsthatamplifyissuesinbadsoftware.Thiscanbeagoodtemporarymeasureifthesoftwareisalreadydeployedtoproductionandinuse.Ifyoualreadyhaveliveperformanceproblemsthenthiscanbuyyousometimetoengineeraproperfix.
LatencyAscoveredinpreviouschapters,latencyisthedelaythatoccursbeforeanoperationcancomplete,sometimesalsoknownaslag.Youmaynotbeabletocontrolthelatencyoftheinfrastructurethatyoursoftwarerunson,butyoucanwriteyourapplicationinsuchawaythatitcancopewiththislatencyinagracefulmanner.
Thetwomaintypesoflatencythatwewilldiscussherearenetworklatencyanddisklatency.Asthenamessuggesttheseare,respectively,thedelayinperforminganoperationoverthenetworkandthedelaytoreadfromorwritetoapersistentstoragemedium.Youwilloftendealwithbothatthesametime,forexample,adatabase(DB)querytoaserveronaremotevirtualmachinewillrequirethefollowingoperations:
AnetworkoperationfromwebservertoDBserverAnetworkoperationfromDBservertoremotediskonaStorageAreaNetwork(SAN)Adiskoperationtolookupdataonthephysicaldrive
Note
AlthoughSolidStateDrives(SSDs)havemuchlowerlatencythanspinningplatterdisks,theyarestillrelativelyslow.WhenwetalkaboutdiskI/Ohere,werefertobothtypesofdrive.
Youcanclearlyseethat,ifyouissuetoomanyDBoperations,thelatencypresentintypicalproductioninfrastructurewillcompoundtheproblem.YoucanfixthisbyminimizingthenumberofDBoperationssothattheycan'tbeamplifiedasmuch.
Let'sillustratethiswithanexample.Let'ssupposeyouwishtoreturn200recordsfromyourDBandtheroundtriplatencyis50milliseconds(ms).Ifyouretrievealloftherecordsatonce,thenthetotaltimewillbe50msplusthetimetotransfertherecords.However,ifyoufirstretrievealistoftherecordidentifiersandthenretrieveallofthemindividually,thetotaltimewillbeatleast201*50ms=10.05seconds!
Unfortunately,thisisaverycommonmistake.Inasystemwherelatencydominatesthroughput,itisimportanttokeeprequeststoaminimum.
AsynchronousoperationsMostnew.NETframeworkAPIsthathavesignificantlatencywillhaveasynchronous(async)methods.Forexample,the.NETHTTPclient(supersedingthewebclient),SMTPclient,andEntityFramework(EF)allhaveasyncversionsofcommonmethods.Infact,theasyncversionisusuallythenativeimplementationandthenon-asyncmethodissimplyablockingwrappertoit.Thesemethodsareverybeneficialandyoushouldusethem.However,theymaynothavetheeffectthatyouimaginewhenappliedtowebapplicationprogramming.
Note
Wewillcoverasyncoperationsandasynchronousarchitecturelaterinthisbook.We'llalsogointoMessageQueuing(MQ)andworkerservices.Thischapterisjustaquickintroductionandwewillsimplyshowyousometoolstogoafterthelow-hangingfruitonwebapplications.
AnasyncAPIreturnscontroltothecallingmethodbeforeitcompletes.Thiscanalsobeawaitedsothatoncompletion,executionresumesfromwheretheasynchronouscallwasmade.Withanativedesktopormobileapplication,awaitinganasyncmethodreturnscontroltotheuserinterface(UI)thread,whichmeansthatthesoftwareremainsresponsivetouserinput.Theappcanprocessuserinteractionsratherthanblockingonyourmethod.Traditionally,youmayhaveusedabackgroundworkerforthesetasks.
YoushouldneverperformexpensiveworkontheUIthread.Therefore,thistechniquedoesincreaseperformancefornativeapplications.However,forawebapplicationthisUIblockingproblemdoesnotexistbecausethebrowseristheUI.Therefore,thistechniquewillnotincreaseperformanceforasingleuserinisolation.
AwaitingasynchronousAPImethodsinawebapplicationisstillgoodpractice,butitonlyallowsthesoftwaretoscalebetterandhandlemoreconcurrentusers.Awebrequesttypicallycannotcompleteuntiltheasyncoperationalsocompletes.Therefore,althoughthethreadissurrenderedbackintothethreadpoolandyoucanuseitforotherrequests,theindividualwebrequestwillnotcompletequicker.
SimpleasynchronoustoolsAsthisbookdealswithwebapplicationprogramming,wewon'tgointomuchmoredetailonnativeapplicationUIsinthischapter.Instead,wewillshowcasesomesimpletoolsandtechniquesthatcanhelpwithasynctasksinwebapplications.
Thetoolsweareabouttocoveroffersomesimplesolutionsthatareonlysuitableforverysmallapplications.Theymaynotalwaysbereliable,butsometimestheycanbegoodenough.Ifyouareafteramorerobustsolution,thenyoushouldreadthelaterchaptersaboutdistributedarchitecture.
BackgroundqueuingBackgroundqueuingisausefultechniquewhenyouhaveanoperationthatdoesnotneedtooccurstraightaway.Forexample,loggingstatstoadatabase,sendingane-mail,orprocessingapaymenttransaction.Ifyouperformtoomuchworkinasinglewebrequest,thenbackgroundqueuingmayofferaconvenientsolution,especiallyifyoudon'trequiretheoperationtoalwayssucceed.
IfyouuseASP.NET4.6(oranyversionfrom4.5.2onwards),thenyoucanuseHostingEnvironment.QueueBackgroundWorkItemtorunamethodinthebackground.Thisispreferabletosimplysettingataskrunning,asifASP.NETshutsdownthenitwillissueacancellationrequestandwaitforagraceperiodbeforekillingtheitem.However,thisstilldoesnotguaranteecompletionbecausetheapplicationcandieatanypointduetoanunexpectedrebootorhardwarefailure.Ifthetaskneedstocomplete,thenitshouldbetransactionalandmakearecordofsuccessuponcompletion.Itcanthenberetriedifitfailed.Queuingabackgroundworkitemisokayforfire-and-forgetevents,ifyougenuinelydon'tcarewhethertheysucceedornot.
Unfortunately,HostingEnvironment.QueueBackgroundWorkItemisnotpartofASP.NETCore.Therefore,ifyouwanttousethis,thenyouwillhavetosimplyqueueajob.Wewillshowyouhowtodothislater,butifyouusethefullversionofASP.NET,thenyoucandothefollowingtosendane-mailinthebackground:
varclient=newSmtpClient();
HostingEnvironment.QueueBackgroundWorkItem(ct=>
client.SendMailAsync(message));
Assumingthatyoualreadyhaveyourmessage,thiswillcreateanSMTPclientandsendthee-mailmessageinthebackgroundwithoutblockingfurtherexecution.Thisdoesnotusethect(cancellationtoken)variable.Keepinmindthatthee-mailisnotguaranteedtobesent.Therefore,ifyouneedtodefinitelydispatchit,thenconsiderusinganothermethod.
IfyouuseASP.NETCore,thenthisfunctionalityisnotavailable.However,youcanmanuallycreatesomethingsimilarwithTask.Runasinthefollowingexample.However,thisisprobablynotthebestapproachforanythingnontrivial:
Task.Run(()=>asyncMethod(cancellationToken));
Ifyoucancancelyourtask,thenyoucangettheApplicationStoppingtokenfromaninjectedinstanceoftheIApplicationLifetimeinterfacetopassinasyourcancellationtoken.Thiswillletyourtaskknowwhentheapplicationisabouttostop,andyoucanalsoblockshutdownwithitwhileyougracefullycleanup.
Youshouldusethistechniquewithcaution,sowewon'tgiveyouafullexamplehere.Although,youshouldnowhaveenoughpointerstodigdeeperandunderstandtheASP.NETCoreapplicationlifecycleifyouwish.
HangfireHangfireisanexcellentlibrarytorunsimplebackgroundjobs.ItdoesnotsupportASP.NETCoreyet,butthisisplanned(refertoANCLAFS.comforthelatestinformation).Ifyouusethefull.NET,thenyoushouldconsideritandyoucanreadmoreathangfire.io.
Youneedpersistentstorage,suchasSQLServer,touseHangfire.Thisisrequiredsothatitcanensurethattasksarecompleted.Ifyourtasksareveryquick,thenthisoverheadcanoutweighthebenefits.Youcanreducethelatencyusingmessagequeuesorthein-memorystoreRedis,buttheseareadvancedtopics.
AsthisbookfocusesonASP.NETCoreandHangfiredoesnotsupportityet,wewon'tcoveritsuseinmoredetail.Itisalsobeyondthescopeofthischapterintermsofquickandeasysolutions.
SelectN+1problemsYoumayhaveheardofSelectN+1problemsbefore.It'sanameforaclassofperformanceproblemsthatrelatetoinefficientqueryingofaDB.Thepathologicalcaseiswhereyouqueryonetableforalistofitemsandthenqueryanothertabletogetthedetailsforeachitem,oneatatime.Thisiswherethenamecomesfrom.Insteadofthesinglequeryrequired,youperformNqueries(oneforthedetailsofeachitem)andtheonequerytogetthelisttobeginwith.PerhapsabetternamewouldbeSelect1+N.
Youwillhopefullynotwritesuchbad-performingqueriesbyhand,butanO/RMcaneasilyoutputveryinefficientSQLifusedincorrectly.Youmightalsousesomesortofbusinessobjectsabstractionframework,whereeachobjectlazilyloadsitselffromtheDB.Thiscanbecomeaperformancenightmareifyouwanttoputalotoftheseobjectsinalistorcalculatesomedashboardmetricsfromalargeset.
Note
WewillgointodetailaboutSQLandO/RMoptimizationinChapter5,OptimizingI/OPerformance.Thischapterwillsimplyoffersomequickfixestocommonproblems.
Ifyouhaveaslowapplicationthathasperformanceissueswhenretrievingdata,thenSelectN+1maybetheproblem.RunaSQLprofilertool,asdescribedinthepreviouschapter,todiscoverifthisisthecase.IfyouseelotsofSQLqueriesforyourdatainsteadofjustone,thenyoucanmoveontothesolutionstage.Forexample,ifyourscreenfillswithqueriesonapageload,thenyouknowyouhaveaproblem.
Inthefollowingexample,wewillusethemicro-O/RMDapper(madebytheteamatStackOverflow)tobetterillustratewhatoccurs.However,youaremorelikelytoencountertheseproblemswhenusingalargelazyloadinglibraryorO/RM(suchasEForNHibernate).
Note
EntityFrameworkCore1.0(previouslyEF7)doesnotsupportlazyloading,soyouareunlikelytoencounterSelectN+1problemswhenusingit.PreviousversionsofEFdosupportthisanditmaybeaddedtoEFCoreinthefuture.
Youcurrentlyneedtouseabetapre-releaseversionofDappertoworkwithASP.NETCore.AswithGlimpse,thismaybestablebythetimeyoureadthis(checkANCLAFS.com).TouseGlimpsewithDapper,youneedtousetheGlimpse.ADOpackage,whichunfortunatelydoesnotyetsupport.NETCore.
Considerasimpleblogwebsite.Onthehomepage,wewouldlikealistofthepostsalongwiththenumberofcommentseachposthas.Ourblogpostmodelmaylooksomethinglikethefollowing:
namespaceSelectNPlusOne.Models
{
publicclassBlogPost
{
publicintBlogPostId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicintCommentCount{get;set;}
}
}
Wealsohaveamodelforacomment,whichmaylooklikethis.
namespaceSelectNPlusOne.Models
{
publicclassBlogPostComment
{
publicintBlogPostCommentId{get;set;}
publicstringCommenterName{get;set;}
publicstringContent{get;set;}
}
}
Note
Asthisisanexample,wekeptthingssimpleandonlyusedasinglesetofmodels.Inarealapplication,youwilltypicallyhaveseparateviewmodelsanddataaccesslayermodels.Thecontrollerwillmapbetweenthese,perhapsassistedbyalibrary,suchasAutoMapper(automapper.org).
OurviewtorenderthisintoHTMLmaylooksomethinglikethefollowing:
@modelIEnumerable<SelectNPlusOne.Models.BlogPost>
<tableclass="table">
<tr>
<th>Title</th>
<th>#Comments</th>
</tr>
@foreach(varpostinModel)
{
<tr>
<td>@post.Title</td>
<td>@post.CommentCount</td>
</tr>
}
</table>
Wewanttopopulatethesemodelsandviewfromourdatabase.Wehavetwotables,whichlooklikethis:
Therelationshipbetweenthetwotablesinquestionlookslikethefollowing:
Inourcontroller,wecanwritecode,suchasthefollowingtoquerythedatabase,populatethemodelfromthedatabaseresults,andreturntheviewtorenderit:
using(varconnection=newSqlConnection(connectionString))
{
awaitconnection.OpenAsync();
varblogPosts=awaitconnection.QueryAsync<BlogPost>(@"
SELECT*FROMBlogPost");
foreach(varpostinblogPosts)
{
varcomments=await
connection.QueryAsync<BlogPostComment>(@"
SELECT*FROMBlogPostComment
WHEREBlogPostId=@BlogPostId",
new{BlogPostId=post.BlogPostId});
post.CommentCount=comments.Count();
}
returnView(blogPosts);
}
Wetestthisanditworks!Wefeelprettyhappywithourselves.Itcompletesquicklyonourlocaltestdatabasethatcontainsahandfulofrows.Weusedtheasyncmethodseverywhere,whichmustbewhatmakesthissoquick.Weevenonlygetthecommentsforeachbloginquestion,notallcommentseverytime.WealsousedaparameterizedquerytoavoidSQLinjection,andeverythinglooksgood.Shipit!
Note
Asthisisanexample,wekeptitsimpleforclarity.Inarealapplication,youwillwanttousetechniquessuchasdependencyinjection(suchastheDIbuiltintoASP.NETCore)tomakeitmoreflexible.
Unfortunately,whenthedatastartstoincrease(aspostsandcommentsareadded),theblogstartstogetmuchslowerwithpagestakingalongertimetoload.Ourreadersgetboredwaitingandgiveup.Audiencefiguresdropalongwithrevenue.
Let'sprofilethedatabasetoseewhattheproblemmightbe.WerunSQLServerProfilerfilteringonthedatabaseinquestion,andlookattheSQLbeingexecuted.
ThefollowingscreenshotshowsthefilterdialoginSQLServerProfiler:
Thetracethatwecapturerevealsthatlotsofqueriesarebeingexecuted;fartoomanyforthedatathatweneed.Theproblemisthatourcodeisnotveryefficientbecauseitusesmultiplesimple
queriesratherthanoneslightlymorecomplicatedone.
Ourcodefirstgetsalistofblogpostsandthengetsthecommentsforeachpost,onepostatatime.Wealsobringbackwaymoredatathanweneed.Asyncdoesnotspeedupanindividualrequestbecausewestillneedallofthedatabeforewecanrenderthepage.
Note
ThebadcodingisobviousinthisexamplebecauseDapperhastheSQLrightinyourcode.However,ifyouuseanotherO/RM,thenyouwouldn'ttypicallyseetheSQLinVisualStudio(oryoureditorofchoice).ThisisanadditionalbenefitofusingDapperbecauseyouseetheSQLwhereit'sused,sotherearenosurprises.
However,themainbenefitofDapperisthatit'sfast,veryfast,andmuchfasterthanEF.It'sagreatchoiceforperformanceandyoucanreadmoreaboutitatgithub.com/StackExchange/dapper-dot-net.
Weonlywantacountofthecommentsforeachpostandwecangeteverythingthatweneed(andonlywhatweneed)inonequery.Let'salterourpreviouscodetouseaslightlymorecomplicatedSQLqueryratherthantwosimplerqueries,oneofwhichwasinsideaforeachloop:
Tip
ASQLqueryinsidealoopisanobviouscodesmellthatindicatesthingsmaynotbeaswellthought-outastheycanbe.
using(varconnection=newSqlConnection(connectionString))
{
awaitconnection.OpenAsync();
varblogPosts=awaitconnection.QueryAsync<BlogPost>(@"
SELECT
bp.BlogPostId,
bp.Title,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId,bp.Title");
returnView(blogPosts);
}
Thismoreefficientcodeonlyperformsasinglequeryagainstthedatabaseandgetsalloftheinformationthatweneed.Wejointhecommentstabletothepostsinthedatabaseandthenaggregatebygrouping.Weonlyrequestthecolumnsthatweneedandaddthecountofthecommentstoourselection.
Let'sprofilethenewcodetoseewhetherwefixedtheproblem.Thefollowingimageshowsthatwenowonlyhaveasinglequerybeingexecutedratherthanthethousandsbeingexecutedbefore:
Thenumberofquerieshasbeendramaticallyreduced.Therefore,thepageloadsmuchfaster.However,thepageisstillverybigbecausealltheblogpostsarelistedonitandtherearealot.Thisslowsdownrenderingandincreasesthetimetodeliverthepagetoabrowser.
EfficientpagingInarealapplication,youwanttoimplementpagingsothatyourlistisnottoolongwhenalotofdataisinthetable.It'sabadideatolistthousandsofitemsonasinglepage.
YoumaywanttodothiswithLINQcommandsbecausetheyareveryconvenient.However,youneedtobecareful.IfyourO/RMisnotLINQawareoryouaccidentallycasttothewrongtypealittletooearly,thenthefilteringmayoccurinsidetheapplicationwhenthebestplacetoperformthisfilteringisactuallyinthedatabase.Yourcodemayberetrievingallofthedataandthrowingmostofitawaywithoutyourealizingit.
Perhapsyouaretemptedtomodifytheactionmethodreturnstatementtolooksomethinglikethefollowing:
returnView(blogPosts.OrderByDescending(bp=>bp.CommentCount)
.Skip(pageSize*(pageNumber-1))
.Take(pageSize));
Thisworksandwillspeedupyourapplicationconsiderably.However,itmaynothavetheeffectthatyouthinkithas.Theapplicationisquickerbecausetheviewrenderingisspeedierduetogeneratingasmallerpage.ThisalsoreducesthetimetosendthepagetothebrowserandforthebrowsertorendertheHTML.
Yet,theapplicationstillgetsalloftheblogpostsfromthedatabaseandloadsthemintomemory.Thiscanbecomeaproblemastheamountofdatagrows.IfyouwanttouseLINQmethodssuchasthis,thenyouneedtocheckthattheyarehandledallthewaytothedatabase.It'saverygoodideatoreadthedocumentationforyourO/RMorframeworkanddouble-checktheSQLthatisgeneratedusingaprofiler.
Let'shavealookatwhattheSQLshouldlooklike.Forexample,ifyouuseSQLServer,startingwiththeprecedingquery,youcantakeonlythetoptenmost-commentedpostsbyalteringitlikethefollowing:
SELECTTOP10
bp.BlogPostId,
bp.Title,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId,bp.Title
ORDERBYCOUNT(bpc.BlogPostCommentId)DESC
Weorderbycommentcountindescendingorder.However,youcansortbydescendingIDtogetaroughreversechronologicalorderifyoulike.Fromthisorderedset,weselect(ortake)onlythetoptenrecords.
Ifyouwanttoskiprecordsforpaging,theSELECTTOPclauseisnotgoodenough.InSQLServer2012andonward,youcanusethefollowinginstead:
SELECT
bp.BlogPostId,
bp.Title,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId,bp.Title
ORDERBYCOUNT(bpc.BlogPostCommentId)DESC
OFFSET0ROWS
FETCHNEXT10ROWSONLY
YoucanadjustthevalueforOFFSETtogetthecorrectentriesforyourpagenumber.TheFETCHNEXTvaluewillchangethepagesize(thenumberofentriesonapage).Youcanpassthesevaluesinwithaparameterizedquery,asfollows:
using(varconnection=newSqlConnection(connectionString))
{
awaitconnection.OpenAsync();
varblogPosts=awaitconnection.QueryAsync<BlogPost>(@"
SELECT
bp.BlogPostId,
bp.Title,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId,bp.Title
ORDERBYCOUNT(bpc.BlogPostCommentId)DESC
OFFSET@OffsetRowsROWS
FETCHNEXT@LimitRowsROWSONLY",new
{
OffsetRows=pageSize*(pageNumber-1),
LimitRows=pageSize
}
);
returnView(blogPosts);
}
YoucanpassinthepagesizeandnumberasURLparametersifyouupdateyouractionmethodsignaturetothefollowing:
publicasyncTask<IActionResult>Index(intpageNumber=1,
intpageSize=10)
Here,weprovideddefaultvaluesforbothparameters,sotheyareoptional.Whennoparametersareprovided,thenthefirstpageoftenresultsisshown.Weneedtomultiplythepagesizebythezero-indexedpagenumbertocalculatethecorrectoffset.Itshouldbezeroforthefirstpagesothatnorecordsareskipped.
Tip
Itwouldbeaverygoodideatoapplysomevalidationtothepagingparameters.Don'tallowuserstosetthemtoanythingoutsideofareasonablerange.Thisisleftasanexercisetothereader.
Ifwelookintheprofileratthequeriesbeingexecutedonthedatabaseserver,thenwecanseewhatSQLisnowbeingrun.Wecanalsoseethetimetakenandcomparethistoourresultsfrompreviously:
Thequeryinthescreenshotgetsthedataforthethirdpagewiththepagesizesetto50entries.Therefore,itusedanoffsetof100(toskipthefirsttwopagesof50)andfetchedthenext50rows.TheURLquerystringforthiscanlooksomethinglikethefollowing:
/?pagenumber=3&pagesize=50
Wecanseethatthedurationofthequeryhasdecreasedfrom24mspreviouslyto14msnow.
Tip
NotehowtheSQLexecutesdifferentlywhenparametersarepassedintothequery.Thisismuchsaferthanconcatenatinguser-suppliedvaluesdirectlyintoaSQLcommand.
Ifyoudonotuseanyparameters,thenthedefaultvaluesareusedandthehomepageshowsonlytenentries,whichlookssomethinglikethefollowingscreenshot,dependingonthedatainthedatabase:
Bydefault,thehomepageonlydisplaysthetop10mostcommentedposts,butyoucaneasilyaddpagenavigationwithhyperlinks.SimplyaddthepagenumberandpagesizequerystringparameterstotheURL.
YoucanusetheexampleURLquerystringshownpreviouslyoneitherthehomepageorthebadpagingpath,forexample,/Home/BadPaging/?pagenumber=3&pagesize=50.
Thelinksinthenavigationbarloadtheexamplesthatwejustwalkedthrough.Thebestisthe
sameasthehomepageandisthedefault.Top10andbadpagingshouldbefairlyself-explanatory.Badwilltakealongtimetoload,especiallyifyouusetheDBcreationscriptincludedwiththeproject.Youcantimeitwithyourbrowserdevelopertools.
ForpreviousversionsofSQLServer(priorto2012),therearepagingworkaroundsusingROW_NUMBER()ornestedSELECTstatements,whichinvertthesortorder.Ifyouuseanotherdatabase,suchasPostgreSQL,MySQL,orSQLite,thenyoucaneasilyimplementpagingwiththeLIMITclause.ThesefreedatabasesoftenhavemorefeaturesthanSQLServer,suchastheLimitclausementionedhereandaconcatenationaggregatortonamejustoneother.
Note
OneofthetoutedbenefitsofbigO/RMsisthelayerofabstractionthattheyoffer.Thisallowsyoutochangethedatabasethatyouuse.However,inpractice,itisraretochangesomethingascoreasadatabase.Asyoucanseefromthesimplepagingexample,syntaxvariesbetweendatabasesforanythingotherthansimplestandardSQL.Togetthebestperformance,youreallyneedtounderstandthefeaturesandcustomsyntaxofthedatabasethatyouuse.
StaticsitegeneratorsThedatabaseisthelogicalplacetoperformanyworktofilterandsortdata.Doingthisintheapplicationisawaste.However,forasimpleblogthatisupdatedinfrequently,adatabasemaybeunnecessaryinthefirstplace.Itmayevenbecomethebottleneckandslowthewholeblogdown.Thisisatypicalproblemofblogengines,suchasWordPress.Abetterapproachmaybetouseastaticsitegenerator.
AstaticsitegeneratorprerendersallofthepagesandsavestheresultingHTML.Thiscaneasilybeservedbyasimplewebserverandscaleswell.Whenachangeismadeandpagesneedupdating,thenthissiteisregeneratedandanewversionisdeployed.Thisapproachdoesn'tincludedynamicfeatures,suchascomments,butthird-partyservicesareavailabletoprovidetheseaddedextras.
ApopularstaticsitegeneratorisJekyll,whichiswritteninRuby.GitHubprovidesafreestaticsite-hostingservicecalledGitHubPages,whichsupportsJekyll,andyoucanreadmoreaboutitatpages.github.com.Anotherstaticsitegenerator(writteninGo)isHugo,whichyoucanreadaboutatgohugo.io.Thesetoolsarebasicallyaformofextremecaching.We'llcovercachinginthenextsectionandlateroninthisbook.
It'softenworthtakingastepbacktoseewhethertheproblemthatyou'retryingtosolveisevenaproblem.Youmaywellimprovedatabaseperformancebyremovingthedatabase.
PragmaticsolutionswithhardwareThebestapproachtotakewithapoorlyperformingapplicationisusuallytofixthesoftware.However,itisgoodtobepragmaticandtrytolookatthebiggerpicture.Dependingonthesizeandscaleofanapplication,itcanbecheapertothrowbetterhardwareatit,atleastasashorttermmeasure.
Hardwareismuchcheaperthandevelopertimeandisalwaysgettingbetter.Installingsomenewhardwarecanworkasaquickfixandbuyyousometime.Youcanthenaddresstherootcausesofanyperformanceissuesinsoftwareaspartoftheongoingdevelopment.Youcanaddalittletimetothescheduletorefactorandimproveanareaofthecodebaseasyouworkonit.
Onceyoudiscoverthatthecauseofyourperformanceproblemislatency,youhavetwopossibleapproaches:
Reducethenumberoflatency-sensitiveoperationsReducethelatencyitselfusingfastercomputersorbymovingthecomputersclosertogether
Withtheriseofcloudcomputing,youmaynotneedtobuyorinstallnewhardware.Youcanjustpaymoreforahigher-performinginstanceclassoryoucanmovethingsaroundinsideyourcloudprovider'sinfrastructuretoreducelatency.
AdesktopexampleToborrowanexamplefromnativedesktopapplications,itisquitecommontohavepoorly-performingLineofBusiness(LoB)applicationsoncorporatedesktops.Thedesktopwillprobablybeoldandunderpowered.Thenetworkingbacktothecentraldatabasemaybeslowbecausetheconnectionmightbeoveraremotelinktoaregionaloffice.
Withabadly-writtenapplicationthatistoochattywiththeDB,itcanbebetter,performance-wise,toruntheapplicationonaservercloseto(oronthesameserveras)theDB.PerhapstheapplicationworkspaceandDBserverscanbeinthesameserverrackatthedatacenterandconnectedbyGigabit(ortenGigabit)Ethernet.
TheusercanthenusearemotedesktopconnectionorCitrixsessiontointeractwiththeapplication.ThiswillreducethelatencytotheDBandcanspeedthingsup,eventakingintoconsiderationthelagoftheremoteUI.ThiseffectivelyturnsthedesktopPCintoathinclient,similartohowoldmainframesareused.
Forexample,youcanbuildahigh-performanceserverwithRAIDSSDsandlotsofRAMformuchlessthanthecostofthedevelopertimetofixalargeapplication.Evenbadly-writtensoftwarecanperformwellifyouruntheapplicationandDBtogetheronthesamemachine,especiallyifyourunitonbaremetalwithnovirtualmachinesintheway.Thistacticwouldbuyyoutimetofixthingsproperly.
Theseremoteapplicationandvirtualizationtechnologiesareusuallysoldastoolstoaiddeploymentandmaintenance.However,thepotentialperformancebenefitsarealsoworthconsidering.
Duetotheriseofwebapplications,thickclientdesktopapplicationsarenowlesscommon.Architectureseemstooscillatebetweencomputationontheserveranddoingworkontheclient,astherelativeprogressofnetworkingspeedandprocessingpowerraceeachother.
WebapplicationsThesamerelocationapproachdoesnottypicallyworkaswellforwebapplications,butitdependsonthearchitectureused.Thegoodnewsisthat,forwebapplications,youusuallycontroltheinfrastructure.Thisisnotnormallythecasefornativeapplicationhardware.
Ifyouuseathree-tierarchitecture,thenyoucanmovetheapplicationserversclosertotheDBserver.Whetherthisiseffectiveornotdependsonhowchattythewebserversarewiththeapplicationservers.IftheyissuetoomanywebAPIrequests,thenthiswon'tworkwell.
Atwo-tierarchitecture(wherethewebserverstalkdirectlytothedatabase)ismorecommonfortypicalwebapplications.Therearesolutionsusingclustereddatabasesorread-onlymirrorstoplacethedataclosetothewebservers,buttheseaddcomplexityandcost.
Whatcanmakeasignificantdifferenceareproxyservers.ApopularopensourceproxyserverisVarnishandyoucanalsousetheNGINXwebserverasaproxy.Proxyserverscachetheoutputofwebserverssothatapagedoesn'thavetoberegeneratedforeachuser.Thisisusefulforsharedpagesbutcachingishard;typically,youshouldnotcachepersonalizedpages.Youdon'twanttoaccidentallyservesomeone'sauthenticatedprivateinformationtoanotheruser.
ProxiessuchasVarnishcanalsoroutedifferentpartsofyourwebsitetodifferentservers.IfyouhaveasmallareaofyoursitethatperformsbadlyduetoDBchatter,thenyoucouldhostthatpartfromwebserverson(orverycloseto,suchasonthesameVMhost)theDBmachinesandrouterequestsforittothere.Therestofthesitecouldremainontheexistingwebserverfarm.
Thisisn'talongtermsolution,butitallowsyoutosplitoffapoorlyperformingpartofyourprogramsothatitdoesn'timpacttherestofyoursystem.You'rethenfreetofixitonceit'sbeendecoupledorisolated.YoucanevensplitoffthedatarequiredtoaseparateDBandsynchronizeitwithabackgroundprocess.
TherearealsoContentDeliveryNetworks(CDNs),suchasCloudFlare,AmazonCloudFront,andAzureCDN,whicharegoodtocachestaticassets.CDNscachepartsofyoursiteindatacentersclosetoyourusers,reducingthelatency.CloudFlarecanevenaddHTTPStoyoursiteforfree,includingautomaticallyissuingcertificates.
Note
YoucanreadmoreabouttheCDNofferingsofCloudFlare(includingHTTP/2serverpushandWebSocketsonthefreeplan)atwww.cloudflare.com.
WewillcovercachinginmoredetailinChapter7,LearningCachingandMessageQueuing,sowewon'tgointomoredetailhere.Cachingisachallengingsubjectandneedstobeunderstoodwellsothatyoucanuseiteffectively.
OversizedimagesWhilewe'reonthesubjectofstaticassets,weshouldbrieflymentionimageoptimization.We'llcoverthisinmuchmoredetailinthenextchapter,butit'sworthhighlightingsomecommonproblemshere.Asyouhaveverylittlecontrolovernetworkconditionsbetweenyourinfrastructureandtheuser,lowthroughputmaybeaprobleminadditiontohighlatency.
Webapplicationsheavilyuseimages,especiallyonlandingpagesorhomepages,wheretheymightformafullscreenbackground.Itisregrettablycommontoseearawphotofromacamerasimplydroppedstraightin.Imagesfromcamerasaretypicallymanymegabytesinsize,fartoobigforawebpage.
Youcantestwhetherthereareproblemsonawebpageusingatool,suchasGoogle'sPageSpeedInsights.Visitdevelopers.google.com/speed/pagespeed/insights,enteraURL,andclickonANALYZEtoviewtheresults.Googleusethisinformationaspartoftheirsearchengineranking,soyouwoulddowelltotakeitsadviceuptoapoint.Slowsitesranklowerinsearchresults.
Youcanalsousethebrowserdevelopertoolstoviewthesizeofimages.PressF12andlookatthenetworktabafterapageloadtoviewhowmuchdatawastransferredandhowlongittook.Youcanoftenmisstheseperformanceissuesonalocalmachineortestserverbecausetheimagewillloadquickly.Afterthefirstload,itwillalsobestoredinthebrowser'scache,somakesureyoudoafullhardreloadandemptyordisablethecache.InChrome(whenthedevtoolsareopen),youcanright-clickorlongclickonthereloadbuttonfortheseextraoptions.It'salsoagoodideatousethebuilt-inthrottlingtoolstoseehowauserwillexperiencethepageloading.
Themostbasicimageoptimizationproblemstypicallyfallintotwocategories:
ImagesthatareoverlylargeforthedisplayareatheyaredisplayedinImagesthatusethewrongcompressionformatforthesubjectmatter
ImageresolutionThemostcommonissueisthatanimagehastoohigharesolutionfortheareathatdisplaysit.Thisforcesthebrowsertoresizetheimagetofitthescreenorarea.Ifthesizeofthefileisunnecessarilylarge,thenitwilltakelongertobetransferredoveraninternetconnection.Thebrowserwillthenthrowawaymostoftheinformation.Youshouldresizetheimageaheadoftimebeforeaddingittothesite.
Therearemanyimagemanipulationtoolsavailabletoresizepictures.IfyourunWindows,thenPaint.NET(www.getpaint.net)isanexcellentfreepieceofsoftware.ThisismuchbetterthanthePaintprogramthatcomeswithWindows(althoughthiswillworkifyouhavenootheroption).
Forotherplatforms,GIMP(www.gimp.org)isverygood.Ifyoupreferusingthecommandline,thenyoumaylikeImageMagick(imagemagick.org),whichcanperformlotsofimagemanipulationtasksprogrammaticallyorinbatches.Therearealsocloud-hostedimagemanagementservices,suchasCloudinary(cloudinary.com).
Youshouldshrinkimagestotheactualsizethattheywillbedisplayedontheuser'sscreen.Therecanbecomplicationswhendealingwithresponsiveimages,whichscalewiththesizeoftheuser'sscreenorbrowserwindow.AlsokeepinmindhighDPIorRetinadisplays,whichmayhavemorethanonephysicalpixeltoeverylogicalpixel.Yourimagesmayhavetobebiggertonotlookblurry,buttheupperboundisstilllikelytobelowerthantherawsize.Itisraretoneedanimageatmorethantwicethesizeofthedisplayedresolution.Wewilldiscussresponsiveimagesinmoredetaillaterinthisbook,butitisworthkeepingtheminmind.
ThefollowingimagedisplaystheresizingdialogfromPaint.NET:
Whenresizinganimage,itisusuallyimportanttokeeptheaspectratiooftheimagethesame.Thismeanschangingthehorizontalandverticalsizesinproportiontoeachother.
Forexample,reducingtheHeightfrom600pxto300pxandreducingtheWidthfrom800pxto400px(meaningbothdimensionsarereducedby50%)keepstheimagelookingthesame,onlysmaller.Mostimage-manipulationsoftwarewillassistwiththisprocess.Keepingtheaspectratiothesamewillavoidimageslookingstretched.Ifimagesneedtofitadifferentshape,thentheyshouldbecroppedinstead.
ImageformatThenextmostcommonproblemisusingimagesinthewrongfileformatforthecontent.Youshouldneveruserawuncompressedimages,suchasbitmap(BMP),ontheweb.
Fornaturalimagessuchasphotos,usetheJPEGfileformat.JPEGisalossycodec,whichmeansthatinformationislostwhenusingit.Itisverygoodforpictureswithalotofgradientsinthem,suchasimagesofnaturalscenesorpeople.JPEGlookspoorifthereisanytextintheimagebecausetherewillbecompressionartifactsaroundtheedgesoftheletters.Mostmid-andlow-endcamerasnativelysaveimagesasJPEG,soyoudonotloseanythingbystayingwithit.However,youshouldresizetheimagestomakethemsmaller,asmentionedpreviously.
Forartificialimagessuchasdiagramsoricons,usePNG.PNGisalosslesscodec,whichmeansthatnoinformationisdiscarded.Thisworksbestforimageswithlargeblocksofsolidcolor,suchasdiagramsdrawninpaintingsoftwareorscreenshots.Thisalsosupportstransparency,soyoucanhaveimagesthatdon'tappearrectangularoraretranslucent.YoucanalsohaveanimatedPNGs,whichareofsuperiorqualitytoGIFs,butwewon'tgointothedetailsoftheminthischapter.
Youcanaltertheformatofimagesusingthesametoolsthatyouusetoresizethem,asmentionedpreviously,bysimplychangingthefileformatwhensavingtheimage.Asalways,youshouldtestforwhatworksbestinyourspecificusecase.Youcanperformexperimentsbysavingthesameimageindifferentformats(anddifferentresolutions)thenobservingthesizesofthefilesondisk.
ThefollowingimagedisplaystheavailableimageoptionsinPaint.NET.AdditionalformatsareavailableandwewillgointomoredetailinChapter4,AddressingNetworkPerformance:
EvenwhenyouonlychoosebetweenJPEGandPNG,youcanstillmakeasignificantdifference.Thefollowingscreenshotdisplaysthedifferenceinthesizeofthefileofthesameimageintworesolutionsandtwoformats.
Thefollowingtestimageistheoneusedintheexperiment.DuetothehardedgesitlooksbestasaPNG,butthegradientbackgroundmakesitmoredifficulttocompress:
Note
Thetestimagesusedhereareavailablefordownloadwiththisbook,soyoucantrytheexperimentforyourself.
Inawebcontext,thisparticularimagemaybebestservedwithatransparentbackgroundusingCSSforthegradient.However,simpleshapes,suchasthesecanbetterberepresentedasScalableVectorGraphics(SVG)orwithaHTML5canvas.
SummaryInthischapter,youlearnedaboutsomecommonperformanceproblemsandhowtofixthem.Wecoveredasynchronousoperations,SelectN+1problems,pragmatichardwarechoices,andoverly-largeimages.
Inthenextchapter,wewillexpandonimageoptimizationandextendthistootherformsofcompressionfordifferenttypesofresources.We'lllookatthenewprocessforthebundlingandminificationofstaticassetsinASP.NETCoreusingopensourcetools.
Additionally,wewillintroducenetworkingtopics,suchasTCP/IP,HTTP,WebSockets,andencryption.We'llalsocovercaching,includinganotherlookatCDNs.
Chapter4.AddressingNetworkPerformanceThischapterbuildsonasubsetoftheproblemsthatwerediscussedinthepreviouschapterbutinmoredetail.Itdealswithlatency,orlag,whichoriginatesatthenetworkinglevelbetweentheuserandtheapplication.Thisismostlyapplicabletowebapplicationswheretheuserinteractswiththeapplicationviaawebbrowser.Youwilllearnhowtooptimizeyourapplicationtocaterforbandwidthandlatencythatisunknownandoutsideofyourcontrol.You'llcompressyourpayloadstobeassmallaspossible,andthenyouwilldeliverthemtotheuserasquicklyaspossible.Youwilllearnaboutthetoolsandtechniquesthatcanbeusedtoachieveafastandresponsiveapplication.You'llalsoseethetrade-offsinvolvedandbeabletocalculatewhetherthesemethodsshouldbeappliedtoyoursoftware.
Thetopicsthatwewillcoverinthischapterincludethefollowing:
TCP/IPHTTPandHTTP/2HTTPS(TLS/SSL)WebSocketsandpushnotificationsCompressionBundlingandminificationCachingandCDNs
Thischapterdealswithhowtospeeduptheexperienceforauserusingyourapplication.Theskillsinthischapterarejustasapplicabletoastaticsiteorclient-sidewebappastheyaretoadynamicwebapplication.
Thesetopicsapplytoanywebapplicationframework.However,wewillfocusonhowtheyareimplementedwithASP.NET—inparticularwiththenewASP.NETCoreimplementation,andhowthisdiffersfromtheexistingfullASP.NET.
InternetprotocolsIt'simportanttoknowabouthowyourHTMLandotherassetsaredeliveredfromthewebservertoyouruser'sbrowser.Muchofthisisabstractedawayandtransparenttowebdevelopment,butit'sagoodideatohaveatleastabasicunderstandinginordertoachievehighperformance.
TCP/IPTransmissionControlProtocol/InternetProtocol(TCP/IP)isthenameforapairofcommunicationprotocolsthatunderpintheinternet.IPisthelower-levelprotocolofthetwo,andthisdealswithroutingpacketstotheircorrectdestinations.IPcanrunontopofmanydifferentlower-levelprotocols(suchasEthernet),andthisiswhereIPaddressescomefrom.
TCPisalayeraboveIP,anditisconcernedwiththereliabledeliveryofpacketsandflowcontrol.TCPiswhereportscomefrom,suchasport80forHTTP,andport443forHTTPS.ThereisalsotheUserDatagramProtocol(UDP),whichcanbeusedinsteadofTCP,butitprovidesfewerfeatures.
HTTPrunsontopofTCP,anditisusuallywhatyouwilldealwithinawebapplication.YoumayoccasionallyneedtodirectlyuseSimpleMailTransferProtocol(SMTP)tosende-mails,theDomainNameSystem(DNS)toresolvehostnamestoIPaddresses,orFileTransferProtocol(FTP)touploadanddownloadfiles.
ThebasicunencryptedversionsoftheseprotocolsrundirectlyonTCP,butthesecureencryptedversions(HTTPS,SMTPS,andFTPS)havealayerinbetweenthem.ThislayeriscalledTransportLayerSecurity(TLS),andthisisthemodernsuccessortotheSecureSocketsLayer(SSL).SSLisinsecureanddeprecated,anditshouldnolongerbeused.However,thetermSSLisstillcommonlyandconfusinglyusedtodescribeTLS.AllbrowsersrequiretheuseofTLSencryptiontosupportHTTP/2.
Youmaynotoftenthinkaboutthelower-levelprotocolswhenyoubuildwebapplications.Indeed,youmaynotneedtoconsiderevenHTTP/HTTPSthatmuch.However,theprotocolstackbelowyourapplicationcanhavesignificantperformanceimplications.
Thefollowingdiagramshowshowtheprotocolsaretypicallystacked:
Slow-start
TCPimplementsanalgorithmcalledslow-startforcongestion-controlpurposes.Thismeansthattheconnectionfromabrowsertoawebserverisinitiallyslowandrampsupovertimetodiscovertheavailablebandwidth.Youcanalterthesettingsforthissothattherampupismoreaggressive,andconnectionsgetquickerfaster.Ifyouincreasetheinitialcongestionwindow,thenperformancecanimprove,especiallyonconnectionswithgoodbandwidthbuthighlatency,suchasmobile4Gorserversonothercontinents.
Asusual,youshouldtestforyourusecaseperhapsusingWireshark,asdescribedpreviouslyinChapter2,MeasuringPerformanceBottlenecks.Therearedownsidestoalteringthiswindow,anditshouldbeconsideredcarefully.Althoughthismayspeedupwebsites,itcancausebuffersinnetworkingequipmenttofill,whichcangeneratelatencyproblemsforVoIPapplicationsandgamesifnoQualityofService(QoS)isinuseendtoend.
YoucanchangethisvalueonWindowsServer2008R2withahotfix(KB2472264)andhigher.YoucanalsoeasilyadjustthisonLinux,andASP.NETCoreenablesyoutorunyour.NETwebapponLinux(andMacOSX)inadditiontoWindows.
Wewon'tprovidedetailedinstructionsherebecausethisshouldbeacautiouslyconsidereddecision,andyoushouldn'tapplyadviceblindly.Youcaneasilyfindinstructionsonlinefortheoperatingsystemthatyouuseonyourwebserver.
TCPslow-startisjustoneexampleofwhyyoucan'tignorethelowerlevelsofInternettechnologyontheshouldersofwhichwebapplicationsstand.Let'smoveupthestackalittletotheapplicationlayer.
HTTPAsawebapplicationdeveloperwhowantstodeliverhighperformance,it'simportanttounderstandHypertextTransferProtocol.YoushouldknowwhatversionofHTTPyouuse,howitworks,andhowthisaffectsthings,suchasrequestpipeliningandencryption.
HTTP/1.1istheversionthatyouwillprobablybemostfamiliarwithtodaybecauseithasbeeninuseforsometime.HTTP/2isbecomingmorepopular,anditchangesthebestwaytodomanythings.
Headers
HTTPusesheaderstoprovidemetadataaboutarequestalongwiththemainpayloadinthebodyofthemessage,muchlikee-mailsdo.Youwon'tseetheseheaderswhenyouviewthesource,butyoucanobservethemusingthebrowserdevelopertools.Youcanuseheadersformanythings,suchascachecontrolandauthentication.Cookiesarealsosentandreceivedasheaders.
BrowserswillonlyopenalimitednumberofHTTP/1.1connectionsatonetimetoasinglehost.Ifyourequirealotofrequeststoretrievealltheassetsforapage,thentheyarequeued,whichincreasesthetotaltimetakentofullyloadit.WhencombinedwiththeTCPslow-startmentionedpreviously,thiseffectcanbeamplified,degradingtheperformance.ThisislessofaproblemwithHTTP/2,whichwewillcovershortly.Youcanreducetheimpactofthisproblembyallowingthebrowsertoreuseconnections.Youcandothisbyensuringthatyourwebserverdoesn'tsendaConnection:closeheaderwithHTTPresponses.
HTTPmethods
Therearemultiplemethods(orverbs)thatHTTPuses.ThemostcommonareGETandPOST,buttherearemanymore.Typically,weuseGETrequeststoretrievedatafromaserver,andweusePOSTtosubmitdataandmakechanges.GETshouldnotbeusedtoalterdata.
OtherusefulverbsareHEADandOPTIONS.HEADcanchecktheheadersforaGETrequestwithouttheoverheadofdownloadingthebody.Thisisusefultocheckcachingheaderstoseewhethertheresourcehaschanged.OPTIONSiscommonlyusedforCrossOriginResourceSharing(CORS)toperformapreflightchecktovalidateadomain.
OtheroftenusedverbsarePUT,DELETE,andPATCH.WemainlyusetheseforRepresentationalStateTransfer(REST)APIsbecausetheycanmimicoperationsonresourcesorfiles.However,notallsoftware(suchassomeproxyservers)understandsthem,sosometimes,weemulatethemusingPOST.YoumayevenhaveproblemswithOPTIONSbeingblockedbyproxiesandwebservers.
Statuscodes
HTTPusesnumericresponsecodestoindicateastatus.Youareprobablyfamiliarwith200(OK)and404(NotFound),buttherearemanyothers.Forexample,451indicatesthatthecontenthas
beenblockedbyagovernment-mandatedcensorshipfilter.
Note
The451statuscodeisinreferencetothebookFahrenheit451(whosetitleisthepurportedtemperatureatwhichpaperburns).Youcanreadtheofficialdocument(RFC7725)attools.ietf.org/html/rfc7725.Ifthiscodeisnotused,thenitcanbetrickytodiscoverifandwhyasiteisunavailable.Forexample,youcanfindoutwhethertheUKgovernmentisblockingyoursiteatblocked.org.uk,butthisisjustavolunteereffortrunbytheOpenRightsGrouptheBritishversionoftheElectronicFrontierFoundation(EFF).
Wecommonlyuse3xxcodesforredirection(perhapstoHTTPS).Therearevariousformsofredirectionwithdifferentperformancecharacteristics(andothereffects).Youcanusea302totemporarilyredirectapage,butthenthebrowserhastorequesttheoriginalpageeverytimetoseewhethertheredirecthasended.ItalsohasbadimplicationsforSearchEngineOptimization(SEO),butwewon'tdiscussthesehere.
Abetterapproachistousea301toindicateapermanentredirect.However,youneedtobecareful,asthiscan'tbeundoneandclientswon'tlookattheoriginalURLagain.IfyouuseredirectstoupgradeusersfromHTTPtoHTTPS,thenyoushouldalsoconsiderusingHTTPStrictTransportSecurity(HSTS)headers.Again,dothiscarefully.
Encryption
HTTPencryptionisveryimportant.Itnotonlysecuresdataintransittopreventeavesdropping,butitalsoprovidesauthentication.Thisensuresthatusersactuallyconnecttothesitethattheythinktheyareandthatthepagewasn'ttamperedwith.Otherwise,unscrupulousinternetconnectionproviderscaninjectorreplaceadvertsonyoursite,ortheycanblockinternetaccessuntilyouhaveoptedoutofaparentalfilter.Or,thesecanbeworsethings,suchasstealingyouruser'sdata,whichyouareusuallyrequiredbylawtoprotect.
Thereisreallynogoodreasontodaytonotuseencryptioneverywhere.Theoverheadsaretiny,althoughwewillstillconsiderthemandshowyouhowtoavoidpotentialissues.ArgumentsagainstusingHTTPSareusuallyhangoversfromatimelongagowhencomputationwasexpensive.
Moderncomputinghardwareisverycapableandoftenhasspecialaccelerationforcommonencryptiontasks.Therearemanystudiesthatshowthattheprocessingoverheadsofencryptionarenegligible.However,therecanbeasmalldelayininitiallysettingupasecureconnectionforthefirsttime.Inordertounderstandthis,itisusefultoillustrateasimplemodelofhowTLSworks.
Therearetwopartstosecurecommunication:theinitialkeyexchangeandtheongoingencryptionofthechannel.Sessionciphers,suchastheAdvancedEncryptionStandard(AES),canbeveryquick,andtheycanoperateatclosetolinespeed.However,theseciphersaresymmetricalandbothpartiesneedtoknowthekey.Thiskeyneedstobedistributedsecurelysothatonlythetwo
communicatingpartiespossessit.Thisiscalledkeyexchange,anditusesasymmetricencryption.Thisusuallyalsorequiresathirdpartytovouchfortheserver,sowehaveasystemofcertificates.Thisinitialsetupistheslowpart,althoughwewillshowyouanalternativefordevicesthatlacktheAESaccelerationlater.
Keyexchange
Asmentionedpreviously,keyexchangeistheprocessofsecurelysharinganencryptionkeybetweentwopartieswithoutbeingintercepted.Therearevariousmethodsofdoingthis,whichmostlyrelyonasymmetricencryption.Unlikesymmetricencryption(thatweexchangethiskeyfor),thiscanonlybeperformedinonedirectionwithasinglekey.Inotherwords,thekeythatisusedtoencryptcannotbeusedtodecrypt,andadifferentkeyisrequired.Thisisnotthecaseforthemajorityofthedataoncewehavesharedakey.Thereasonthatwedothisisthatsymmetricencryptionisfasterthanasymmetricencryption.Therefore,itisnotusedforeverythingandisonlyneededtoencryptanotherkey.
Inadditiontoexchangingakey,thebrowser(orotherHTTPSclient)shouldcheckthecertificatetoensurethattheserverbelongstothedomainthatitclaimsto.Someprogrammaticclientsfailtodothisbydefault,sothisisworthcheckingout.Youcanalsoimplementcertificatepinning(eveninthebrowserwithHTTPPublicKeyPinning)toimprovesecurity,butthisisbeyondthescopeofthisbook.
Wewillillustratetwovariationsofkeyexchangebyanalogyinsimplifiedformstoshowyouhowtheprocessworks.Youcanlookupthetechnicaldetailsifyouwish.
RSA
RSAistraditionallythemostcommonkey-exchangemechanismthatisusedforTLS.Untilrecently,weuseditonmostHTTPSconnections.
RSAstandsforRivest-Shamir-Adlemanafterthenamesofitscreators,anditisprobablythemostpopularformofpublickeycryptography.TheBritishsnoopingagency,GovernmentCommunicationsHeadquarters(GCHQ),supposedlyconceivedpublickeycryptographyataroundthesametime,butasitwasonlymadepublicin1997,it'simpossibletoprovethis.TheinventioncreditgoestoWhitfieldDiffieandMartinHellman,whorecentlypickedupaTuringAwardforit.We'lltalkmoreabouttheirworkshortly.
Note
TheTuringAwardistheNobelPrizeofcomputing.It'snamedafterAlanTuring,thelegendarycomputingpioneerwhohelpedtheallieswinWWIIwhileworkingforthenascentGCHQ,butwhowaslaterbetrayedbytheBritishgovernment.
RSAuseslargeprimenumberstogenerateapublicandprivatekeypair.Thepublickeycanbeusedtoencryptinformationthatcanonlybedecryptedwiththeprivatekey.Inadditiontothis,theprivatekeycanbeusedtosigninformation(usuallyahashofit),whichcanbeverifiedwiththe
publickey.RSAisoftenusedtosignTLScertificatesevenifanotheralgorithmisusedasthekeyexchangemechanism(thisisnegotiatedduringtheinitialTLShandshake).
Tip
ThishashingandsigningofcertificatesiswhereyoumayhaveheardofSHA-1certificatesbeingdeprecatedbybrowsers.SHA-1isnolongerconsideredsecureforhashingand,likeMD5beforeit,shouldnotbeused.CertificatechainsmustnowuseatleastanSHA-2hashingalgorithm(suchasSHA-256)tosign.
AnanalogytohelpexplainhowRSAworksistothinkofsendingalockinsteadofsendingakey.Youcanpostanopenpadlocktosomeone,retainingthekeytoit.Theycanthenuseyourlocktosecureacasewithakeyoftheirsinsideandsenditbacktoyou.Now,onlyyoucanopenthecasetogetthenewkey.
Inreality,thisismorecomplicated.Youcan'tbesurethatsomeonedidn'tinterceptyourlockandthenusetheirownlocktogetthekeyandcopyitbeforesendingitontoyou.Typically,wesolvethiswithPublicKeyInfrastructure(PKI).Atrustedthirdpartywillsignyourcertificateandverifythatitisindeedyourpublickeyandthatyouownthelock.BrowserstypicallydisplayawarningifaCertificateAuthority(CA)doesnotcountersignthecertificateinthisway.
Diffie-Hellman(D-H)keyexchangeisanothermethodofgainingasharedkey.InventedshortlybeforeRSA,ithasonlyrecentlybecomepopularontheweb.Thisispartlyduetothereducedcomputationalcostoftheellipticcurvevariant.However,anotherreasonisthattheephemeralversionsprovideaqualitycalledPerfectForwardSecrecy(PFS).UnlikeRSA,thesessionkeyforthesymmetricencryptionneverneedstobetransmitted.Bothpartiescancalculatethesharedkeywithoutitneedingtobesentonthewire(eveninanencryptedstate)orpermanentlystored.Thismeansthataneavesdroppedencryptedexchangecannotbedecryptedinthefutureifthekeyswererecovered.WithRSAkeyexchange,youcanrecoverarecordedcommunicationinplaintextifyouobtaintheprivatekeyslater.PFSaisusefulcountermeasureagainstmasssurveillance,whereallcommunicationiscaughtinadragnetandpermanentlystored.
D-Hisbetterexplainedwithacolormixinganalogy,wherepaintsrepresentnumbers.Thetwopartieschooseasharedcolor,andeachpartychoosesasecretcoloroftheirown.Bothmixthesharedcolorwiththeirsecretcolorandsendtheresulttotheother.Eachpartythenmixesthecolorthattheyreceivedwiththeirsecretcoloragain.Bothpartiesnowhavethesamecolorwithouteverhavingtosendthiscoloranywherewhereitcouldbeobserved.
Asthisisnotabookaboutsecurity,wewon'tgointoanymoredetailonencryptionalgorithms.Ifyouareinterested,thereisahugeamountofinformationavailablethatwecan'tcoverhere.Encryptionisalargesubject,butsecurityisanevenbroaderconcern.
TLShandshake
ThepointofbrieflyexplaininghowTLSkeyexchangeworksforvariousmethodsistoshowthat
itiscomplex.Manymessagesneedtobesentbackandforthtoestablishasecureconnection,andnomatterhowfasttheconnection,latencyslowsdowneverymessage.ThisalloccursintheTLShandshake,wheretheclient(usuallyawebbrowser)andservernegotiatecommoncapabilitiesandagreeonwhatcipherstheyshoulduse.ThereisalsoServerNameIndication(SNI)toconsider,whichissimilartotheHTTPhostheaderinthatitallowsmultiplesitestousethesameIPaddress.Someolderclientsdon'tsupportSNI.
WecanobservetheTLShandshakeusingWireshark.Wewon'tgointoahugeamountofdetail,butyoucanseethatatleastfourmessagesareexchangedbetweentheclientandserver.Theseareclienthello,serverhello(includingthecertificateandserverkeyexchange),clientkeyexchange,andcipheragreement.Thebrowsermaysendmoremessagesifwedonotoptimallyconfiguredthings,suchasrequestinganintermediatecertificate.Thismayalsocheckarevocationlisttoseewhetherthecertificatewasrevoked.
ThefollowingscreenshotshowsaTLShandshakecapturedwithWireshark:
Allthesenetworkoperationshappenquickly.However,iftheconnectionhasahighlatency,thentheseextramessagescanhaveanamplifiedeffectonperformance.Thecomputationaldelaysaretypicallymuchsmallerthanthenetworkdelays,sowecandiscountthese,unlessyouuseveryoldhardware.Fortunately,therearesomesimplethingsyoucandothatwillhelpspeedthingsupandletyouenjoyhighperformancewhilestillbeingsecure.
Delaydiagnostics
TherearevariousmechanismsthatarebuiltintoTLSthatcanyoucanusetospeeditup.However,therearealsothingsthatwillslowitdownifyoudon'tdothemcorrectly.SomegreatfreeonlinetoolstoassessyourTLSconfigurationareavailablefromQualysSSLLabsatssllabs.com.Theservertestatssllabs.com/ssltestisveryuseful.YouenteraURL,andtheygiveyouagradealongwithlotsofotherinformation.
Forexample,ifweanalyzethepacktpub.comsite,wecanseethatonthedateofthetestitgotaBgrade.ThisisduetosupportingweakDiffie-HellmanparametersandtheobsoleteandinsecureRC4cipher.However,itisnotalwaysassimpleasremovingoldciphers.Youcanhaveaverysecuresite,butyoumightexcludesomeofyourcustomers,whouseolderclientsthatdon'tsupportthelateststandards.Thiswill,ofcourse,varydependingonthenatureofyourclientbase,andyoushouldmeasureyourtrafficandconsideryouroptionscarefully.
ThefollowingscreenshotshowssomeofthereportfromSSLLabsforpacktpub.com.
Ifwehavealookatasitewithabetterconfiguration(emoncms.org),wecanseethatitgetsanAgrade.YoucangetanA+gradeusingHSTSheaders.Additionally,theseheadersavoidtheoverheadofaredirect.Youmayalsobeabletogetyoursiteembeddedinapreloadedlistshippedwithbrowsersifyousubmitthedomainstothevendors.
ThefollowingscreenshotshowssomeofthereportfromSSLLabsforemoncms.org:
TheoptionschosenbymodernbrowserswouldtypicallybeanEllipticCurveDiffie-HellmanEphemeralkeyexchange(ECDHE)withanRSASHA-256signatureandAESsessioncipher.TheephemeralkeysprovidePFSbecausetheyareonlyheldinmemoryforthesession.Youcanseewhatconnectionhasbeennegotiatedbylookinginyourbrowser.
InFirefox,youcandothisbyclickingonthelockiconintheURLbarandthenclickingonthe
MoreInformationbutton,asshowninthefollowingimage:
IntheTechnicalDetailssection,youwillseetheciphersuiteused.ThefollowingimagefromFirefoxshowsECDHEkeyexchangeandRSAcertificatesigning:
YoucanalsoviewthecertificatedetailsbyclickingontheViewCertificatebutton.ThedomainisusuallyincludedastheCommonName(CN)intheSubjectfield.AlternativedomainscanalsobeincludedundertheCertificateSubjectAltNameextension:
InChrome,youcanlookattheTLSconnectioninformationintheSecuritytabofthedevelopertools.Forexample,thefollowingimagedisplaysthesecuritydetailsforhuxley.unop.uk:
Thefollowingscreenshotdisplaysthesamewindowforemoncms.org:
Tip
YoumayneedtorefreshthepagetoseeTLSinformationifthesitewasalreadyloadedwhenyouopenedthedevelopertools.YoucanaccessthesametabbyclickingonthepadlockintheChromeURLbarandthenclickingontheDetailslink.
Youcanviewthecertificate(inthenativeoperatingsystemcertificatestore)byclickingontheOpenfullcertificatedetailsbutton.AlinkwiththesamefunctionexistsontheequivalentscreenofChromeforAndroid,althoughthecertificateinformationisreduced.
Performancetweaks
WealreadydiscussedthemostimportantperformancetweakforTLSbecauseitisnotaboutTLS.YoushouldensurethatyourHTTPconnectionsarereusable,becauseifthisisnotthecase,thenyouwillincurtheaddedpenaltyoftheTLSnegotiationalongwiththeTCPoverhead.Cachingisalsoveryimportant,andwewilltalkmoreaboutthislater.
Note
TLSandHTTPbothsupportcompression,butthesehavesecurityimplications.Therefore,considerthemcarefully.Theycanleakinformation,andadeterminedadversarycanuseananalysisofthemtorecoverencrypteddata.TLScompressionisdeprecated,anditwillberemovedinTLS1.3.Therefore,donotuseit.WewilldiscussHTTPcompressionlateroninthis
chapter.
InregardtospecificadviceforTLS,thereareafewthings,whichyoucandotoimproveperformance.Themaintechniqueistoensurethatyouusesessionresumption.ThisisdifferenttoreusingHTTPconnections,andthismeansthatclientscanreuseanexistingTLSconnectionwithouthavingtogothroughthewholekeyexchange.
Tip
YoucanimplementsessionswithIDsontheserverorwithencryptedtickets(inasimilarmannertoASP.NETcookiesthatareencryptedwiththemachinekey).TherewasabugintheMicrosoftclientimplementationaroundticketencryptionkeyrotation,buttheKB3109853patchfixedit.Makesurethatyouinstallthisupdate,especiallyifyouseeexceptionsthrownwhenconnectingtosecureendpointsfromyour.NETcode.
Itisimportanttonotoverdothingsandbiggerisnotalwaysbetter,especiallywhenitcomestokeysize.Itisatrade-offbetweenperformanceandsecurity,andthiswilldependonyourspecificsituation.Ingeneral,agoodbalanceisnotusing256bitAESkeyswhen128bitwilldo.
A2048bitRSAkeyisbigenough,lowerisinsecureandlargeristooslow.YoucanusetheEllipticCurveDigitalSignatureAlgorithm(ECDSA)tosigninsteadofRSA,asitismuchquicker.However,supportislimited,soyouwouldneedtodeployRSAinparallel.
IfyouuseECDSA,thena256bitkeyissufficient.ForECDHE,256bitisalsofine,andfortheslowerversionwithoutellipticcurves(DHE),2048bitissufficient.IfyouuseECDSA,thenyouwillseethislistedinsteadoftheRSAsigningintheconnectiondetails.Forexample,whenvisitinghuxley.unop.uk,thedetailsinthefollowingscreenshotsaredisplayedinFirefox.ThisdifferenceisalsodisplayedinthepreviousChromescreenshots:
Additionally,itisimportanttoincludethefullcertificatechainwithyourcertificate.Ifyoufailtoincludeallintermediatecertificates,thenthebrowserwillneedtodownloadthemuntilitfindsoneinitstrustedrootstore.YoucanalsouseatechniquecalledOnlineCertificateStatusProtocol(OCSP)stapling,byembeddingrevocationdatasobrowsersdon'tneedtocheckacertificaterevocationlist.
Bothofthesecertificatetechniquesmayincreasethesizeofpayloads,whichcanbeanissueifbandwidthisaconcern.However,theywillreducethenumberofmessages,whichwillincreaseperformanceiflatencyisthemainproblem,whichisusuallythecase.Keepingkeysizessmallalsohelpsalittlewithbandwidth.Itishardtorecommendonegenericapproach.Therefore,asalways,testforyouruniquesituation.
ThereisalsoanalternativestreamciphercalledChaCha/Poly,whichisespeciallyusefulformobiledevices.ThisusestheChaCha20streamcipherandthePoly1305MessageAuthenticationCode(MAC)algorithmtocreateasecurealternativetoRC4.AESisablockcipherandisfastwithhardwaresupport,butmanymobiledevicesandsomeoldercomputersdon'thavethisacceleration.ChaCha/Polyisfasterwhenusingjustsoftware.Therefore,thisisbetterforbatterylife.ThisissupportedinChrome,includingChromeforAndroid,andinFirefox(fromversion47).
Note
Asallalgorithmsaredifferent,youcan'tdirectlycomparekeysizesasameasureofhowsecuretheyare.Forexample,a256bitECDHEkeyisequivalenttoa3072bitRSAkey.AESisverysecurewithrelativelysmallkeys,butyoucannotuseitforkeyexchange.ChaCha/PolyismorecomparabletothesecurityofAES256thanAES128.
InthefollowingscreenshotofChromeonAndroid,youcanseethatwhenconnectingtohuxley.unop.uk,ChromeusesCHACHA20_POLY1305asthestreamcipher,ECDHEforthekeyexchange,andECDSAforthesignature:
Note
ThenewversionofTLS(1.3)isstilladraft,butitmaybefinalizedsoon.ItlookslikeitwillonlyallowAuthenticatedEncryptionwithAdditionalData(AEAD)ciphers.AES-GCMandChaCha/Polyaretheonlytwociphersthatcurrentlymeetthesecriteria.Itwillalsoremovesomeotherobsoletefeatures,suchasTLScompression.
ItmaysometimessoundlikeusingTLSisnotalwaysworthit,butitisanexcellentideatouseHTTPSonyourentiresite,includinganythird-partyresourcesthatyouloadin.Bydoingthis,youwillbeabletotakeadvantageoftheperformanceenhancingfeaturesofHTTP/2,whichincludetechniquesthatmeanthatitisnolongercrucialtoserveresources(suchasJavaScriptlibraries)frommultipledomains.YoucansecurelyhosteverythingyourselfandavoidtheDNS,TCP,andTLSoverheadofadditionalrequests.AllofthiscanalsobefreebecauseLet'sEncryptandCloudFlareprovidecertificatesatzerocost.Let'slookatHTTP/2indetailnow.
HTTP/2
Asthenamesuggests,HTTP/2isthenewversionofHTTP.Itcontainssomesignificantperformanceimprovementsforthemodernweb.ItwaspredatedbySPDY,whichhassincebeendeprecatedinfavorofHTTP/2.
Asmentionedpreviously,thefirststeptowardusingHTTP/2istouseHTTPSonyourentiresite.Althoughnottechnicallyrequired,mostclients(allthemajorbrowsers)mandatetheuseofTLStoenableHTTP/2.ThisismainlyduetotheApplication-LayerProtocolNegotiation(ALPN)thatTLSprovides,whichallowseasysupportforHTTP/2.Italsostopsproxyserversfrommessingupthedata,whichmanyISPsusetoreducetheircostsandrecordwhattheircustomersdoonline.
HTTP/2improvesperformanceinanumberofways.Itusescompressionevenfortheheaders,andmultiplexing,whichallowsmultiplerequeststosharethesameconnection.Italsoallowstheservertopushresourcesthatitknowstheclientwillneedbeforetheclienthasrealizeditneedsthem.Although,thisrequiressomeconfigurationtosetthecorrectheadersanditcanwastebandwidthifitisoverused.
Multiplexinghasimplicationsforbundlingandimageconcatenation(sprites),whichwewilltalkaboutinthecompressionsectionlateroninthischapter.Thisalsomeansthatyoudon'tneedtosplitassetsovermultipledomains(shards),wheretheextraoverheadsmayevenslowthingsdown.However,youmaystillwishtouseacookie-freesubdomaintoservestaticassetswithoutcookies,eventhoughthenewheadercompressionmeansthatthebandwidthsavingswillbesmaller.Ifyouuseanakeddomain(withoutawww),thenyoumayneedanewdomainnameforcookie-lessuse.
YoucanidentifywhatversionofHTTPisusedtodeliveryourassetsusingthebrowserdevelopertools.InFirefox,youcanseethisonthedetailspanelofthenetworktab.YouwillseetheversionlistedasHTTP/1.1whentheoldprotocolisinuse.
Thefollowingscreenshotshowsthatpacktpub.comusesHTTP/1.1:
Tip
InChrome,youcanright-clickonthecolumnheadersinthenetworkinspectorandaddaProtocolcolumn.Youcanalsoseemoredetailednetworkinformationbyenteringchrome://net-internalsintotheaddressbar.Thisdisplaysthings,suchassessionsforHTTP/2andQuickUDPInternetConnections(QUIC)—anexperimentalmultiplexedstreamtransport.
Thefollowingscreenshotshowsthatemoncms.orgalsousesHTTP/1.1,eventhoughTLSisconfigureddifferently.TheencryptedtransportlayeristransparenttoHTTP:
WhenHTTP/2isused,youwillseetheversionlistedasHTTP/2.0.Thefollowingscreenshotdisplaysthisforhuxley.unop.uk,anditalsodisplaysCORS,caching,andcontentcompressionheaders:
WebSockets
WebSocketsisadifferentprotocoltoHTTP.However,HTTPinitiatesitanditusesthesameports,sowe'lldiscussitbrieflyhere.ThisHTML5featureisusefulforpushnotificationsandRealTimeCommunication(RTC)applications.WebSocketsusethews://andwss://protocolprefixesinsteadofhttp://andhttps://.OnceestablishedbyanexistingHTTPconnection,theprotocolisfull-duplexandbinaryincontrasttoHTTP/1.
BeforeWebSockets,ifyourwebserverwantedtonotifyaclientofachange,thenyouwouldhavetouseatechnique,suchaslongpolling.Thisiswhereawebrequestisheldopenbytheserverincaseitwantstosendsomething.Whentherequestgetsaresponseorittimes-out,itisre-established.Needlesstosay,pollingisneververyefficient.
Pushnotificationscanimproveperformancefromauser'spointofviewbecausetheyreceiveupdatesassoonastheyoccur.Theydon'tneedtorefreshanythingorkeepchecking.Youcanimmediatelyrespondtotheuserwhenalongrunningprocessstarts,runitasynchronously,andnotifythemimmediatelyuponitscompletion.
Socket.IOisapopularWebSocketlibraryforNode.js.Toseeitinaction,youcanlookinthebrowserdevelopertoolsonasitethatusesit.Forexample,ifyouopenthedevtoolsandgotohttps://www.opentraintimes.com/maps/signalling/staines,youwillseetheconnectionbeingupgradedfromHTTPStoWSS(orfromHTTPtoWSifyouusetheinsecureversion).
WebSocketspredateHTTP/2,buttheyarestillrelevantdespitethenewserverpushtechnology.Thesetwofeaturesappearsimilar,buttheyservedifferentpurposes.WebSocketsareforreal-timeandtwo-waydatatransfers,andserverpushiscurrentlyjusttopreload.
Note
InadditiontoHTTP/2serverpushpreloading,thereisanewbrowserfeaturethatiscurrentlysupportedinAndroid,Chrome,andOpera,whichallowsyoutodeclareresourcepreloadinginmarkupusingrel="preload"onalinktag.Youcanreadthespecatw3c.github.io/preloadandcheckthecurrentstateofbrowsersupportatcaniuse.com/#feat=link-rel-preload.
InChrome,theprotocolswitchwilllooksomethinglikethefollowingscreenshot.Youcan'tseethecontentsofaWebSocketconnection,soyouwon'tbeabletoviewthedatabeingtransferredfromwithinthedevtools:
ThereisaMicrosoftlibraryforASP.NET,whichiscalledSignalR.ThislibraryallowsyoutoperformpushnotificationswithWebSockets.Italsofallsbacktolongpollingiftheclientorserverdoesnotsupportthem.YouwillneedafairlyrecentversionofWindowsServer(2012orlater)andIIS(8.0andabove)touseWebSockets.
Unfortunately,thelateststableversion(SignalR2)doesnotsupport.NETCore.Thenewversion(SignalR3)isnotplannedforreleaseuntilaftertheReleasetomanufacturing(RTM)ofASP.NETCore,butthisisatoppriority.Youcantryabetaversion,butitmaybestablebythetimeyoureadthis.
Tip
YoumayalsowishtolookatStackExchange.NetGainasaWebSocketserver.
CompressionDatacompressionisabroadtopic,andwecan'thopetocoveritall.Here,wewilllearnaboutlosslesscompressionandhowtouseitinHTTP.Wewillalsocoverlossyimagecompressionofpictureslaterinthechapter.Compressionisimportantbecauseifwecanmakefilessmaller,wecanshortenthetimethatittakestotransferthemoveranetwork.
LosslesscompressionalgorithmsYoumayhavenoticedHTTPheadersfromsomeofthepreviousscreenshotswererelatedtoencoding.ThemostcommoncompressionalgorithmsforHTTParegzipandDEFLATE,whichareverysimilar.ThesearebothrelatedtothealgorithmusedinZIPfiles.IfyoudonotalreadyuseHTTPcompression,thenthisisaquickwin,anditwillimprovetheperformanceofyoursiteifyouenableit.
Therearemanyothermoreadvancedcompressionalgorithms,suchasxz,whichissimilartothe7-Zip(7z)formatandusestheLempel-Ziv-MarkovchainAlgorithm(LZMA/LZMA2).However,therearecurrentlyonlytwoadditionalalgorithmsincommonuseinmajorbrowsers.TheseareBrotliandSharedDictionaryCompressionforHTTP(SDCH).BotharefromGoogle,butonlyChromesupportsSDCH,anditrequiresalargedictionary.
Brotliismoreinteresting,andOperaandChrome(currentlybehindachrome://flags/#enable-brotliflag),andFirefoxbydefault(version44orhigher)supportit.BothbrowsersrequiretheuseofHTTPStosupportBrotli(yetanothergoodreasontouseTLS),andtheencodingtokenusedintheheadersisbr.Brotlipromisessignificantperformanceimprovements,especiallyformobiledevicesonslowconnections.
IfyouaccessasiteoverHTTP,youwillseethefollowingfortherequestheadersintheChromedevtoolsnetworkinspectorinthedetailsofarequest:
Accept-Encoding:gzip,deflate,sdch
However,ifyouuseHTTPSthenyouwillseethisinstead(afterenablingtheflag):
Accept-Encoding:gzip,deflate,sdch,br
TheservercanthenrespondwithBrotli-encodedcontentusingthisresponseheader:
Content-Encoding:br
Forexample,ifyouvisithttps://www.bayden.com/test/brotliimg.aspxinasupportedbrowser,thenBrotliwilldeliverthecontent(animageofastar).Hereisasubset(forclarityandbrevity)oftherequestheadersfromChrome:
GET/test/brotliimg.aspxHTTP/1.1
Host:www.bayden.com
Connection:keep-alive
Accept-Encoding:gzip,deflate,sdch,br
Thisisasubsetofthecorrespondingresponseheaders:
HTTP/1.1200OK
Content-Type:image/png
Content-Encoding:br
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
YourAcceptEncoding:gzip,deflate,sdch,br
Fiddler(theawesomeHTTPdebuggingproxybyEricLawrencethatwementionedpreviously)alsosupportsBrotliwithasimpleadd-on(drophttps://bayden.com/dl/Brotli.exeintofiddler2\toolsandrestartit).Youcanusethistoeasilytesttheimpactonyoursitewithoutdeployinganythingtoyourwebservers.
BundlingandminificationBundlingandminificationaretechniquesthatyoumayalreadybefamiliarwith.Theyspeedupthedeliveryofstaticassets.Theyareusuallyusedfortextfiles,suchasJavaScriptandCSScontent.
Bundling
Bundlingisthetechniqueofcombiningorconcatenatingmultiplefilestogethersothattheycanbedeliveredasone.ThisisagoodideawhenusingHTTP/1.1becausethenumberofconcurrentconnectionsislimited.However,bundlingislessnecessarywithHTTP/2,andinfact,itcanreduceperformance.ThenewmultiplexinginHTTP/2meansthatthereisnolongeralargepenaltywhenyourequestmanyfilesinsteadofonethatcontainallofthesamecontent.Youcantakeadvantageofthisbyonlydeliveringwhatisneededforapageratherthantheentireclientsidecodebaseforeverypage.Evenifyouselectivelybundleperpage,thiscouldbeinefficient.
Forexample,youmayincludeavalidationlibraryforusewithforms.However,becausethisisbundled,itwillbesenttoallpages,includingtheoneswithnoformstovalidate.Ifyouhaveaseparatebundleforvalidatedpages,thentheremaybeduplicationinthecommoncorecodethatisalsosent.Bykeepingthingsseparated,theclientcancachethemindividuallyandreusecomponents.Thisalsomeansthatifyouchangesomething,youonlyneedtoinvalidatethecacheofthisonepart.Theclientcankeepusingtheotherunmodifiedpartsandnothavetoredownloadthem.
Asalways,youshouldmeasureforyourparticularusecase.Youmayfindthatbundlingstillreducesthetotalfilesize.TheoverheadsforHTTP/2aremuchlowerbutstillnotzero,andcompressioncanworkbetteronlargerfiles.However,keepinmindtheimplicationsforcachingandreusability.
Minification
Minificationistheprocessofreducingthefilesizeofatextualstaticasset.Wedothisbyvariousmeans,includingstrippingoutcomments,removingwhitespace,andshorteningvariablenames.Itcanalsobeusefultoobfuscatecodetomakeithardertoreverseengineer.MinificationisstillusefulwhenyouuseHTTP/2,butyoushouldbecarefulwhentestingtocomparepreminifiedandpostminifiedfilessizeafterthelosslesscompressionhasalsobeenapplied.
Asdiscussedpreviously,youshoulduseHTTPcontentcompressionwithatleastthegziporDEFLATEalgorithms.Theseareprettyefficient;so,youmayfindthatwhencompressed,yourminifiedfileisnotmuchsmallerthanthecompressedrawsourcefile.
ChangesinASP.NETCore
Inthefull.NETFrameworkandpreviousversionsofMVC,therewasanintegratedbundlingandminificationsystem.ThishaschangedforASP.NETCore,andtherearenewtoolstoperformthiswork.
Thenewtoolsthatwereadoptedincludethetaskrunnergulp,althoughyoucanuseGruntifyoupreferto.Also,ageneratortoolcalledYeomanisusedforscaffolding.Therearenowpackagemanagers,suchasBowerandnpm,whicharesimilartoNuGet,butforfrontendlibraries.Forexample,NuGetnolongerdeliversjQueryandTwitterBootstrap,andtheyuseBowerinsteadbydefault.
MostofthesetoolsarewritteninJavaScript,andtheyrunonNode.js.ThepackagemanagerforNode.jsisnpm.Thesetoolsarepopularinotheropensourcewebframeworks,andtheyarewellestablished.They'renotnewtothescene,onlynewto.NET.
Gulppackagescomefromnpmandareresponsiblefortheminificationofyourstaticassets.Thisisnowdoneatbuildtime,asopposedtorequesttime,aswaspreviouslythecase.Itworksmuchmorelikeastaticsitegeneratorthanadynamicwebapplication.Agulpfile(gulpfile.js)intherootofyourprojectconfiguresthesetasksusingJavaScript.
ThenewtoolingisnotonlyrestrictedtoASP.NETCore,andyoucanusethesefeatureswithtraditionalASP.NETapplicationsinVisualStudio.Thisisagoodexampleofthecross-pollinationandbenefitsthatthenewframeworkscanprovidetotheexistingones.
ImageoptimizationDigitalmediacompressionismuchmorecomplicatedthanthelosslessfilecompressionthatwetalkedaboutpreviouslyevenifwejuststicktoimages.WebrieflymentionedwhentousePNGandwhentouseJPEGinthepreviouschapter.Here,we'llgointomuchmoredetailandexploresomeotherexoticoptions.
Wecoveredtheruleofthumb,whichsaysthatPNGisthebestimageformatforiconsandJPEGisbetterforphotos.Thesetwoformatsarethemostcommonforlosslessandlossyimagecompression,respectively.
Wewilltalkmoreaboutotherimageformatslater,butyouareusuallyconstrainedtothepopularformatsbywhatbrowserssupport.So,howcanyougetmoreoutofthecommonchoices?
PNG
PortableNetworkGraphics(PNG)isalosslessimagecompressionformatthatinternallyworkssimilarlytoaZIPfile(usingtheDEFLATEalgorithm).It'sagoodchoiceforimagesthatcontainsolidblocksofcolor,andithasabetterquality(withmorecolors)thantheoldGraphicsInterchangeFormat(GIF).
PNGsupportstransparencyinallmodernbrowsers,soyoushoulduseitinsteadofGIFforstaticimages.ThisisnotaproblemunlessyouneedtosupportInternetExplorer6,inwhichcasethisisprobablytheleastofyourtroubles.PNGalsosupportsanimationwithAnimatedPNG(APNG)files.ThesearelikeanimatedGIFsbutofamuchhigherquality.Unfortunately,onlyFirefoxandSafarisupportAPNGs.
Tip
Agreatsitetolookupwhichbrowserssupportaparticularfeatureiscaniuse.com.Youcansearchforfeaturesupport,thencheckthisagainsttheuseragentanalyticsofyoursite.Forexample,youcouldsearchforPNG-alpha,Brotli,orAPNG.
SomeZIPalgorithmimplementationsarebetterthanothers,andtheyproducesmallerfilesthatcanstillbedecodedbyeveryone.Forexample,7-ZipismuchmoreefficientthanmostotherzipcompressionsoftwareonWindows,evenwhenusingtheZIPformat,notitsnative7zformat.Likewise,youcancompressaPNGmorecompactlywithoutlosinganydataandstillhaveitworkinallbrowsers.Thisusuallycomeswithahigherupfrontcomputationalcost.However,ifyoucompressstaticassets,whichrarelychange,thenitcanbewellworththeeffort.
YoumayalreadyusethePNGOUTtooltolosslesslyreducethesizeofyourPNGimages.Ifyou'renot,thenyouprobablyshould.Youcanreadmoreaboutitanddownloaditatadvsys.net/ken/utils.htm.
However,thereisanewalgorithmcalledZopflithatoffersbettercompression,butitisveryslowtocompress.Decompressionisjustasquick,soit'sonlyasingleoptimizationcostfor
precompiledresources.ZopfliisaprecursortoBrotli,butit'scompatiblewithDEFLATEandgzip,asit'snotanewformat.
YoucangetZopflifromgithub.com/google/zopfli,butyoushouldalwaystestwithyourimagesandverifythatthereisindeedafilesizereduction.Youwillfindthatthesetoolscanhelpyoudeliveryourassetsquickerandachievehigherperformance.
Youmayalsousethepracticeofcombiningmanyspritesintooneimage.Aswithbundling,thisislessnecessarywhenusingHTTP/2.However,thesamecaveatsapplyaswithcompression,andyoushouldalwaystestforyoursetofimages.
JPEG
JPEGisalossyimagecompressionformat,whichmeansthatitusuallydiscardsdatafromthepicturetomakeitsmaller.Itisbestsuitedtonaturalgradientsandcontinuoustones,suchasthosefoundinphotographs.JPEGdoesnotsupporttransparencylikePNGdoes,soifyouwanttouseoneondifferentbackgrounds,thenyouwillneedtoprerenderthem.
Tip
It'sagoodspacesavingideatoremovetheExchangeableimagefileformat(Exif)metadatafromyourJPEGfilesfortheweb.Thiscontainsinformationaboutthecamerausedandgeographicdataofwherethephotowastaken.
JPEGhasaqualitysetting,whichaffectstheimagefilesizeandthelevelofdetail.Thelowerthequality,thesmallerthefile,buttheworseitwilllook.Youcanperformtestsonyourimagestoseewhatsettingsprovideanacceptabletrade-off.Crucially,thebestvalueforthisqualitysettingwillvaryperimage,dependingonthecontent.Therearetoolsthatallowyoutoautomaticallydetecttheoptimalqualitylevel,suchasGoogle'sbutteraugli.
ThereisaninterestingprojectfromMozilla(themakersoftheFirefoxbrowser)calledmozjpeg.ThisaimstobettercompressJPEGimagesandissimilartowhatPNGOUTandZopflidoforPNGimages.YoucanusemozjpegtocompressyourJPEGimagestoasmallersizethannormal,withoutaffectingdecompressionorquality.Itisavailableatgithub.com/mozilla/mozjpeg,butyouwillneedtocompileityourself.Asalways,resultsmayvary,sotestitforthephotosonyoursite.
JPEGArchive(github.com/danielgtaylor/jpeg-archive)isahandytoolthatusesmozjpegtocompressJPEGimages,usingvariouscomparisonmetrics.Anothersimilartoolisimgmin(github.com/rflynn/imgmin),whichisslightlyolder.
Otherimageformats
Manyotherimageformatsareavailable,butyouareusuallylimitedonthewebbywhatbrowserssupport.Asdiscussedinthepreviouschapter,youshouldn'tscaleimagesinthebrowser,oryouwillgetpoorperformance.Thisusuallymeanshavingtosavemultipleseparatecopiesofsmaller
images,forexample,whendisplayingthumbnails.Clearlythisresultsinduplication,whichisinefficient.Someofthesenewimageformatshavecleversolutionstotheproblemofresponsiveandscalableimages.
BPGisanimageformatbythetalentedFabriceBellard,andyoucanreadmoreaboutitatbellard.org/bpg.IthasaJavaScriptpolyfilltosupportbrowsersbeforenativesupportisaddedtoanyofthem.
WebPisanimageformatfromGoogle,andonlyChrome,Android,andOperasupportit.IthasimpressivespacesavingsoverJPEG,anditwillbeagoodchoiceifitbecomesmorewidelysupported,socheckcaniuse.comforthelatestadoptionstats.
JPEG2000isanimprovedversionofJPEG,althoughitmaybeencumberedbysoftwarepatents,soithasn'tseenwidespreadadoptionoutsideofmedicalimaging.OnlySafarisupportsJPEG2000,andthereisalsoJPEGXR,whichisonlysupportedinIE.
WhereasJPEGusesaDiscreteCosineTransform(DCT),JPEG2000isbasedonaWaveletTransform.Oneofthepropertiesthisprovidesisaprogressivedownload.Thismeansthattheimageisstoredinsuchawaythatifyoudownloadasmallpartfromthebeginningofthefile,thenyouhaveasmallerandlowerqualityversionofthefullimage.Thishasobviousapplicationsforresponsiveandscalableimages.Thebrowserwouldonlyneedtodownloadenoughoftheimagetofilltheareaitisrenderingto,andthefileneedonlybestoredonce.Noresizingandnoduplicationforthumbnailswouldberequired.ThistechniqueisalsousedintheFreeLosslessImageFormat(FLIF).
FLIFisoneofthemoreexcitingupcomingimageformats,asitisprogressiveandresponsive,butfreeandnotpatented.FLIFisstillindevelopment,butitpromisestobeveryusefulifbrowserssupportit,andyoucanreadmoreaboutitatflif.info.
Note
JPEGandPNGcansupportprogressivedownload,butthisisn'tnormallyusefulforresponsiveimages.ProgressiveJPEGsubjectivelyloadsmoregracefullyandcanevenmakefilessmaller,butinterlacedPNGusuallymakesfilesbigger.
Theproblemisthatmostoftheseprogressiveimageformatsarenotyetreadyforthemainstreambecauseallofthemajorbrowsersdonotsupportthem.It'sagoodideatokeepaneyeonthefuture,butfornow,weneedtoresizeimagesforhighperformance.
Resizingimages
Untilnewimageformatsgainwidespreadadoption,resizingisstillrequired,andyoumayneedtodothisdynamicallyfordifferentdevices.Perhaps,youalsohaveuser-submittedimagecontent,althoughyouneedtobeverycarefulwiththisfromasecuritypointofview.Someimagelibrariesarenotsafe,andaspecially-craftedimagecanexploityoursystem.Infact,manyimage-processinglibrarieshaveissueswhentheyareusedinawebcontext.
Ifyouarenotextremelydiligentandcareful,thenyoucaneasilyendupwithmemoryleaks,whichcantakedownyourwebserver.Itisalwaysagoodideatoseparateandsandboxaprocessthatdealswithlargemediafiles.
Comingfroma.NETstandpoint,itcanbetemptingtouseWinFormsSystem.DrawingoritsWPFsuccessor(System.Windows.Media).However,theseweredesignedfordesktopsoftware,andMicrosoftstronglyrecommendsagainstusingtheminaserviceorwebapplication.MicrosoftrecommedstheWindowsImagingComponent(WIC),butthisisaComponentObjectModel(COM)APIthatismeantforusefromCorC++apps.Inadditiontothis,noneoftheseimaginglibrariesarecross-platform,sotheyarenotsuitableforusein.NETCore.
IfyouuseWindows,thenyoucouldtryusingImageResizerbyImazen(imazen.io),fromimageresizing.net.WhileitstillusestheGDI+System.Drawing,itisprettybattlehardened,somostofthebugsshouldhavebeenworkedout.There'salsoDynamicImage,whichwrapsthenewerWPFimagefunctionsandusesshaders.Youcanreadmoreaboutitatdynamicimage.apphb.com,althoughithasn'tbeenupdatedinawhile,anditdoesn'tsupport.NETCore.
ApopularoptioninopensourcecirclesisImageMagick,whichwe'vementionedpreviously,andaforkcalledGraphicsMagick,whichclaimstobemoreefficient.AnotherpopularimagelibraryisLibGD,andit'ssuitableforserveruse.Youcanreadmoreatlibgd.github.io.Althoughit'swritteninC,therearewrappersforotherprogramminglanguages,forexample,DotnetGDtargeting.NETCore.
Oneofthefeaturesthat.NETCorelacksisthatthereisnotyetacompellingoptionforimageprocessing.ImageResizer5mayhelpwiththiswhenreleased,soitisworthkeepinganeyeonit.Nativecodesupportisnowmuchbetterin.NETCore,asitwasapaintodoinclassic.NET,whichmayhelpwithintegratingnativecross-platformimaginglibraries.
Thereisalsoanewcross-platformversionoftheopensourceImageProcessorlibraries(imageprocessor.org),calledImageProcessorCore,whichshowspromise.However,thisisstillaworkinprogress,anditisnotyetstable.Ifyouwanttotryitout,thenyoucangetthenightlypackagesfromMyGetorbuilditfromsource.
Note
Platformsupportandcompatibilitychangesrapidly,socheckANCLAFS.comforthelatestinformation.Feelfreetocontributetothislistortotheprojects.
Fornow,itmaybeeasiertoinstallanopensourceservice,suchasThumbor,oruseacloud-basedimagingservice,suchasImageEngine(WURFL.io)orCloudinary,whichwe'vealreadymentioned.Imagemanipulationisacommontask,anditiseffectivelyasolvedproblem.Itmaybebettertouseanexistingsolutionandnotreinventthewheel,unlessit'spartofyourcorebusinessoryouhaveveryunusualrequirements.
Tip
Onceyouhaveyourresizedimages,youcanloadthemresponsivelywiththepictureandsourcetagsusingthesrcsetandsizesattributes.Youcanalsousethistechniquetoprovidenewerimageformats(suchasWebP),withafallbackforbrowsersthatdon'tyetsupportthem.OryoucanuseClientHints(refertohttpwg.org/http-extensions/client-hints.htmlandcaniuse.com/#feat=client-hints-dpr-width-viewport).
CachingItisoftensaid(originallybyPhilKarlton)thatcachingisoneofthehardestproblemsincomputerscience,alongwithnamingthings.Thismaywellbeanexaggeration,butcachingiscertainlydifficult.Itcanalsobeveryfrustratingtodebugifyouarenotmethodicalandpreciseinyourapproach.
Cachingcanapplyatvariousdifferentlevelsfromthebrowsertotheserverusingmanydiversetechnologies.Yourarelyusejustasinglecacheevenifyoudon'trealizeit.Multiplecachesdon'talwaysworkwelltogether,andit'svexingifyoucan'tclearone.
Webrieflytoucheduponcachinginthepreviouschapter,andwe'llgointomuchmoredetailinChapter7,LearningCachingandMessageQueuing.However,ascachinghasanimpactonnetworkperformance,we'llcoverithereaswell.
BrowserAlotofcachinghappensinthewebbrowser,whichisinconvenientbecauseasyoudon'thavedirectcontroloverit(unlessit'syourbrowser).Askinguserstocleartheircacheisunsatisfactoryandconfusingtomany.Yet,youcanexertinfluenceonhowbrowserscacheresourcesbycarefullycontrollingtheHTTPheadersthatyousetandtheURLsthatyouuse.
Ifyoufailtodeclarewhatresourcesarecacheableandforhowlong,thenmanybrowserswilljustguessthis.Theheuristicsforthiscanbewildlydifferentbetweenimplementations.Therefore,thiswillresultinsuboptimalperformance.Youshouldbeexplicitandalwaysdeclarecacheinformationeven(andespecially)forassetsthatshouldn'tbecachedbymarkingthemasnoncacheable.
Tip
Youneedtobevigilantwithwhatyouadvertiseascacheablebecauseifyouarecareless,thenyoucangetyourselfintoasituationwhereyou'reunabletoupdatearesource.Youshouldhaveacache-bustingstrategyinplace,andtested,beforeusingcaching.
Therearevarioustechnologiesthatareusedaretocacheinbrowsers.ManydifferentHTTPheaderscanbeset,suchasAge,Cache-Control,ETag(EntityTag),Expires,andLast-Modified.Thesecomefromafewdifferentstandards,andtheinteractionscanbecomplex,ortheyvarybetweenbrowsers.WewillexplaintheseinmoredetailinChapter7,LearningCachingandMessageQueuing.
AnothertechniqueistouseauniqueURLforcontent.IfaURLchanges,thenabrowserwilltreatitasadifferentresource,butifitisthesame,thenitmayloaditfromitslocalcache.Someframeworkscalculateahashofthefilecontents,andthentheyusethisasaquerystringparameter.Thisway,whenthecontentsofthefilechanges,sodoestheURL.
Thereareotherandmoremodernfeaturesthatyoucanusetocache,suchastheHTML5ApplicationCache(orAppCache).Thiswasdesignedforofflinewebapplicationsandwasn'tveryflexible.Bustingthecachewascomplicatedtoputitmildly.AppCacheisalreadydeprecated,andyoushoulduseServiceWorkersinstead.Theseprovidemuchmoreflexibility,althoughsupportisprettyrecent.
Therearemanyimprovementscoming,inthelatestbrowsersthatgiveyoumorecontrol,andwe'llalsoshowyouhowtousetheminChapter7,LearningCachingandMessageQueuing.
ServerThewebserverisagreatplacetocachebecauseitisusuallyunderyourcompletecontrol.However,it'snotreallypartofnetworkperformance,apartfromgeneratingthecorrectheaders.Therecanbeothergreatperformancebenefitswithserver-sidecachingintermsofimprovingthespeedtogeneratepages,butwewillcovertheseinlaterchapters.
Ifyouusethetraditional.NETFrameworkonMicrosoft'sInternetInformationServices(IIS)webserver,thenyoucanuseoutputcachingfromwithinyourapplication.Thiswilltakecareofsettingthecorrectheadersandsending304(NotModified)responsestobrowserrequests.Itwillalsocachetheoutputontheserverinmemory,ondiskorusingMemcached/Redis.Youcanaddattributestoyourcontrolleractionmethodstocontrolthecachingoptions,butotherwaysofdoingthisareavailable,forexample,intheconfigurationfiles.
OutputCacheisnotavailableinASP.NETCore,butyoucanuseResponseCachetosetthecorrectheaders.Theoutputisnotcachedontheserver,butyoucaninstallacachingproxyinfrontofit.Again,wewillcoverthismoreanddemonstrateserver-sidecachinginChapter7,LearningCachingandMessageQueuing.
IfyouwanttodisablecachingonanASP.NETCorepage,thenaddthisannotationtoyourcontrolleraction:
[ResponseCache(NoStore=true,Duration=0)]
ThiswillsetthefollowingheaderontheHTTPresponseandensurethatitisnotcached:
Cache-Control:no-store
Tocacheapageforanhour,addthefollowinginstead,Durationisinseconds:
[ResponseCache(Duration=3600,VaryByHeader="Accept")]
Thecachecontrolheaderwillthenlooklikethefollowing:
Cache-Control:public,max-age=3600
There'splentymoretosayaboutothercachingconfigurationoptionsandprofiles.Therefore,ifyou'reinterested,thenreadthelaterchapters.It'sacomplextopic,andwe'veonlyscratchedthesurfacehere.
Note
YoucanreaddocumentationaboutresponsecachinginASP.NETCoreatdocs.asp.net/en/latest/performance/caching/response.html.
Thesecachingdirectivesnotonlyinstructthebrowser,buttheyalsoinstructanyproxiesontheway.Someofthesemaybeinyourinfrastructureifyouhaveacachingproxy,suchasSquid,
Varnish,orHAProxy.Orperhaps,youhaveaTLS-terminatingloadbalancer(suchasAzureApplicationGateway)toreducetheloadonyourwebserversthatalsocaches.Youcanforciblyflushthecachesofserversthatyoucontrol,buttheremaybeothercachesinbetweenyouandyouruserswhereyoucan'tdothis.
ProxyserversbetweenyouandyourusersTherecanbemanyproxyserversbetweenyouandyourusersoverwhichyouhavenodirectcontrol.Theymayignoreyourcachingrequests,blockpartsofyoursite,orevenmodifyyourcontent.ThewaytosolvetheseproblemsistouseTLS,aswehavealreadydiscussed.TLScreatesasecuretunnelsothattheconnectionbetweenyourinfrastructureandthebrowsercan'teasilybetamperedwith.
CorporateproxiescommonlyManintheMiddleattack(MitM)yourconnectiontotheusersothattheycanspyonwhatemployeesaredoingonline.Thisinvolvesinstallingacustom-trustedrootcertificateonusers'workstationssothatyourcertificatecanbefaked.Unfortunately,thereisn'tmuchyoucandoaboutthis,apartfromeducatingusers.Certificatepinningiseffectiveinnativeapps,butit'snotsousefulforwebapplications.HTTPPublicKeyPinning(HPKP)isavailablebut,asitisaTrustonFirstUse(TOFU)technique,theinitialconnectioncouldbeintercepted.Clientcertificatesareanotheroption,buttheycanbedifficulttodistribute,andtheyaren'tcommonlyused.
MitMcanbeusefulifyoutrustthethirdpartyandremainincontrol.ThisisusedbysomeContentDeliveryNetworks(CDNs)tospeedupyoursite.
CDNs
CDNscanimprovetheperformanceofyoursitebystoringcopiesofyourcontentatlocationsclosertoyourusers.Services,suchastheonesprovidedbyCloudFlare,performaMitMonyourconnectionandsavecopiesatdatacentersaroundtheworld.Thedifferencefromanunauthorizedproxyisthatyoucontroltheconfiguration,andyoucanpurgethecachewheneveryoulike.
Youshouldbecarefulbecauseifyoudon'tusethecachingfeatures,thenthiscanreducetheresponsivenessofyoursiteduetotheextrahopsinvolved.MakesurethatyoumonitortheresponsetimeswithandwithoutaCDN,andyouneedafallbackplanincasetheygodown.
AnothercommonusecaseforCDNsistodistributepopularlibraries,forexample,thejQueryJavaScriptlibrary.TherearefreeCDNsfromjQuery(MaxCDN),Google,Microsoft,andcdnjs(CloudFlare)thatdothis.Thehypothesisisthatausermayalreadyhavethelibraryfromoneoftheseintheircache.However,youshouldbeextremelycarefulthatyoutrusttheproviderandconnection.Whenyouloadathird-partyscriptintoyoursite,youareeffectivelygivingthemfullcontroloveritoratleastrelyingonthemtoalwaysbeavailable.
IfyouchoosetouseaCDN,thenensurethatitusesHTTPStoavoidtamperingwithscripts.Youshoulduseexplicithttps://URLsonyoursecurepagesoratleastprotocolagnosticURLS(//),andneverhttp://.Otherwise,youwillgetmixedcontentwarnings,whichsomebrowsersdisplayastotallyunencryptedorevenblock.
YouwillneedafallbackthatishostedonyourownserversanywayincasetheCDNgoesdown.IfyouuseHTTP/2,thenyoumayfindthatthereisnoadvantagetousingaCDN.Obviously,
alwaystestforyoursituation.
TherearesomeusefulnewfeaturesinASP.NETCoreviewstoeasilyenablelocalfallbackforCDNresources.We'llshowyouhowtousethemandotherfeaturesinlaterchapters.
SummaryInthischapter,youlearnedhowtoimproveperformanceatthenetworklevelbetweentheedgeofyourinfrastructureandyourusers.Younowknowmoreabouttheinternetprotocolsunderyourapplicationandhowtooptimizeyouruseofthemforbesteffect.
Youlearnedhowtotakeadvantageofcompressiontoshrinktextandimagefiles.Thiswillreducebandwidthandspeedupdeliveryofassets.Wealsohighlightedcaching,andyoushouldnowseehowimportantitis.We'llcovercachingmoreinChapter7,LearningCachingandMessageQueuing.
Inthenextchapter,youwilllearnhowtooptimizetheperformanceinsideyourinfrastructure.YouwillseehowtodealwithI/Olatency,andhowtowritewell-performingSQL.
Chapter5.OptimizingI/OPerformanceThischapteraddressesissuesthatoftenoccurwhenyoutakeyourfunctionallytestedapplicationandsplititupintopartsfordeployment.Yourwebservershostthefrontendcode,yourdatabaseissomewhereelseinthedatacenter,youmayhaveaStorageAreaNetwork(SAN)forcentralizedfiles,anappserverforAPIs,andthevirtualdisksareallondifferentmachinesaswell.
Thesechangesaddsignificantlatencytomanycommonoperationsandyourapplicationnowbecomessuperslow,probablybecauseit'stoochattyoverthenetwork.Inthischapter,youwilllearnhowtofixtheseissuesbybatchingqueriestogether,andperformingworkonthebestserverforthejob.Evenifeverythingrunsononemachine,theskillsthatyou'lllearnherewillhelptoimproveperformancebyincreasingefficiency.
Thetopicscoveredinthischapterincludethefollowing:
TheoperationsthatcanbeslowSelectN+1problemsindetailReturningonlywhatyouneedWritinghigh-performanceSQL
Youwilllearnabouttheoperationsthatyoushouldn'tusesynchronously,andhowtoqueryforgettingonlythedatathatyouneedinanefficientmanner.You'llalsoseehowtotameyourO/RM,andlearntowritehigh-performanceSQLwithDapper.
WebrieflycoveredsomeofthesetopicsinChapter3,FixingCommonPerformanceProblems,butherewe'lldiveintogreaterdetail.Thefirsthalfofthischapterwillfocusonbackgroundknowledgeandusingdiagnostictools,whilethesecondhalfwillshowyousolutionstoissuesyoumaycomeacross.You'llalsolearnaboutsomemoreunusualproblems,andhowtofixoralleviatethem.
We'llinitiallyfocusonunderstandingtheissues,becauseifyoudon'tappreciatetherootcauseofaproblem,thenitcanbedifficulttofix.Youshouldn'tblindlyapplyadvicethatyouread,andexpectittoworksuccessfully.Diagnosingaproblemisnormallythehardpart,andoncethisisachieved,itisusuallyeasytofixit.
Input/outputI/Oisageneralnameforanyoperationinwhichyourcodeinteractswiththeoutsideworld.TherearemanythingsthatcountasI/O,andtherecanbeplentyofI/Othatisinternaltoyoursoftware,especiallyifyourapplicationhasadistributedarchitecture.
Note
Therecentriseinpopularityofthe.ioTopLevelDomain(TLD)canbepartlyattributedtostandingforI/O,butthatisnotitsrealmeaning.AsisthecaseforsomeotherTLDs,itisactuallyacountrycode.Otherexamplesinclude.lyforLibyaand.tvforTuvalu(which,liketheneighboringKiribati,maysoonbesubmergedbeneaththePacificOceanduetoclimatechange).
TheTLD.ioisintendedfortheBritishIndianOceanTerritory(BIOT),acollectionoftinybutstrategicislandswithashamefulhistory.The.ioTLDisthereforecontrolledbyaUK-basedregistry.BIOTisnothingmorethanamilitarybase,andalsohappenstobeahopontheproposedAWEfiberopticcablebetweenAustraliaandDjibouti.
Inthischapter,wewillfocusonimprovingthespeedofI/O,notonavoidingit.Therefore,wewon'tcovercachinghere.BothI/Ooptimizingandcachingarepowerfultechniquesontheirown,andwhenthey'recombined,youcanachieveimpressiveperformance.SeeChapter7,LearningCachingandMessageQueuingformoreoncaching.
CategoriesofI/OThefirstchallengeistoidentifytheoperationsthattriggerI/O.Ageneralruleofthumbin.NETisthatifamethodhasanasynchronousAPI(MethodAsync()variants),thenitisdeclaringthatitcanbeslow,andmaybedoingI/Owork.Let'stakeacloserlookatsomeofthedifferentkindsofI/O.
Disks
ThefirsttypeofI/Owewillcoverisreadingfrom,andwritingto,persistentstorage.ThiswillusuallybesomesortofadiskdrivesuchasaspinningplatterHardDiskDrive(HDD),orasismorecommonthesedays,aflashmemory-basedSolidStateDrive(SSD).
HDDsareslowerthanSSDsforrandomreadsandwrites,butarecompetitiveforlargeblocktransfers.ThereasonforthisisthatthearmontheHDDhastophysicallymovetheheadtothecorrectlocationonthemagneticplatterbeforeitcanbeginthereadorwriteoperations.Ifthediskispowereddown,thenitcantakeevenlonger,astheplatterswillhavetoSpin-upfromastationarypositiontothecorrectrevolutionsperminute(rpm)beforehand.
Note
Youmayhaveheardtheterm"Spin-up"inreferencetoprovisioningagenericresource.Thishistoricallycomesfromthetimetakentospintheplattersonarotatingdiskuptotheoperationalspeed.Thetermisstillcommonlyused,eventhoughthesedaystheremaynotbeanymechanicalcomponentspresent.
Terminologylikethisoftenhasahistoricalexplanation.Asanotherexample,afloppydiskiconisnormallyusedtorepresentthesavefunction.Yetfloppydisksarenolongerinuse,andmanyyoungerusersmayneverhaveencounteredone.
Knowingwhattypeofdriveyourcodeisrunningonisimportant.HDDsperformbadlyifyoumakelotsofsmallreadsandwrites.Theyprefertohavebatchedoperations,sowritingonelargefileisbetterthanmanysmallerones.
Theperformanceofdisksissimilartothatofanetwork,inthatthereisbothlatencyandthroughput,oftencalledbandwidthinnetworkingparlance.ThelatencyofanHDDishigh,asittakesarelativelylongtimetogetstarted,butoncestarted,thethroughputcanberespectable.Youcanreaddatarapidlyifit'sallinoneplaceonthedisk,butitwillbeslowerifitisspreadallover,evenifthetotaldataisless.Forexample,copyingasinglelargefiledisk-to-diskisquick,buttryingtolaunchmanyprogramssimultaneouslyisslow.
SSDsexperiencefeweroftheseproblemsastheyhavelowerlatency,butitisstillbeneficialtokeeprandomwritestoaminimum.SSDsarebasedonflashmemory(similartothechipsusedinmemorycardsforphonesandcameras),andtheycanonlybewrittentoafixednumberoftimes.ThecontrollerontheSSDmanagesthisforyou,buttheSSD'sperformancedegradesovertime.
Aggressivewritingwillacceleratethisdegradation.
Multiplediskscanbecombinedtoimprovetheirperformanceandreliabilitycharacteristics.ThisiscommonlydoneusingatechnologycalledRedundantArrayofIndependentDisks(RAID).Dataissplitacrossmultiplediskstomakeitquickertoaccess,andmoretoleranttohardwarefailures.RAIDiscommoninserverhardware,butcanincreasethestartuptime,asSpin-upissometimesstaggeredtoreducethepeakpowerdraw.
HDDsoffermuchlargercapacitythanSSDs,andsoareagoodchoiceforstorageofinfrequentlyusedfiles.Youcangethybriddrives,whichcombineanHDDwithanSSD.Theseclaimtoofferthebestofbothworlds,andarecheaperthanSSDsofanequivalentsize.However,ifyoucanaffordit,andifyoucanfitallofyourdataonanSSD,thenyoushoulduseone.Youwillalsodecreaseyourpowerandcoolingrequirements,andyoucanalwaysaddanadditionalHDDformassstorageorbackups.
Virtualfilesystems
Fileaccesscanbeslowatthebestoftimesduetothephysicalnatureofthedisksstoringthedata,asmentionedpreviously.Thisproblemcanbecompoundedinavirtualizedenvironmentsuchasacloud-hostedinfrastructure.Thestoragedisksareusuallynotonthesamehostserverasthevirtualmachine,andwillgenerallybeimplementedasnetworkshareseveniftheyappeartobemountedlocally.Inanycase,thereisalwaysanadditionalproblem,whichispresentwhetherthediskisontheVMhostorsomewhereelseonthenetwork,andthatiscontention.
Onavirtualizedinfrastructure,suchasthoseprovidedbyAWSandAzure,yousharethehardwarewithotherusers,butaphysicaldiskcanonlyserviceasinglerequestatonce.Ifmultipletenantswanttoaccessthesamedisksimultaneously,thentheiroperationswillneedtobequeuedandtimeshared.Unfortunately,thisabstractionhasmuchthesamedetrimentaleffectonperformanceasreadinglotsofrandomfiles.Usersarelikelytohavetheirdataondiskstoredinlocationsdifferentfromothercustomers.Thiswillcausethearmonthedrivetofrequentlymovetodifferentsectors,reducingthroughputandincreasinglatencyforeveryoneonthesystem.
Allthismeansthatonsharedvirtualhosting,usinganSSDcanhaveabiggerpositiveperformanceimpactthannormal.EvenbetteristohavealocalSSD,whichisdirectlyattachedtotheVMhost,andnottoanothermachineonthenetwork.Ifdisksmustbenetworked,thenthestoragemachineshouldbeascloseaspossibletotheVMusingit.
YoucanpayextraforadedicatedVMhostwhereyouaretheonlytenant.However,youmayaswellthenberunningonbaremetal,andreapingthebenefitsofreducedcostsandhigherperformance.Ifyoudon'trequiretheeasyprovisioningandmaintenanceofVMs,thenabaremetaldedicatedservermaybeagoodoption.
ManycloudhostingprovidersnowofferSSDs,butmostonlyofferephemerallocaldisks.ThismeansthatthelocaldiskonlyexistswhileyourVMisrunning,andvanisheswhenitisshutdown,makingitunsuitableforstoringtheOSifyouwanttobringaVMbackupinthesamestate.
Youhavetowriteyourapplicationinadifferentwaytotakeadvantageofanephemerallocaldrive,asitcoulddisappearatanytime,andsocanonlybeusedfortemporaryworkingstorage.Thisisknownasanimmutableserver,whichmeansitdoesn'tchangeandisdisposable.ThisnormallyworksbetterwhentheOSisLinux,asitcanbetrickytobootstrapnewinstanceswhenrunningWindows.
Databases
Databasescanbeslow,becausetheyrelyondisksforthestorageoftheirdata,butthereareotheroverheadsaswell.However,DBsareusuallyabetterwayofstoringsignificantdatathanflatfilesondisk.Arbitrarydatacanberetrievedquicklyifitisindexed,muchquickerthanscanningafilebybruteforce.
Relationaldatabasesareamatureandveryimpressivetechnology.However,theyonlyshinewhenusedcorrectly,andhowyougoaboutqueryingthemmakesamassivedifferencetoperformance.DBsaresoconvenientthatthey'reoftenoverused,andaretypicallythebottleneckforawebapplication.
Anunfortunatelycommonanti-patternisrequiringadatabasecallinordertorenderthehomepageofawebsite.AnexampleiswhenyoutrytovisitawebsitementionedonliveTV,onlytodiscoverthatithascrashedduetotheMySQLDBbeingoverloaded.Thissortofawebsitewouldbebetterarchitectedasastaticsitewiththeclient-sidecodehittingcachedandqueuedwebAPIs.
ThepathologicalcaseforaslowDBiswherethewebserverisinonedatacenter,thedatabaseserverisinanother,andthedisksfortheDBareinathird.Also,alltheserversmaybesharedwithotherusers.Obviously,it'sbestnottoendupinthissituation,andtoarchitectyourinfrastructureinasaneway,butyouwillalwayshavesomelatency.
ThereareapplicationprogrammingtechniquesthatallowyoutokeepyournetworkandDBchattertoaminimum.Thesehelpyoutoimprovetheperformanceandresponsivenessofyoursoftware,especiallyifitishostedinahigh-latencyvirtualizedenvironment.Wewilldemonstratesomeoftheseskillslateroninthischapter.
APIs
Modernwebapplicationprogramminggenerallyinvolvesusingthird-partyservicesandtheirassociatedAPIs.It'sbeneficialtoknowwheretheseAPIsarelocated,andwhatthelatencyis.Aretheyinthesamedatacenter,oraretheyontheothersideoftheplanet?Unlessyou'vediscoveredsomeexcitingnewphysics,thenlightonlytravelssofast.
Note
Today,almostallintercontinentaldatatravelsbyfiberopticscables.Satellitesarerarelyusedanymore,asthelatencyishigh,especiallyforgeostationaryorbits.Manyofthesecablesareundertheoceans,andarehardtofix.IfyourelyonanAPIonadifferentcontinent,notonlycanit
slowyoudown,butitalsoexposesyoutoadditionalrisk.
Youprobablyshouldn'tbuildanimportantworkflowthatcanbedisruptedbyafishermantrawlinginthewrongplace.Youalsoneedtofurthersecureyourdata,assomecountries(suchastheUK)areknowntotapcablesandstorethecommunications,iftheycrosstheirborders.
OneoftheissueswithAPIsisthatlatencycancompound.YoumayneedtocallmanyAPIs,ormaybeanAPIcallsanotherAPIinternally.Thesesituationsarenotnormallydesignedthisway,butcangroworganicallyasnewfeaturesareadded,especiallyifnorefactoringisperformedperiodicallytotidyupanymess.
Onecommonformoflatencyisstartuptime.Websitescangotosleepifnotused,especiallyifusingthedefaultInternetInformationServices(IIS)settings.Ifawebsitetakesanon-negligibleamountoftimetowakeup,andalltherequiredAPIsalsoneedtowakeup,thenthedelayscanquicklyadduptoasignificantlagforthefirstrequest.Itmayeventime-out.
Thereareacoupleofsolutionstothisinitiallagproblem.IfyouuseIIS,thenyoucanconfiguretheapplicationpooltonotgotosleep.ThedefaultsinIISareoptimizedforsharedhosting,sotheywillneedtweakingforadedicatedserver.Thesecondoptionistokeepthesitealivebyregularlypollingitwithahealthcheckoruptimemonitoringtool.Youshouldbedoingthisanywaysothatyouknowwhenyoursitegoesdown,butyoushouldalsoensurethatyouareexercisingalltherequireddependencies(suchasAPIsandDBs).Ifyouaresimplyretrievingastaticpageorjustcheckingfora200statuscode,thenservicesmaygodownwithoutyourealizing.
Similarly,scalingcanhavealag.Ifyouneedtoscaleup,thenyoushouldpreheatyourloadbalancersandwebservers.ThisisespeciallyimportantifusinganAWSElasticLoadBalancer(ELB).Ifyou'reexpectingabigpeakintraffic,thenyoucanaskAWStohaveyourELBsprewarmed.AnalternativewouldbeusingAzureLoadBalancer,AzureApplicationGateway,orrunningHAProxyyourselfsothatyouhavemorecontrol.Youshouldalsoberunningloadtests,whichwe'llcoverinChapter9,MonitoringPerformanceRegressions.
NetworkdiagnosticstoolsAswediscoveredearlier,practicallyallI/Ooperationsinavirtualizedorcloud-hostinginfrastructurearenownetworkoperations.Disksanddatabasesarerarelylocal,asthiswouldpreventscalingouthorizontally.Therearevariouscommand-linetoolsthatcanhelpyoudiscoverwheretheAPI,DB,oranyotherserveryou'reusingislocated,andhowmuchlatencyispresentontheconnection.
Whileallofthesecommandscanberunfromyourworkstation,theyaremostusefulwhenrunfromaserverviaaSecureShell(SSH)orRemoteDesktopProtocol(RDP)connection.Thisway,youcancheckwhereyourdatabases,APIs,andstorageserversare,inrelationtoyourwebservers.Unfortunately,itiscommonforhostingproviderstogeographicallyseparateyourservers,andputthemindifferentdatacenters.
Forexample,ifusingAWS,thenyouwouldwanttoconfigureyourserverstobeinatleastthesameregion,andpreferablyinthesameAvailabilityZone(AZ),whichusuallymeansthesamedatacenter.Youcanreplicate(cluster)yourDBorfileserveracrossAZs(orevenacrossregions)sothatyourwebserversarealwaystalkingtoaserverontheirlocalnetwork.Thisalsoaddsredundancy,soinadditiontoincreasingperformance,itwillmakeyourapplicationmoreresilienttohardwarefaultsorpowersupplyfailures.
Ping
Pingisasimplenetworkingdiagnosticstool,availableonalmostalloperatingsystems.ItoperatesattheIPlevelandsendsanInternetControlMessageProtocol(ICMP)echomessagetothehostspecified.
Notallmachineswillrespondtopings,orrequestsmaybeblockedbyfirewalls.However,it'sgoodnetiquettetoallowserverstorespondfordebuggingpurposes,andmostwilloblige.Forexample,openacommandpromptorterminal,andtypethefollowing:
pingec2.eu-central-1.amazonaws.com
ThiswillpinganAmazonWebServices(AWS)datacenterinGermany.Intheresponse,youwillseethetimeinmilliseconds.FromtheUK,thisround-triptime(RTT)maybesomethinglike33ms,butyourresultswillvary.
Tip
OnWindows,bydefault,pingperformsfourattempts,thenexits.OnaUnix-likeOS(suchasMacOSX,BSD,orLinux),bydefault,itcontinuesindefinitely.PressCtrl+Ctostopandquit.
Trythiscommandnext,whichwilldothesame,butforanAWSdatacenterinAustralia:
pingec2.ap-southeast-2.amazonaws.com
FromtheUK,thelatencynowgoesup,byalmostanorderofmagnitude,toaround300ms.AWSdoesn'thaveanydatacentersintheUK,andneitherdoMicrosoftandGoogle(readintothatwhatyouwill).SotopingaUKhostingprovider,enterthefollowing:
pingbytemark.co.uk
Thelatencynowdecreasestoanaverageof23ms,asourconnectionhas(probably)notleftthecountry.Obviously,yourresultswillvarydependingonwhereyouare.Nextwe'llseehowtodiscoverwhatrouteourdataistaking,asit'snotalwaysonlydistancethat'simportant.Thenumberofhopscanlikewisebesignificant.
ThefollowingimageshowstheoutputofthethreepingoperationsthatwehavejustperformedtoGermany,theUK,andAustralia.Notethedifferenceinthetimings;however,yourresultswillbedifferent,sotrythisforyourself.
Tip
IPv4addressesstartingwith54(theonesintheform54.x.x.x)areacluethattheservermayberunningonanAWSElasticComputeCloud(EC2)virtualserver.PerformareverseDNSlookupwithnslookuporping(coveredlaterinthischapter)toconfirmifthisisthecase.AWSprovidesIPaddressrangesatthefollowinglink:docs.aws.amazon.com/general/latest/gr/aws-ip-
ranges.html
Tracert
Tracert(ortracerouteonaUnix-likeOS)isatoolwhich,asthenamesuggests,tracestheroutetoadestinationhost.Enterthefollowingcommand:
tracertwww.google.com
YoushouldbeabletoseetheconnectionleavingthenetworkofyourInternetServiceProvider(ISP),andenteringthedomain1e100.net,whichisGoogle'sdomain.1.0x10100isagoogol,whichistheirnamesake.Thefollowingimageshowstheoutputthatyoumightseeforthistrace:
Next,let'stracearoutetoAustraliabyrunningthefollowingcommandwiththesameAWShostnameasourearlierexample,asfollows:
tracertec2.ap-southeast-2.amazonaws.com
Thismaytakesometimetorun,especiallyifsomehostsdon'trespondtopingsandtraceroutehastotimeout.Ifyougetasterisks(***),thenthiscouldindicatethepresenceofafirewall.Yourresultsmaylooksomethinglikethefollowingimage:
Intheprecedingexample,wecanseetheconnectionleavingtheBritishTelecom(BT)network,andenteringtheNipponTelegraphandTelecom(NTT)GlobalIPNetwork.WecanevenseetheroutetakenfromLondontoSydney,viaAmsterdam,Ashburn(eastUS,inVirginia),andLosAngeles.ThehostnamessuggestthattheconnectionhasgoneviatheFaradaytelephoneexchangebuilding,nearSt.Paul'sCathedralinLondon(namedafterelectricalpioneerMichaelFaraday),andenteredAmazon'snetworkinLA.
Note
Thisisn'tthewholestoryasitonlyshowstheIPlevel.Atthephysicallevel,thefiberlikelycomesbacktotheUKfromtheNetherlands(possiblyviaPorthcurno,GoonhillySatelliteEarthStation,ormorelikely,BudewhereGCHQconvenientlyhaveabase).BetweenLAandAustralia,therewillalsoprobablybeastopoverinHawaii(wheretheNSAbasethatEdwardSnowdenworkedatislocated).
Therearemapsoftheconnectionsavailableatsubmarinecablemap.comandwww.us.ntt.net/about/network-map.cfm.It'sgoodideatohaveatleastabasicunderstandingofhowtheinternetisphysicallystructured,inordertoachievehighperformance.
IfwenowtracetheroutestotheAWSdatacentersinKoreaandJapan,wecanseethat,initially,theybothtakethesamerouteaseachother.TheygofromLondontoNewYorkandthentoSeattle,beforereachingOsakainJapan.TheKoreantracethencarriesonforanotherelevenhops,buttheJapanesetraceisdoneinsix,whichmakeslogicalsense.
ThefollowingimageshowsthetypicalresultsofatracetoKoreafirst,thentheresultsofa
secondtracetoJapan.
Youcanusethedifferenceintimebetweenhopstoworkouttheapproximategeographicdistance.However,thereareoccasionallyanomaliesifsomesystemsrespondquickerthanothers.
Tip
Ifyou'reonaflightwithfreeWi-Fi,thenatracerouteisaninterestingexercisetoperform.The
internetconnectionislikelygoingviasatellite,andyou'llbeabletotelltheorbitaltitudefromthelatency.Forexample,ageostationaryorbitwillhavealargelatencyofaround1,000ms,butaLowEarthOrbit(LEO)willbemuchsmaller.Youshouldalsobeabletoworkoutwherethegroundstationislocated.
Nslookup
NslookupisatoolfordirectlyqueryingaDNSserver.Digisanothersimilartool,butwewon'tcoverithere.BothpingandtraceroutehaveperformedDNSlookups,butyoucandothisdirectlywithnslookup,whichcanbeveryuseful.Youcancallnslookupwithcommand-lineparameters,butyoucanalsouseitinteractively.Todothis,simplytypethenameofthetoolintoaconsoleoracommandprompt,asfollows:
nslookup
Youwillnowgetaslightlydifferentcommandpromptfromwithintheprogram.Bydefault,theDNSnameserversofthecomputeryou'reonareused,anditbypassesanyentriesinyourlocalhostsfile.
Tip
AhostsfilecanbeveryusefulfortestingchangespriortoaddingthemtoDNS.Itcanalsobeusedasacrudeblockerforadvertsandtrackersbysettingtheiraddressesto0.0.0.0.TherearelocalDNSserversyoucanruntodothisforyourwholenetwork.Onesuchprojectispi-hole.net,whichisbasedondnsmasq,butwhichsimplifiessettingitupandupdatingthehostsonRaspberryPi.
EnterthehostnameofaservertoresolveitsIPaddress;forexample,typethefollowing:
polling.bbc.co.uk
TheresultsshowthatthishostnameisaCNAME(analiasfortherealCanonicalName)ofpolling.bbc.co.uk.edgekey.net,whichresolvestoe3891.g.akamaiedge.net,andthiscurrentlyhasanIPaddressof23.67.87.132.WecanperformareverseDNSlookupontheIPaddressbyenteringit:
23.67.87.132
Wethengetthehostnameofthatmachine,convenientlycontainingtheIPaddress,whichisa23-67-87-132.deploy.static.akamaitechnologies.com.ThedomainnameisownedbyAkamai,whichisaContentDeliveryNetwork(CDN)usedtodistributeload.
IfyouareusingaDNSserveronyourlocalnetwork,possiblywithyourrouterrunningdnsmasq,thenitmaycacheresults,andgiveyoustaledata.Youcanseemoreup-to-dateinformationbychangingtheservertoacoreonethatpropagateschangesquicker.Forexample,touseoneofGoogle'spublicDNSservers,enterthefollowing(butbeawarethatGooglewilllogalltheinternetsitesyouvisitifyouusethisnormally):
server8.8.8.8
Thenrunthesamequeryagain.NoticehowthehostnamenowresolvestoadifferentIPaddress.ThisisacommonbehaviorforCDNs,andtherecordwillchangeovertime,evenonthesameDNSserver.Itisoftenusedasatechniquetobalancenetworkload.ChangingDNSserverscanalsosometimesbeusedtogetaroundNaïvecontentfiltersorlocationrestrictions.
Toexitthenslookupinteractivemode,typeexitandpressreturn.Thefollowingimageshowstheoutputforthepreviouscommands:
Note
IPv4istheversionofIPthatyouwillprobablybemostfamiliarwith.Ituses32-bitaddressesthatareusuallyrepresentedasfourdotteddecimaloctets,suchas192.168.0.1.However,wehaverunoutofIPv4addresses,andtheworldis(slowly)movingtothenewversionofIP,calledIPv6.Theaddresslengthhasincreasedfourfold,to128-bit,andisusuallyrepresentedinhexadecimalsuchas2001:0db8:0000:0000:0000:ee00:0032:154d.Leadingzeroscanbeomitted,like2001:db8::ee00:32:154d,tomakethemeasiertowrite.Localhostloopback(127.0.0.1)isnowsimply::1inIPv6.
OnWindows,youcanuseping-ax.x.x.xtodoareverseDNSlookup,andresolveIPaddressestohostnames.OnLinux(andonotherUnix-likesystemssuchasOSX),thisfeatureis
notavailable,andthe-aflagservesadifferentpurpose.Youwillhavetousenslookup,ordigforreverseDNSontheseOSs.
Buildyourown
YoucanbuildyourowntoolsusingC#,andthefunctionsyouneedareprovidedby.NET.Thesearebuiltintothefull.NETFramework,butfor.NETCore,youwillneedtoaddtheNuGetpackageSystem.Net.Pingforping,althoughtheDNSnameresolutionisbuilt-in.Theunderlyingimplementationsareplatform-specific,buttheframeworkwilltakecareofcallingthenativecodeontheOSyou'reusing.
Youwon'tnormallyneedtoprogrammaticallyresolveahostname,asmostnetworkingcommandswilldothisautomatically.However,itcanoccasionallybeuseful,especiallyifyouwanttoperformareverseDNSlookup,andfindthehostnameforanIPaddress.
Tip
The.NETDnsclassdiffersfromnslookup,asitincludesentriesfromthelocalhostsfileratherthanjustqueryingaDNSserver.Itis,therefore,morerepresentativeoftheIPaddressesthatotherprocessesareresolving.
ToprogrammaticallyperformaDNSlookup,followthesesteps:
1. AddtheSystem.Netnamespace.
usingSystem.Net;
2. ToresolveahostnametoanIPaddress,usethefollowingstaticmethod.ThiswillreturnanarrayofIPaddresses,althoughtherewillusuallyonlybeone.
varresults=awaitDns.GetHostAddressesAsync(host);
3. ToresolveanIPaddresstoahostname,usethefollowingmethodinstead:
varrevDns=awaitDns.GetHostEntryAsync(result);
4. Ifsuccessful,thenthehostnamewillbeavailableasrevDns.HostName.
Toprogrammaticallypingahost,followthesesteps:
1. AddtheSystem.Net.NetworkInformationnamespace.
usingSystem.Net.NetworkInformation;
2. YoucantheninstantiateanewPingobject.
varping=newPing();
3. Withthisobject,youcannowpinganIPaddressorhostname(thatwillperformaDNSlookupinternally)byusingthefollowingmethod:
varresult=awaitping.SendPingAsync(host);
4. Youcangetthestatusofthepingwithresult.Status,andifsuccessful,thenyoucangettheRTTinmillisecondswithresult.RoundtripTime.
Note
Thesourcecodeforourconsoleapplication,illustratinghowtousethe.NETCoreDnsandPingclasses,isavailablefordownloadalongwiththisbook.
AreverseDNSlookupcanusuallyrevealthehostingcompanybeingusedbyawebsite.Usually,thereisonlyoneIPaddressperhostname,asshowninthefollowingimageofour.NETCoreconsoleappoutput:
Intheprecedingscreenshot,wecanseethatemoncms.orgisusingredstation.comasahost.Thelowlatencysuggeststhattheserverislocatedinthesamecountryasourcomputer.
DNSisoftenusedforloadbalancing.Inthiscase,youwillseemanyIPaddressesreturnedforasingledomainname,asshowninthefollowingscreenshot:
Wecanseeintheprecedingscreenshotthattheprivacy-focusedsearchengineDuckDuckGo(whichdoesn'ttrackitsuserslikeGoogledoes)isusingAWS.DNSisbeingusedtobalancetheloadacrossvariousinstances—inthiscase,they'reallintheDublindatacenter,becausethat'stheclosestone.NoticehowthepingtimesarenowslightlyhigherthantheUK-basedhostinthepreviousexample.
It'slikelythatthey'reusingtheAWSDNSserviceRoute53(sonamedbecauseDNSusesport53).Thiscanbalanceloadacrossregions,whereasanELB(whichDuckDuckGodoesn'tappeartobeusing)canonlybalanceinsidearegion(butbothinsideandacrossAZs).AzureoffersasimilarservicecalledTrafficManagerforDNSloadbalancing.
SolutionsNowthatyouunderstandabitmoreaboutthecausesoflatency-basedproblems,andhowtoanalyzethem,wecandemonstratesomepotentialsolutions.Themeasurementsthatyouhavetakenusingthepreviouslyillustratedtoolswillhelpyouquantifythescaleoftheproblems,andchoosetheappropriatefixestobeapplied.
BatchingAPIrequestsRenderingatypicalwebpagemayrequirecallstomanydifferentAPIs(orDBtables)togatherthedatarequiredforit.Duetothestyleofobject-orientedprogrammingencouragedbyC#(andmanyotherlanguages),theseAPIcallsareoftenperformedinseries.However,iftheresultofonecalldoesnotaffectanother,thenthisissuboptimal,andthecallscouldbeperformedinparallel.We'llcoverDBtableslaterinthischapter,astherearebetterapproachesforthem.
Concurrentcallscanbemorepertinentifyouimplementamicroservicesarchitecture(asopposedtothetraditionalmonolith,orbigballofmud),andhavelotsofdifferentdistributedendpoints.MessagequeuesaresometimesabetterchoicethanHTTPAPIsinmanycases,perhapsusingapublishandsubscribepattern.However,maybeyou'renotresponsiblefortheAPI,andareinsteadintegratingwithathirdparty.Indeed,iftheAPIisyours,thenyoucouldalterittoprovideallthedatathatyouneedinoneshotanyway.
ConsidertheexampleofcallingtwoisolatedAPIsthathavenodependenciesoneachother.Thesequencediagramforthismaylooksomethinglikethefollowing:
ThislinearprocessofcallingA,andthencallingBwhenAisdone,issimple,asitrequiresnocomplexorchestrationtowrangletheresultsoftheAPIcalls,butitisslowerthannecessary.BycallingbothAPIssynchronouslyandinsequence,wewastetimewaitingforthemtoreturn.Abetterwayofdoingthis,ifwedon'trequiretheresultofthefirstAPIfortherequesttothesecond,maybetocallthemtogetherasynchronously.Thesequencediagramforthisnewflowmaylooksomethinglikethefollowing:
Therearetwochangesinthisnewsequence,oneobviousandtheothersubtle.WecallbothAPIsasynchronouslyandinparallelsothattheyaresimultaneouslyinflight.Thisfirstchangewillhavethegreatestimpact,butthereisasmallertweakthatcanalsohelp,whichiscallingtheslowestAPIfirst.
Intheoriginalsequencediagram,wecallAPIAandthenAPIB,butBisslower.CallingAandBatthesametimewillhaveabigimpact,butcallingBandthenAisslightlybetter.Bdominatesthetimeline,andwewillbekillinga(relatively)largeamountoftimewaitingforit.
WecanusethisdowntimetocallA,astherewillbesomesmallfixedoverheadinanyAPImethodcall.BothofthesechangescombinedmeanthatwearenowonlywaitingforB,andeffectivelygetthecalltoAforfree,intermsoftime.
Wecanillustratethisprinciplewithasimpleconsoleapplication.TherearetwomethodsthatsimulatetheAPIs,andbotharesimilar.APIAhasthefollowingcode:
privatestaticasyncTaskCallApiA()
{
Thread.Sleep(10);
awaitTask.Delay(100);
}
Thread.Sleepsimulatesthefixedoverhead,andTask.DelaysimulateswaitingfortheAPIcalltoreturn.APIBtakestwiceaslongtoreturnasAPIA,butthefixedoverheadisthesame,andithasthefollowingcode:
privatestaticasyncTaskCallApiB()
{
Thread.Sleep(10);
awaitTask.Delay(200);
}
Now,ifwesynchronouslycallthemethodsinsequence,wediscoverthatallofthedelaysaddup,asexpected.
CallApiA().Wait();
CallApiB().Wait();
Theseoperationstakeatotalofaround332msonaverage,asthereisabout10msofadditionalintrinsicoverheadinthemethodinvocation.Ifwecallbothmethodssimultaneously,thetimereducessignificantly.
Task.WaitAll(CallApiA(),CallApiB());
Theoperationsnowtakeanaveragetotalof233ms.Thisisgood,butwecandobetterifweswaptheorderofthemethods.
Task.WaitAll(CallApiB(),CallApiA());
Thisnowtakes,onanaverage,atotalof218ms,becausewehaveswallowedthefixedoverheadsofAPIAintothetimewearewaitingforAPIB.
Note
Thefullconsoleapplicationwhichbenchmarksthesethreevariantsisavailablefordownloadwiththisbook.ItusestheStopwatchclasstotimetheoperations,andaveragestheresultsovermanyruns.
Theresultsofthesethreedifferentapproachesareshowninthefollowingimage:
Asisalwaysthecase,measureyourresultstomakesuretherereallyisanimprovement.YoumayfindthatifyouaremakingmanycallstooneAPI,orreusingthesameAPIclient,thenyourrequestsareprocessedsequentially,regardless.
ThisparallelizingoftasksnotonlyworksforI/O,butcanalsobeusedforcomputation,aswewilldiscoverinthenextchapter.Fornow,wewillmoveon,andtakeadeeperlookatdatabasequeryoptimization.
EfficientDBoperationsAlthoughthisisn'tabookaimedatDatabaseAdministrators(DBAs),it'sadvantageousforyoutoappreciatetheunderlyingtechnologythatyou'reusing.Asisthecasewithnetworking,ifyouunderstandthestrengthsandweaknesses,thenyoucanachievehighperformancemoreeasily.
Thisisadditionallyrelevantfortherecenttrendofdevelopersdoingmoreworkoutsideoftheirspecialization,particularlyinsmallorganizationsorstartups.Youmayhaveheardthebuzzwordsfull-stackdeveloperorDevOps.Theserefertorolesthatblurthetraditionalboundaries,andmergedevelopment(bothfrontendandbackend),qualityassurance,networking,infrastructure,operations,anddatabaseadministrationintoonejob.Beingadevelopertodayisnolongeracaseofjustprogrammingorshippingcode.Ithelpstoknowsomethingabouttheotherareastoo.
Previously,inChapter3,FixingCommonPerformanceProblems,wecoveredusingthemicroO/RMDapper,andhowtofixSelectN+1problems.Now,we'llbuildonthatknowledge,andhighlightafewmorewaysthatyoucanconsolidatequeriesandimprovetheperformanceofyourDBoperations.
AsdetailedinChapter2,MeasuringPerformanceBottlenecks,thefirststepistoprofileyourapplicationanddiscoverwheretheissueslie.Onlythenshouldyoumoveontoapplyingsolutionstotheproblemareas.
Databasetuning
We'regoingtofocusmoreonimprovingpoorlyperformingqueries,sowewon'tgointoDBtuningtoomuch.Thisisacomplextopic,andthereisalotyoucanlearnaboutindexesandhowdataisstored.
However,ifyouhaven'truntheDatabaseEngineTuningAdvisor(DETA),thenthisisaneasysteptoidentifyifyouhaveanymissingindexes.Yet,youshouldbecarefulwhenapplyingtherecommendedchanges,astherearealwaysdownsidesandtradeoffstoconsider.Forexample,indexesmakeretrievingdataquicker,butalsomakeitslowertoaddandupdaterecords.Theyalsotakeupadditionalspace,soitisbestnottooverdoit.Itwilldependonyourparticularbusinessusecase:ifyouwishtooptimizeupfront,ortakethehitlateronretrieval.
ThefirststepistocaptureatracewithSQLServerProfiler.SeeChapter2,MeasuringPerformanceBottlenecksforhowtodothis,andsavetheresultingfile.Thisisoneofthereasonsthatthetuningprofileisagoodchoice.YoushouldmakesurethatthetraceisrepresentativeofagenuineDBusetogetgoodresults.YoucanlaunchtheDETAfromthesamemenuastheprofilerinSSMS.
Youcanthenloadinyourtraceasaworkload,andafterprocessing,itwillgiveyousomerecommendations.Wewon'tcoverthedetailsofhowtodothishereforspacereasons,anditisprettyself-explanatory.Therearemanygoodguidesavailableonline,ifrequired.
Reporting
Acommonusecase,whichcanoftenbringadatabasetoitsknees,isreporting.Reportsusuallyrunonlargeamountsofdata,andcantakeconsiderabletimeifpoorlywritten.
IfyoualreadyhaveamethodforretrievingasingleitemfromaDB,thenitcanbetemptingtoreusethisforreportingpurposesandforcalculatingmetricsinsideoftheapplication.However,thisisbestavoided;reportsshouldgenerallyhavetheirowndedicatedqueries.
Evenbetteristohaveanotherdatabasededicatedtoreporting,whichispopulatedfromthemainDBorfrombackups.Thisway,intensivereportswon'taffecttheperformanceofthemainapplicationattheexpenseofnotincludingreal-timedata.Thisissometimesknownasadatawarehouseordatamart,andthedataisoccasionallydenormalizedforsimplicityorperformancereasons.PopulatinganotherDBcanalsobeaconvenientwaytotestyourbackups,asdatabasebackupsshouldalwaysbetestedtoensurethattheycanberestoredcorrectlyandcontainalloftherequireddata.
Note
Intheensuingexamples,wewillfocusonMicrosoftSQLServer(MSSQL)andtheTransact-SQL(T-SQL)dialectofSQL.Otherdatabases,suchasPostgreSQL,areavailableaswell.PostgreSQLhasitsowndialectcalledProceduralLanguage/PostgreSQL(PL/pgSQL),whichissimilartoOraclePL/SQL.ThesedialectsallsupportbasicSQLcommands,butusedifferentsyntaxforsomeoperations,andcontaindifferentoradditionalfeatures.
ThelatestversionofMSSQLServerisSQLServer2016,andit'sthefirsteditiontosupportrunningonLinuxinadditiontoWindows.ItisbasedontheSQLAzureservicecode,sothereshouldnowbefewerdifferencesbetweenaself-hosted,on-premiseDBandMicrosoft'scloudoffering.
Aggregates
AggregatefunctionsareanincrediblyusefulfeatureofaRDBMS.Youcancomputevaluesthatsummarizemanyrecordsinthedatabase,andonlyreturntheresultkeepingthesourcedatarowsintheDB.
YouwillbefamiliarwiththeCOUNTaggregatefunctionfromearlierinthebook,ifnotbefore.Thisgivesyouthetotalnumberofrecordsreturnedbyyourquery,butwithoutreturningthem.YoumayhavereadadvicethatCOUNT(1)performsbetterthanCOUNT(*),butthisisnolongerthecase,asSQLServernowoptimizesthelattertoperformthesameastheformer.
Tip
Bydefault,SQLServerwillreturnamessagedetailingthecountoftherecordsreturned,alongwiththeresultofeveryquery.YoucanturnthisoffbyprefixingyourquerywiththeSETNOCOUNTONcommand,whichwillsaveafewbytesintheTabularDataStream(TDS)connection,andincreaseperformanceslightly.Thisissignificantonlyifacursorisbeingused,whichisbadpracticeanywayforlockingreasons.It'sgoodpracticetore-enablerowcountafterthequery,eventhoughitwillberesetoutsideofthelocalscopeanyway.
InChapter3,FixingCommonPerformanceProblems,wesolvedourSelectN+1problembyjoiningtablesintheDB,andusingCOUNTinsteadofperformingthesecalculationsinourapplicationcode.Therearemanyotheraggregatefunctionsavailable,thatcanbeusefulinimprovingperformance,especiallyforreportingpurposes.
Goingbacktoourearlierexample,supposewenowwanttofindoutthetotalnumberofblogposts.Wealsowanttofindthetotalnumberofcomments,theaveragecommentcount,thelowestnumberofcommentsforasinglepost,andthehighestnumberofcommentsforasinglepost.
Thefirstpartiseasy—justapplyCOUNTtothepostsinsteadofthecomments—€”butthesecondpartisharder.Aswealreadyhaveourlistofpostswithacommentcountforeach,itmaybetemptingtoreusethat,andsimplyworkeverythingoutinourC#code.
Thiswouldbeabadidea,andthequerywouldperformpoorly,especiallyifthenumberofpostsishigh.Abettersolutionwouldbetouseaquerysuchasthefollowing:
;WITHPostCommentCountAS(
SELECT
bp.BlogPostId,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId
)SELECT
COUNT(BlogPostId)'TotalPosts',
SUM(CommentCount)'TotalComments',
AVG(CommentCount)'AverageComments',
MIN(CommentCount)'MinimumComments',
MAX(CommentCount)'MaximumComments'
FROMPostCommentCount
ThisqueryusesaCommonTableExpression(CTE),butyoucouldalsouseanestedSELECTtoembedthefirstqueryintotheFROMclauseofthesecond.Itillustratesaselectionoftheaggregatefunctionsavailable,andtheresultsonthetestdatabasefrombeforelooklikethefollowing:
Note
Thesemicolonatthestartissimplyagoodpracticetoavoiderrorsandremoveambiguity.Itensuresthatanypreviouscommandhasbeenterminated,asWITHcanbeusedinothercontexts.Itisn'trequiredfortheprecedingexample,butmightbeifitwerepartofalargerquery.CTEscanbeveryusefultools,especiallyifyourequirerecursion.However,theyareevaluatedeverytime,soyoumayfindthattemporarytablesperformmuchbetterforyou,especiallyifqueryingonerepeatedlyinanestedSELECT.
Nowsupposethatwewishtoperformthesamequery,butonlyincludepoststhathaveatleastonecomment.Inthiscase,wecoulduseaquerylikethefollowing:
;WITHPostCommentCountAS(
SELECT
bp.BlogPostId,
COUNT(bpc.BlogPostCommentId)'CommentCount'
FROMBlogPostbp
LEFTJOINBlogPostCommentbpc
ONbpc.BlogPostId=bp.BlogPostId
GROUPBYbp.BlogPostId
HAVINGCOUNT(bpc.BlogPostCommentId)>0
)SELECT
COUNT(BlogPostId)'TotalPosts',
SUM(CommentCount)'TotalComments',
AVG(CommentCount)'AverageComments',
MIN(CommentCount)'MinimumComments',
MAX(CommentCount)'MaximumComments'
FROMPostCommentCount
WehaveaddedaHAVINGclausetoensurethatweonlycountpostswithmorethanzerocomments.ThisissimilartoaWHEREclause,butforusewithaGROUPBY.Thequeryresultsnowlooksomethinglikethefollowing:
Sampling
Sometimes,youdon'tneedtouseallofthedata,andcansampleit.Thistechniqueisparticularlyapplicabletoanytime-seriesinformationthatyoumaywishtograph.InSQLServer,thetraditionalwaytoperformrandomsamplingwasusingtheNEWID()method,butthiscanbeslow.Forexample,considerthefollowingquery:
SELECTTOP1PERCENT*
FROM[dbo].[TrainStatus]
ORDERBYNEWID()
Thisqueryreturnsexactly1%oftherowswitharandomdistribution.Whenrunagainstatablewith1,205,855entries,itreturned12,059resultsinaboutfourseconds,whichisslow.AbetterwaymaybetouseTABLESAMPLE,whichisavailableinanyreasonablyrecentversionofSQLServer(2005onwards),asfollows:
SELECT*
FROM[dbo].[TrainStatus]
TABLESAMPLE(1PERCENT)
Thisprecedingqueryismuchquicker,andwhenrunagainstthesamedataasthepreviousexample,itcompletesalmostinstantly.Thedownsideisthatit'scruderthantheearliermethod,anditwon'treturnexactly1%oftheresults.Itwillreturnroughly1%,butthevaluewillchangeeverytimeitisrun.Forexample,runningagainstthesametestdatabase,itreturned11,504,13,441and11,427rowswhenexecutingthequerythreetimesinarow.
Insertingdata
Queryingdatabasesmaybethemostcommonusecase,butyouwillusuallyneedtoputsomedatainthereinthefirstplace.OneofthemostcommonlyusedfeatureswheninsertingrecordsintoarelationalDBistheidentitycolumn.Thisisanauto-incrementingIDthatisgeneratedbythedatabase,anddoesn'tneedtobesuppliedwhenaddingdata.
Forexample,inourBlogPosttablefromearlier,theBlogPostIdcolumniscreatedasINTIDENTITY(1,1).Thismeansthatit'sanintegervaluestartingatoneandincreasingbyoneforeverynewrow.YouINSERTintothistable,withoutspecifyingBlogPostId,likeso:
INSERTINTOBlogPost(Title,Content)
VALUES('MyAwesomePost','Writesomethingwittyhere...')
Identitiescanbeveryuseful,butyouwillusuallywanttoknowtheIDofyournewlycreatedrecord.Itistypicaltowanttostorearow,thenimmediatelyretrieveitsothattheIDcanbeused
forfutureeditingoperations.YoucandothisinoneshotwiththeOUTPUTclause,likeso;
INSERTINTOBlogPost(Title,Content)
OUTPUTINSERTED.BlogPostId
VALUES('MyAwesomePost','Writesomethingwittyhere...')
Inadditiontoinsertingtherow,theIDwillbereturned.
Note
YoumayseeSCOPE_IDENTITY()(oreven@@IDENTITY)advocatedaswaysofretrievingtheidentity,buttheseareoutdated.Therecommendedwayofdoingthis,onmodernversionsofSQLServer,istouseOUTPUT.
OUTPUTworksontheINSERT,UPDATE,DELETE,andMERGEcommands.Itevenworkswhenoperatingonmultiplerowsatatime,asinthisexampleofbulkinsertingtwoblogposts:
INSERTINTOBlogPost(Title,Content)
OUTPUTINSERTED.BlogPostId
VALUES('MyAwesomePost','Writesomethingwittyhere...'),
('MySecondAwesomePost','Tryharderthistime...')
Theprecedingquerywillreturnaresultsetoftwoidentities,forexample,3003and3004.InordertoexecutetheseinsertswithDapper,youcanusethefollowingmethodforasinglerecord.First,letuscreateablogpostobject,whichwe'llhardcodehere,butwhichwouldnormallycomefromuserinput:
varpost=newBlogPost
{
Title="MyAwesomePost",
Content="Writesomethingwittyhere..."
};
Toinsertthisonepost,andsettheID,youcanusethefollowingcode.Thiswillexecutetheinsertstatement,andreturnasingleintegervalue.
post.BlogPostId=awaitconnection.ExecuteScalarAsync<int>(@"
INSERTINTOBlogPost(Title,Content)
OUTPUTINSERTED.BlogPostId
VALUES(@Title,@Content)",
post);
YoucanthenassignthereturnedIDtothepost,andreturnthatobjecttotheuserforediting.Thereisnoneedtoselecttherecordagain,assumingtheinsertsucceedsandnoexceptionsarethrown.
YoucaninsertmultiplerecordsatoncewiththesameSQLbyusingtheexecutemethod.However,theSQLwillbeexecutedmultipletimes,whichmaybeinefficient,andyouonlygetbackthenumberofinsertedrows,nottheirIDs.ThefollowingcodesuppliesanarrayofpoststothesameSQLusedinthepreviousexample:
varnumberOfRows=awaitconnection.ExecuteAsync(@"
INSERTINTOBlogPost(Title,Content)
OUTPUTINSERTED.BlogPostId
VALUES(@Title,@Content)",
new[]{post,post,post});
IfyouwantmultipleIDsreturned,thenyouwillneedtousethequerymethodtoreturnacollectionofvalues,aswehavedonepreviously.However,itisdifficulttomakethisworkforavariablenumberofrecords,withoutdynamicallybuildingSQL.Thefollowingcodeperformsabulkinsert,usingmultipleseparateparametersforthequery:
varids=awaitconnection.QueryAsync<int>(@"
INSERTINTOBlogPost(Title,Content)
OUTPUTINSERTED.BlogPostId
VALUES(@Title1,@Content1),
(@Title2,@Content2)",new
{
Title1=post.Title,
Content1=post.Content,
Title2=post.Title,
Content2=post.Content
});
Thiswillperformalltheworkinasinglecommand,andreturnanenumerablecollectionoftheidentities.However,thiscodeisnotveryscalable(orevenelegant).
Tip
TherearemanyhelpermethodsintheDapper.Contribpackagewhichcanassistyouwithinsertingrecordsandotheroperations.However,theysufferfromthesamelimitationsastheexampleshere,andyoucanonlyreturnasingleidentityorthenumberofrowsinserted.
GUIDs
Integeridentitiescanbeusefultoadatabaseinternally,butperhapsyoushouldn'tbeusinganidentifyingkeyexternally,especiallyifyouhavemultiplewebserversorexposetheIDstousers.AnalternativeistouseaGloballyUniqueIdentifier(GUID),referredtoasUNIQUEIDENTIFIERinSQLServer.Wehavealreadytouchedonthese,astheyaregeneratedbytheNEWID()functionusedinthesuboptimalsamplingexample.
GUIDsareusedubiquitously,andare16byteslong—fourtimesbiggerthananinteger.ThesizeofGUIDsmeansthatyouareunlikelytogetauniqueconstraintconflictwheninsertingarandomGUIDintoanalreadypopulatedtable.
Note
PeoplesometimesworryaboutGUIDcollisions,butthenumbersinvolvedaresostaggeringlyhugethatcollisionsareincrediblyunlikely.TheGUIDsgeneratedby.NET(usingaCOMfunctiononWindows)are,specifically,UniversallyUniqueIdentifiers(UUIDs)version4.Thesehave122bitsofrandomness,soyouwouldneedtogeneratenearlythreebillionGUIDsbeforehavingevenhalfachanceofacollision.
Atonenewrecordpersecond,thatwouldtakeover90billionyears.EvenattwomillionGUIDspersecond(whatanaveragecomputertodaycouldproduce),itwouldstilltakeover45thousandyears(moretimethanhumancivilizationhasbeenaround).Ifyouthinkthatthiswillbeanissueforyoursoftware,thenyoushouldprobablybefuture-proofingitbyusingfive-digityears,suchas02016,toavoidtheY10K(orYAKinhexadecimal)problem.
ThisuniquenesspropertyallowsyoutogenerateaGUIDinyourapplicationcodeandstoreitinadistributeddatabase,withoutworryingaboutmergingdatalater.ItalsoallowsyoutoexposeIDstousers,withoutcaringifsomeonewillenumeratethemortryandguessavalue.IntegerIDsoftenexposehowmanyrecordsthereareinatable,whichcouldbesensitiveinformationdependingonyourusecase.
OnethingyouhavetowatchoutforwithrandomGUIDsisusingthemaskeys,asopposedtoIDs.Thedifferencebetweenthesetwotermsissubtle,andtheyareoftenoneandthesame.Thekey(primaryorclustered)iswhattheDBusestoaddressarecord,whereastheIDiswhatyouwouldusetoretrieveone.Thesecanbethesamevaluebuttheydon'thavetobe.UsingarandomGUIDasakeycancauseperformanceissueswithindexing.Therandomnessmaycausefragmentation,whichwillslowdownqueries.
YoucanusesequentialGUIDs,forexampleNEWSEQUENTIALID()canbetheDEFAULTvalueforacolumn,butthenyoulosemostofthebeneficialqualitiesofGUIDsthatmainlycomefromtherandomness.Younoweffectivelyjusthaveareallybiginteger,andifyou'reonlyconcernedwiththemaximumnumberofrowsinatable,andrequiremorethantwobillion,thenabigint(twiceanint,buthalfaGUID)shouldsuffice.
Agoodcompromiseistohaveanintidentityastheprimarykey,buttouseaGUIDastheID(andenforcethiswithauniqueconstraintonthecolumn).It'sbestifyougeneratetheGUIDinapplicationcodewithGuid.NewGuid(),asusingadefaultcolumnvalueintheDBmeansyouhavetoretrievetheIDafteraninsert,asshownpreviously.
Atableusingthisstrategymaypartiallylooksomethinglikethefollowingimage.ThisisascreencaptureofpartofatablefromtheMembershipRebootusermanagementandauthenticationlibrary:
AdvancedDBtopics
Therearemanyotherdatabaseperformanceenhancingtechniquesthatwecouldcoverhere,butdon'thavespacefor.We'llbrieflymentionsomeadditionaltopicsincaseyouwanttolookintothemfurther.
Acommonrequirementwhensavingdataistoinsertarecordifitdoesn'tyetexist,ortoupdateanexistingrecordifthereisalreadyarowcontainingthatID.Thisissometimesreferredtoasanupsert,whichisaportmanteauwordcombiningupdateandinsert.
YoucanusetheMERGEcommand,todothisinoneoperationandnotworryaboutchoosingbetweenUPDATEorINSERT(wrappedinatransactioninsideastoredprocedure).However,MERGEdoesnotperformaswellasUPDATEorINSERT,soalwaystesttheeffectsforyourusecase,anduseitsparingly.
Storedprocedures,transactions,andlockingareallbigsubjectsontheirown.Theyareimportanttounderstand,andnotonlyfromaperformanceperspective.Wecan'tfitalloftheseinhere,butwewilltouchuponmaintainingstoredprocedureslaterinthebook.
Someothertechniquesyoucouldlookintoarecross-databasejoins,whichcansaveyoufromqueryingmultipleDBs.Thereisalsothepracticeofdenormalizingyourdata,whichinvolvesflatteningyourrelationalrecordsaheadoftimetoprovideasinglerowratherthanneedingtojoinacrossmanytablesforaquery.Webrieflymentionedthisinrelationtodatawarehousesearlier.
Note
YoucanfindlotsofusefulSQLdocumentationandinformationonMSDN(msdn.microsoft.com)andTechNet(technet.microsoft.com).Additionally,therearemanygoodbooksonadvancedSQLtechniques.
Finally,anoteonhousekeeping.It'simportanttohaveaplanformanagingthesizeofadatabase.Youcan'tsimplykeepinsertingdataintoatable,andhopeitwillcontinuetoperformwellforever.Atsomepoint,itwillgetsolargethatevendeletingrecordsfromitwillcauseyourDBtogrindtoacrawl.Youshouldknowaheadoftimehowyouwillremoveorarchiverows,anditisbettertodothisregularlyinsmallbatches.
SimulationandtestingTowrapupthischapter,let'sreiteratetheimportanceofbeingabletotestyourapplicationonrealisticinfrastructure.Yourtestenvironmentsshouldbeaslive-likeaspossible.Ifyoudon'ttestonequivalentDBsandnetworks,thenyoumaygetanastysurprisecomedeploymenttime.
Whenusingacloudhostingprovider(andifyouautomateyourserverbuilds),thenthisiseasy:youcansimplySpin-upastagingsystemthatmatchesproduction.Youdon'thavetoprovisionittotheexactsamescaleaslongasallthepartsarethereandinthesameplace.Toreducecostsfurther,youonlyneedtokeepitaroundforaslongasyourtest.
Alternatively,youcouldcreateanewliveenvironment,deployandtestit,thenswitchover,anddestroyorreusetheoldliveenvironment.Thisswappingtechniqueisknownasblue-greendeployment.Anotheroptionistodeploynewcodebehindafeatureswitch,whichallowsyoutotogglethefeatureatruntime,andonlyforsomeusers.Notonlydoesthisallowyoutofunctionallyverifyfeatureswithtestusers,youcanalsograduallyrolloutanewfeature,andmonitortheperformanceimpactasyoudoso.WewillcoverbothofthesetechniquesinChapter9,MonitoringPerformanceRegressions.
SummaryWe'vecoveredalotinthischapter,anditshouldhopefullybeclearthatbeingahighperformancedeveloperrequiresmorethansimplybeingacapableprogrammer.Therearemanyexternalitiestoconsideraroundyourcode.
YounowunderstandthebasicsofI/O,andthephysicalcausesoftheintrinsiclimitationspresent.Youcananalyzeanddiagnosehowanetworklogicallyfitstogether.Wehavecoveredhowtomakebetteruseofthenetworktoreduceoveralllatency,whichisimportantasmoreI/Ooperationsnowhappenoveranetwork.Youhavealsoseenhowtomakebetteruseofadatabase,andhowtodomorewithfeweroperations.
Inthenextchapter,wewilldigintocodeexecutionindetail,andshowyouhowtospeedupyourC#.We'llseehow.NETCoreandASP.NETCoreperformsomuchbetterthanthepreviousversions,andhowyoucantakeadvantageoftheseimprovements.
Chapter6.UnderstandingCodeExecutionandAsynchronousOperationsThischaptercoverssolvingperformanceproblemsintheexecutionofyourcode,whichisnotnormallythefirstlocationthatspeedissuesoccur,butcanbeagoodadditionaloptimization.We'lldiscusstheareaswhereperformanceisneeded,andwhereitisokay(orevenrequired)tobeslow.Themeritsofvariousdatastructureswillbecomparedfromthestandardbuilt-ingenericcollectionstothemoreexotic.Wewilldemonstratehowtocomputeoperationsinparallel,andhowtotakeadvantageofextrainstructionsetsthatyourCPUmayprovide.We'lldiveintotheinternalsofASP.NETCoreand.NETCoretohighlighttheimprovementsthatyoushouldbeawareof.
Thetopicscoveredinthischapterincludethefollowing:
.NETCoreandthenativetoolchainCommonLanguageRuntime(CLR)servicessuchasGC,JIT,andNGenASP.NETCoreandtheKestrelwebserverGenericcollectionsandBloomfiltersSerializationanddatarepresentationformatsRelativeperformanceofhashingfunctionsParallelization(SIMD,TPL,andPLINQ)Poorlyperformingpracticestoavoid
Youwilllearnhowtocomputeresultsinparallelandcombinetheoutputsattheend.Thisincludeshowtoavoidincorrectwaysofdoingthis,whichcanmakethingsworse.You'llalsolearnhowtoreduceserverutilization,andtochoosethemostappropriatedatastructuresinordertoprocessinformationefficientlyforyourspecificsituation.
GettingstartedwiththecoreprojectsTherearemanybenefitsofusing.NETCoreandASP.NETCoreovertheoldfullversionsoftheframeworks.Themainenhancementsaretheopensourcedevelopmentandcrossplatformsupport,buttherearealsosignificantperformanceimprovements.Opendevelopmentisimportantandthesourcecodeisnotonlyavailable,thedevelopmentworkhappensintheopenonGitHub.Thecommunityisencouragedtomakecontributionsandthesemaybemergedinupstreamiftheypassacodereview;theflowisn'tjustoneway.ThishasledtoincreasedperformanceandadditionalplatformsupportcomingfromoutsideofMicrosoft.Ifyoufindabuginaframework,youcannowfixitratherthanworkaroundtheproblemandhopeforapatch.
ThemultipleprojectsthatmakeuptheframeworksaresplitacrosstwoorganizationsonGitHub.Oneofthedrivingprincipleshasbeentosplittheframeworksupintomodules,soyoucanjusttakewhatyouneedratherthanthewholemonolithicinstallation.Thelowerlevelframework,.NETCore,canbefound,alongwithotherprojects,undergithub.com/dotnet.Thehigherlevelwebapplicationframework,ASP.NETCore,canbefoundundergithub.com/aspnet.Thereasonforthissplitisthat.NETCoreismanagedbythe.NETFoundationwhichisanindependentorganization,althoughmostofthemembersareMicrosoftstaff.ASP.NETCoreismanageddirectlybyMicrosoft.
Let'shaveaquicklookatsomeofthevarious.NETCorerepositoriesandhowtheyfittogether.
.NETCoreThereareacoupleofprojectsthatformthemainpartsof.NETCoreandtheseareCoreCLRandCoreFX.CoreCLRcontainsthe.NETCoreCLRandthebasecorelibrary,mscorlib.TheCLRisthevirtualmachinethatrunsthe.NETcode.CoreCLRcontainsajust-in-time(JIT)compiler,GarbageCollector(GC),andalsobasetypesandclassesinmscorlib.CoreFXincludesthefoundationallibrariesandsitsontopofCoreCLR.Thisincludesmostbuilt-incomponentsthataren'tsimpletypes.
Note
Youmaybefamiliarwiththe<gcServer>elementusedtosetaGCmode,moresuitableforserveruse,withshorterpauses.Youcanreadmoreabouttheoriginalversionatmsdn.microsoft.com/en-us/library/ms229357.In.NETCoreyoucansettheCOMplus_gcServerenvironmentvariableto1orsetSystem.GC.ServertotrueasaruntimeoptioninaJSONruntimeconfigurationfile.
It'sworthhighlightinganotherprojectcalledCoreRT,whichisaruntimethatallowsahead-of-time(AOT)compilation,insteadoftheJITofCoreCLR.ThismeansthatyoucancompileyourC#codetonativemachinecode,andrunitwithoutanydependencies.Youendupwithasingle(staticallylinked)binaryanddon'tneed.NETinstalled,whichisverysimilartohowGooperates.WiththeRoslyncompiler,younolongeralwaysneedtocompiletoCommonIntermediateLanguage(CIL)bytecodethenhavetheCLRJITcompiletonativeinstructionsatruntimewithRyuJIT.
Thisnativetoolchainallowsforperformanceimprovements,asthecompilationdoesnothavetohappenquickly,inrealtime,andcanbefurtheroptimized.Forexample,abuildcanbetunedforexecutionspeedattheexpenseofcompilationspeed.It'sconceptuallysimilartotheNativeImageGenerator(NGen)tool,whichhasbeeninthefull.NETFrameworksinceitsinception.
ASP.NETCoreASP.NETCorerunsontopof.NETCore,althoughitcanalsorunonthefull.NETFramework.Wewillonlycoverrunningon.NETCore,asthisperformsbetterandensuresenhancedplatformsupport.TherearemanyprojectsthatmakeupASP.NETCoreandit'sworthbrieflymentioningsomeofthem.
Tip
It'susefultonotincludeanyframeworkreferencesto.NET4.5/4.6inyourproject,sothatyoucanbesureyou'reonlyusing.NETCoreanddon'taccidentallyreferenceanydependenciesthatarenotyetsupported.
ASP.NETCoreincludesModelViewController(MVC),WebAPI,andWebPages(awaytomakesimplepageswithRazor,similartoPHP,andthespiritualsuccessortoclassicASP).Thesefeaturesareallmergedtogether,soyoudon'tneedtothinkofMVCandWebAPIasseparateframeworksanymore.Therearemanyotherprojectsandrepositories,includingEFCore,buttheonewewillhighlighthereistheKestrelHTTPserver.
Kestrel
KestrelisanewwebserverforASP.NETCoreanditperformsbrilliantly.It'sbasedonlibuv,whichisanasynchronousI/OabstractionandsupportlibrarythatalsorunsbelowNode.js.Kestrelisblazinglyfast,andthebenchmarksareveryimpressive.However,itisprettybasic,andforproductionhosting,youshouldputitbehindareverseproxy,sothatyoucanusecachingandotherfeaturestoserviceagreaternumberofusers.YoucanusemanyHTTPorproxyserversforthispurposesuchasIIS,NGINX,Apache,orHAProxy.
Tip
YoushouldbecarefulwithyourconfigurationifusingNGINXasareverseproxy,asbydefault,itwillretryPOSTrequestsiftheresponsefromyourwebservertimesout.Thiscouldresultinduplicateoperationsbeingperformed,especiallyifusedasaloadbalanceracrossmultiplebackendHTTPservers.
DatastructuresDatastructuresareobjectsthatyoucanusetostoretheinformationyou'reworkingon.Choosingthebestimplementationforhowyourdataisusedcanhavedramaticeffectsonthespeedofexecution.Here,we'lldiscusssomecommonandsomemoreinterestingdatastructuresthatyoumightliketomakeuseof.
Asthisisabookaboutwebapplicationprogrammingandnotoneoncomplexalgorithmimplementationormicro-optimization,wewon'tbegoingintoahugeamountofdetailondatastructuresandalgorithms.Asbrieflymentionedintheintroduction,otherfactorscandwarftheexecutionspeedinawebcontext,andweassumeyou'renotwritingagameengine.However,goodalgorithmscanhelpspeedupapplications,so,ifyouareworkinginanareawhereexecutionperformanceisimportant,youshouldreadmoreaboutthem.
We'remoreinterestedintheperformanceofthesystemasawhole,notnecessarilythespeedthecoderunsat.Itisoftenmoreimportanttoconsiderwhatyourcodeexpresses(andhowthisaffectsothersystems)thanhowitexecutes.Nevertheless,itisstillimportanttochoosetherighttoolforthejob,andyoudon'twanttohaveunnecessarilyslowcode.Justbecarefulofover-optimizingwhenitalreadyexecutesfastenough,andaboveall,trytokeepitreadable.
ListsA.NETList<T>isastapleofprogramminginC#.It'stypesafe,soyoudon'thavetobotherwithcastingorboxing.Youspecifyyourgenerictypeandcanbesurethatonlyobjectsofthatclass(orprimitive)canbeinyourlist.Listsimplementthestandardlistandenumerableinterfaces(IListandIEnumerable),althoughyougetmoremethodsontheconcretelistimplementation,forexample,addingarange.YoucanalsouseLanguage-IntegratedQuery(LINQ)expressionstoeasilyquerythem,whichistrivialwhenusingfluentlambdafunctions.However,althoughLINQisoftenanelegantsolutiontoaproblem,itcanleadtoperformanceissues,asitisnotalwaysoptimized.
Alistisreallyjustanenhanced,one-dimensional,array.Infact,itusesanarrayinternallytostorethedata.Insomecases,itmaybebettertodirectlyuseanarrayforperformance.Arrayscanoccasionallybeabetterchoice,ifyouknowexactlyhowmuchdatatherewillbe,andyouneedtoiteratethroughitinsideatightloop.Theycanalsobeusefulifyouneedmoredimensions,orplantoconsumeallofthedatainthearray.
Youshouldbecarefulwitharrays;usethemsparinglyandonlyifbenchmarkingshowsaperformanceproblemwheniteratingoveralist.Althoughtheycanbefaster,theyalsomakeparallelprogramminganddistributedarchitecturemoredifficult,whichiswheresignificantperformanceimprovementscanbemade.
Modernhighperformancemeansscalingouttomanycoresandmultiplemachines.Thisiseasierwithanimmutablestatethatdoesn'tchange,whichiseasiertoenforcewithhigherlevelabstractionsthanwitharrays.Forexample,youcanhelpenforcearead-onlylistwithaninterface.
Ifyouareinsertingorremovingalotofitemsinthemiddleofalargelist,thenitmaybebettertousetheLinkedList<T>class.Thishasdifferentperformancecharacteristicstoalist,asitisn'treallyalist–it'smoreofachain.Itmayperformbetterthanalistforsomespecializedcases,but,inmostcommoncases,itwillbeslower.Forexample,accessbyindexisquickwithalist(asitisarraybacked),butslowwithalinkedlist(asyouwillhavetowalkthechain).
Itisnormallybesttoinitiallyfocusonthewhatandwhyofyourcoderatherthanthehow.LINQisverygoodforthis,asyousimplydeclareyourintentions,anddon'tneedtoworryabouttheimplementationdetailsandloops.Itisabadideatooptimizeprematurely,sodothisonlyiftestingshowsaperformanceproblem.Inmostcommoncases,alististhecorrectchoiceunlessyouneedtoselectonlyafewvaluesfromalargeset,inwhichcase,dictionariescanperformbetter.
DictionariesDictionariesaresimilartolists,butexcelatquicklyretrievingaspecificvaluewithakey.Internally,theyareimplementedwithahashtable.There'sthelegacyHashtableclass(intheSystem.Collections.NonGenericpackage)butthisisnottypesafe,whereasDictionary<T>isagenerictype,soyouprobablyshouldn'tuseHashtableunlessyou'reportingoldcodeto.NETCore.ThesameappliestoArrayList,whichisthelegacy,non-genericversionofList.
Adictionarycanlookupavaluewithakeyveryquickly,whereasalistwouldneedtogothroughallthevaluesuntilthekeywasfound.Youcan,however,stillenumerateadictionaryasitisordered,althoughthisisn'treallyhowitisintendedtobeused.Ifyoudon'tneedordering,thenyoucanuseaHashSet.Therearesortedversionsofallofthesedatastructures,andyoucanagainuseread-onlyinterfacestomakethemdifficulttomutate.
CollectionbenchmarksAccuratebenchmarkingishardandtherearelotsofthingswhichcanskewyourresults.Compilersareverycleverandwilloptimize,whichcanmaketrivialbenchmarkslessvaluable.Thecompilermayoutputverysimilarcodefordifferentimplementations.
Whatyouputinyourdatastructureswillalsohavealargeeffectontheirperformance.It'susuallybesttotestorprofileyouractualapplicationandnotoptimizeprematurely.Readabilityofcodeisveryvaluableandshouldn'tbesacrificedforruntimeefficiencyunlessthereisasignificantperformanceproblem(orifit'salreadyunreadable).
Therearebenchmarkingframeworksthatyoucanusetohelpwithyourtesting,suchasBenchmarkDotNetwhichisavailableatgithub.com/PerfDotNet/BenchmarkDotNet.However,thesecanbeanoverkill,andaresometimestrickytosetup,especiallyon.NETCore.OtheroptionsincludeSimpleSpeedTester(whichyoucanreadmoreaboutattheburningmonk.github.io/SimpleSpeedTester)andMiniBench(availablefromgithub.com/minibench).
We'llperformsomesimplebenchmarkstoshowhowyoumightgoaboutthis.However,don'tassumethattheconclusionsdrawnherewillalwaysholdtrue,sotestforyoursituation.First,wewilldefineasimplefunctiontorunourtests:
privatestaticlongRunTest(Func<double>func,intruns=1000)
{
vars=Stopwatch.StartNew();
for(intj=0;j<runs;j++)
{
func();
}
s.Stop();
returns.ElapsedMilliseconds;
}
WeuseStopwatchhereasusingDateTimecancauseproblems,evenwhenusingUTC,asthetimecouldchangeduringthetestandtheresolutionisn'thighenough.Wealsoneedtoperformmanyrunstogetanaccurateresult.Wethendefineourdatastructurestotestandprepopulatethemwithrandomdata.
varrng=newRandom();
varelements=100000;
varrandomDic=newDictionary<int,double>();
for(inti=0;i<elements;i++)
{
randomDic.Add(i,rng.NextDouble());
}
varrandomList=randomDic.ToList();
varrandomArray=randomList.ToArray();
Wenowhaveanarray,list,anddictionarycontainingthesamesetof100,000key/valuepairs.
Next,wecanperformsometestsonthemtoseewhatstructureperformsbestinvarioussituations.
varafems=RunTest(()=>
{
varsum=0d;
foreach(varelementinrandomArray)
{
sum+=element.Value;
}
returnsum;
},runs);
Theprecedingcodetimeshowlongittakestoiterateoveranarrayinaforeachloopandsumsupthedoubleprecisionfloatingpointvalues.Wecanthencomparethistootherstructuresandthedifferentwaysofaccessingthem.Forexample,iteratingadictionaryinaforloopisdoneasfollows:
vardfms=RunTest(()=>
{
varsum=0d;
for(inti=0;i<randomDic.Count;i++)
{
sum+=randomDic[i];
}
returnsum;
},runs);
Thisperformsverybadly,asitisnothowdictionariesaresupposedtobeused.Dictionariesexcelatextractingarecordbyitskeyveryquickly.Soquicklyinfactthatyouwillneedtorunthetestmanymoretimestogetarealisticvalue.
varlastKey=randomList.Last().Key;
vardsms=RunTest(()=>
{
doubleresult;
if(randomDic.TryGetValue(lastKey,outresult))
{
returnresult;
}
return0d;
},runs*10000);
Console.WriteLine($"Dictselect{(double)dsms/10000}ms");
GettingavaluefromadictionarywithTryGetValueisextremelyquick.Youneedtopassthevariabletobesetintothemethodasanoutparameter.YoucanseeifthiswassuccessfulandiftheitemwasinthedictionarybytestingtheBooleanvaluereturnedbythemethod.
Conversely,addingitemstoadictionaryonebyonecanbeslow,soitalldependsonwhatyou'reoptimizingfor.Thefollowingimageshowstheoutputofaverysimpleconsoleapplicationthattestsvariouscombinatorialpermutationsofdatastructuresandtheiruses:
Theseresults,shownintheprecedingimage,areinformative,butyoushouldbeskeptical,asmanythingscanskewtheoutput,forexample,theorderingofthetests.Ifthegapissmall,thenthereisprobablynotmuchtochoosebetweentwovariants,butyoucanclearlyseethebigdifferences.
Tip
Togetmorerealisticresults,besuretocompileinreleasemodeandrunwithoutdebugging.Theabsoluteresultswilldependonyourmachineandarchitecture,buttherelativemeasuresshouldbeusefulforcomparisons.Youmaygethigherperformanceifcompilingtoasingleexecutablebinarywiththe.NETnativetoolchainorwithadifferentreleaseofthe.NETCoreframework.
Themainlessonhereistomeasureforyourspecificapplicationandchoosethemostappropriatedatastructurefortheworkthatyouareperforming.Thecollectionsinthestandardlibraryshouldserveyouwellformostpurposes,andthereareothersthatarenotcoveredhere,whichcansometimesbeuseful,suchasaQueueorStack.
Youcanfindmoreinformationaboutthebuilt-incollectionsanddatastructuresonMSDN(msdn.microsoft.com/en-us/library/system.collections.generic).Youcanalsoreadaboutthemonthe.NETCoredocumentationsiteontheGitHubpages(dotnet.github.io/docs/essentials/collections/Collections-and-Data-Structures.html).
However,therearesomerarerdatastructures,notinthestandardcollection,thatyoumayoccasionallywishtouse.We'llshowanexampleofoneofthesenow.
BloomfiltersBloomfiltersareaninterestingdatastructurethatcanincreaseperformanceforcertainusecases.Theyusemultipleoverlaidhashingfunctionsandcanquicklytellyouifanitemdefinitelydoesnotexistinaset.However,theycan'tsaywithcertaintyifanitemexists,onlythatitislikelyto.Theyareusefulasapre-filter,sothatyoucanavoidperformingalookup,becauseyouknowforsurethattheitemwon'tbethere.
ThefollowingimageshowshowaBloomfilterworks.A,B,andChavebeenhashedandinsertedintothefilter.Dishashedtocheckifitisinthefilterbut,asitmapstoazerobit,weknowthatitisnotinthere.
Bloomfiltersaremuchsmallerthanholdingallthedataorevenalistofhashesforeachitemintheset.Theycanalsobemuchquicker,asthelookuptimeisconstantforanysizeofset.Thisconstanttimecanbelowerthanthetimetolookupaniteminalargelistordictionary,especially
ifitisonthefilesystemorinaremotedatabase.
AnexampleapplicationforaBloomfiltercouldbealocalDNSserver,whichhasalistofdomainstooverride,butforwardsmostrequeststoanupstreamserver.Ifthelistofcustomdomainsislarge,thenitmaybeadvantageoustocreateaBloomfilterfromtheentriesandholdthisinmemory.
Whenarequestcomesin,itischeckedagainstthefilter,andifitdoesn'texist,thentherequestisforwardedtotheupstreamserver.Iftheentrydoesexistinthefilter,thenthelocalhostsfileisconsulted;iftheentryisthere,itsvalueisused.Thereisasmallchancethattheentrywillnotbeinthelist,evenifthefilterthinksitis.Inthiscase,whenitisn'tfound,therequestisforwarded,butthisapproachstillavoidstheneedtoconsultthelistforeveryrequest.
AnotherexampleofusingaBloomfilterisinacachingnode,perhapsaspartofaproxyorCDN.Youwouldn'twanttocacheresourcesthatareonlyrequestedonce,buthowcanyoutellwhenthesecondrequestoccursifyouhaven'tcachedit?IfyouaddtherequesttoaBloomfilter,youcaneasilytellwhenthesecondrequestoccursandthencachetheresource.
TheyarealsousedinsomedatabasestoavoidexpensivediskoperationsandinCacheDigests,whichallowanagenttodeclarethecontentsofitscache.HTTP/2maysupportCacheDigestsinthefuture,butthiswillprobablyuseGolomb-codedsets(GCS),whicharesimilartoBloomfilters,butsmaller,attheexpenseofslowerqueries.
ThereisanopensourceimplementationofaBloomfilterin.NETavailableatbloomfilter.codeplex.comamongothers.Youshouldtesttheperformanceforyourselftomakesuretheyofferanimprovement.
HashingandchecksumsHashingisanimportantconcept,whichisoftenusedtoensuredataintegrityorlookupvaluesquicklyandsoitisoptimizedtobefast.Thisiswhygeneralhashingfunctionsshouldnotbeusedontheirowntosecurelystorepasswords.Ifthealgorithmisquick,thenthepasswordcanbeguessedinareasonablyshortamountoftime.Hashingalgorithmsvaryintheircomplexity,speedofexecution,outputlength,andcollisionrate.
Averybasicerrordetectionalgorithmiscalledaparitycheck.Thisaddsasinglebittoablockofdataandisrarelyuseddirectlyinprogramming.Itis,however,extensivelyusedatthehardwarelevel,asitisveryquick.Yet,itmaymissmanyerrorswherethereareanevennumberofcorruptions.
ACyclicRedundancyCheck(CRC)isaslightlymorecomplexerrordetectingalgorithm.TheCRC-32(alsowrittenCRC32)versioniscommonlyusedinsoftware,particularlyincompressionformats,asachecksum.
Tip
Youmaybefamiliarwiththebuilt-insupportforhashcodesin.NET(withtheGetHashCodemethodonallobjects),butyoushouldbeverycarefulwiththis.Theonlyfunctionofthismethodistoassistwithpickingbucketsindatastructuresthatusehashtablesinternally,suchasadictionary,andalsoinsomeLINQoperations.Itisnotsuitableasachecksumorkey,becauseitisnotcryptographicallysecureanditvariesacrossframeworks,processes,andtime.
YoumayhaveusedtheMessageDigest5(MD5)algorithminthepast,buttodayitsuseisstronglydiscouraged.ThesecurityofMD5isheavilycompromisedandcollisionscanbeproducedeasily.Sinceitisveryquick,itmayhavesomenon-secureuses,suchasnon-maliciouserrorcheckingbuttherearebetteralgorithmsthatarefastenough.
Ifyouneedastrongbutquickhashingfunction,thentheSecureHashAlgorithm(SHA)familyisagoodchoice.However,SHA-1isnotconsideredfutureproof,soforanewcode,SHA-256isgenerallyabetterchoice.
Whensigningmessages,youshoulduseadedicatedMessageAuthenticationCode(MAC),suchasaHash-basedMAC(HMAC),whichavoidsvulnerabilitiesinasinglepassofthehashingfunction.AgoodoptionistheHMACSHA256classbuiltinto.NET.VariousAPIs,suchassomeoftheAWSRESTAPIs,useHMAC-SHA256toauthenticaterequests.Thisensuresthat,eveniftherequestisperformedoveranunencryptedHTTPchannel,theAPIkeycan'tbeinterceptedandrecovered.
AsbrieflymentionedinChapter1,WhyPerformanceIsaFeature,passwordhashingisaspecialcaseandgeneralpurposehashingalgorithmsarenotsuitableforit–theyaretoofast.AgoodchoiceisPassword-BasedKeyDerivationFunction2(PBKDF2),whichweusedasanexampleinChapter2,MeasuringPerformanceBottlenecks.PBKDF2isaparticularlypopular
choicefor.NET,asitisbuiltintotheframework,andso,theimplementationismorelikelytobecorrect.IthasbeenbuiltagainstanRFCandreviewedbyMicrosoft,whichyoucan'tsayforanyrandompieceofcodefoundonline.Forexample,youcoulddownloadanimplementationofbcryptfor.NET,butyouhavetotrustthatitwascodedcorrectlyorverifyityourself.
HashingbenchmarksLet'sdosomesimplebenchmarkingofvarioushashfunctionstoseehowtheycompareperformancewise.Inthefollowingcodesnippet,wedefineamethodforrunningourtests,similartotheoneforthepreviouscollectionbenchmarks,buttakinganActionparameter,ratherthanaFunc<double>,aswedon'twanttoreturnavalue:
privatestaticlongRunTest(Actionfunc,intruns=1000)
{
vars=Stopwatch.StartNew();
for(intj=0;j<runs;j++)
{
func();
}
s.Stop();
returns.ElapsedMilliseconds;
}
Weincludethefollowingusingstatement:
usingSystem.Security.Cryptography;
Next,wedefineashortprivateconstantstring(hashingData)tohashintheclassandgetthebytesforitinan8-bitUnicode(UTF8)format.
varsmallBytes=Encoding.UTF8.GetBytes(hashingData);
Wealsowanttogetalargerblockofbytestohashtoseehowitcomparesperformancewise.Forthis,weuseacryptographicallysecurerandomnumbergenerator.
varlargeBytes=newbyte[smallBytes.Length*100];
varrng=RandomNumberGenerator.Create();
rng.GetBytes(largeBytes);
Weneedakeyforsomeofourfunctions,soweusethesametechniquetogeneratethis.
varkey=newbyte[256];
varrng=RandomNumberGenerator.Create();
rng.GetBytes(key);
Next,wecreateasortedlistofthealgorithmstotestandexecutethetestsforeachone:
varalgos=newSortedList<string,HashAlgorithm>
{
{"1.MD5",MD5.Create()},
{"2.SHA-1",SHA1.Create()},
{"3.SHA-256",SHA256.Create()},
{"4.HMACSHA-1",newHMACSHA1(key)},
{"5.HMACSHA-256",newHMACSHA256(key)},
};
foreach(varalgoinalgos)
{
HashAlgorithmTest(algo);
}
Ourtestmethodrunsthefollowingtestsoneachalgorithm.TheyallinheritfromHashAlgorithm,sowecanruntheComputeHashmethodoneachofthemforthesmallandlargebytearrays.
varsmallTimeMs=RunTest(()=>
{
algo.Value.ComputeHash(smallBytes);
},runs);
varlargeTimeMs=RunTest(()=>
{
algo.Value.ComputeHash(largeBytes);
},runs);
Wethencalculatetheaverage(mean)timeforbothsizes.Wecastthelongintegertoadoubleprecisionfloatingpointnumbersothatwecanrepresentsmallvaluesbetweenoneandzero.
varavgSmallTimeMs=(double)smallTimeMs/runs;
varavgLargeTimeMS=(double)largeTimeMs/runs;
Theprecedingmethodthenoutputsthesemeantimestotheconsole.WeneedtotestPBKDF2separately,asitdoesn'tinheritfromHashAlgorithm.
varslowRuns=10;
varpbkdf2=newRfc2898DeriveBytes(hashingData,key,10000);
varpbkdf2Ms=RunTest(()=>
{
pbkdf2.GetBytes(256);
},slowRuns);
PBKDF2issoslowthatitwouldtakeaconsiderableamountoftimetoperform100,000runs(thisisthepointofusingit).Internally,thisRFC2898implementationofthekey-stretchingalgorithmrunsHMACSHA-110,000times.Thedefaultis1,000,butduetothecomputingpoweravailabletoday,itisrecommendedtosetthistoatleastanorderofmagnitudehigher.Forexample,Wi-FiProtectedAccessII(WPA2)uses4,096roundsofiterationstoproducea256-bitkeywiththeServiceSetIdentifier(SSID)asthesalt.
Theoutputwilllooksomethinglikethefollowing:
Fromtheprecedingoutput,youcanseethatthetimetakenforonehashvariesfromabout720nanosecondsforasmallMD5to32microsecondsforalargeHMACSHA-256and125millisecondsforasmallPBKDF2withtypicalparameters.
Benchmarkingresultscanvarydramatically,soyoushouldn'treadtoomuchintoabsolutevalues.Forexample,theoutputfromtheBenchmarkDotNettoolcomparingMD5andSHA-256onthesamemachinelookslikethis:
Youcanseeinthelastimagethattheresultsaredifferenttoourhomemadebenchmark.However,thisusesthefull.NETFramework,calculatesmedianratherthanmeanfortheaveragetime,andrunsindebugmode(whichithelpfullywarnsusof)amongotherthings.
Afastermachinewillhaveahigherthroughput(ascanbeseenintheBenchmarkDotNetREADME.mdonGitHub).DedicatedhardwaresuchasGraphicsProcessingUnits(GPUs),Field-
ProgrammableGateArrays(FPGAs),andApplication-SpecificIntegratedCircuits(ASICs)canbemuchfaster.Thesetendtobeusedintheminingofbitcoin(andothercryptocurrencies),asthesearebasedonhashingasaproof-of-work.BitcoinusesSHA-256,butothercurrenciesusedifferenthashingalgorithms.
ThesamealgorithmsformthebasisofTLS,sofasterhardwarecanhandleagreaternumberofsecureconnections.Asanotherexample,GooglebuiltacustomASICcalledaTensorProcessingUnit(TPU)toacceleratetheirmachinelearningcloudservices.
OtherbenchmarkingsamplesareavailableinBenchmarkDotNet,andwhenyoufirstrunit,youwillbepresentedwiththefollowingmenu:
Thepreviousbenchmarkwasthesecondoption,(number#1Algo_Md5VsSha256).
Benchmarkingishard,soit'sagoodideatousealibrarysuchasBenchmarkDotNetifyoucan.TheonlyconclusionwecandrawfromourbenchmarksisthatSHA-256isslowerthanMD5.
However,SHA-256shouldbefastenoughformostapplicationsandit'smoresecureforintegritychecking.However,itisstillnotsuitableforpasswordstorage.
SHA-256canbeusedtoprovidesignaturesforverifyingdownloadedfiles,whichmustberetrievedoverHTTPStobesafe,andforsigningcertificates.WhenusedaspartofanHMAC,itcanalsobeusedtosecurelyauthenticatemessages–APIrequests,forexample.YouwillonlyconnectsuccessfullyifyouknowthecorrectAPIkeytohashwith.
SerializationSerializationistheprocessofturningobjectsintodatasuitablefortransmissionoveranetworkorforstorage.Wealsoincludedeserialization,whichisthereverse,underthisumbrella.Serializationcanhavesignificantperformanceimplications,notonlyonthenetworktransmissionspeedbutalsooncomputation,asitcanmakeupmostoftheexpensiveprocessingonawebserver.YoucanreadmoreaboutserializationonMSDN(msdn.microsoft.com/en-us/library/mt656716).
Serializationformatscanbetext-basedorbinary.Somepopulartext-basedformatsareExtensibleMarkupLanguage(XML)andJavaScriptObjectNotation(JSON).ApopularbinaryformatisProtocolBuffers,whichwasdevelopedatGoogle.There'sanotherbinaryserializationformat(BinaryFormatter)builtintothefull.NET,butthisisnotin.NETCore.
XMLhasfallenoutoffashionwithdevelopers,andJSONisnowgenerallypreferred.ThisispartlyduetothesmallersizeofequivalentJSONpayloads,butitmayalsobeduetotheuseofXMLintheoriginallynamedSimpleObjectAccessProtocol(SOAP).ThisisusedinWindowsCommunicationFoundation(WCF),butSOAPisnolongeranacronym,asdevelopersdiscovereditisfarfromsimple.
JSONispopularduetobeingcompact,human-readable,andbecauseitcaneasilybeconsumedbyJavaScript,particularlyinwebbrowsers.TherearemanydifferentJSONserializersfor.NET,withdifferentperformancecharacteristics.However,becauseJSONisnotasrigidlydefinedasXML,therecanbedifferencesinimplementations,whichmakethemincompatible,especiallywhendealingwithcomplextypessuchasdates.Forexample,theverypopularJson.NETrepresentsdatesintheInternationalOrganizationforStandardization(ISO)format,whereastheJSONserializerusedinoldversionsofASP.NETMVCrepresenteddatesasthenumberofmillisecondssincetheUnixepoch,wrappedinaJavaScriptdateconstructor.
The.NETdevelopercommunityhasconvergedonJson.NET,andcompatibilityisalwayspreferabletoperformance.ASP.NETWebAPIhasusedJson.NETasthedefaultforawhilenow,andASP.NETCorealsousesJson.NET.Thereisaserializerthat'spartoftheServiceStackframeworkcalledServiceStack.Text,whichclaimstobefaster,butyoushouldprobablyvaluecompatibilityanddocumentationoverspeed.ThesameappliestootherJSONlibrariessuchasJil(github.com/kevin-montrose/Jil)andNetJSON(github.com/rpgmaker/NetJSON),whichcanbeevenfasterthanServiceStackinbenchmarks.
Ifyouareafterpureperformance,andyoucontrolalloftheendpoints,thenyouprobablywouldwanttouseabinaryprotocol.However,thismaylimitfutureinteroperabilitywiththird-partyendpointswhichyoudon'tcontrol.Therefore,it'sbesttoonlyusetheseinternally.
ItwouldbeabadideatobuildyourowncustommessageprotocolontopofUDP.So,ifyouwanttousebinaryserialization,youshouldlookatsomethinglikeprotobuf-net,whichisaProtocolBuffersimplementationfor.NET.YoumayalsowishtoconsiderMicrosoft'sBondframework
(github.com/Microsoft/bond)orAmazon'sIon(amznlabs.github.io/ion-docs).Youmayneedtotunethesetoolsforbestperformance,forexample,bychangingthedefaultbuffersize.
SIMDCPUinstructionsSingleInstructionMultipleData(SIMD)isatechniquethatisavailableonmanymodernprocessorsandcanspeedupexecutionbyparallelizingcalculationseveninasinglethreadononecore.SIMDtakesadvantageofadditionalinstructionsavailableonCPUstooperateonsetsofvalues(vectors)ratherthanjustsinglevalues(scalars).
ThemostcommoninstructionsetforthisiscalledStreamingSIMDExtensions2(SSE2)andithasbeenaroundforover15yearssinceitsdebutwiththePentium4.AnewerinstructionsetcalledAdvancedVectorExtensions(AVX)offerssuperiorperformanceoverSSE2andhasbeenaroundforoverfiveyears.So,ifyou'reusingareasonablyrecentx86-64CPU,thenyoushouldhaveaccesstotheseextrainstructions.
Note
SomeARMCPUs(suchasthoseintheRaspberryPi2and3)containasimilartechnologycalledNEON,officiallyknownasAdvancedSIMD.Thisisnotcurrentlysupportedin.NET,butmaybeinthefuture.AnofficialopensourcelibraryprojectinCishostedatprojectne10.org.
YoucanusethefollowingBooleanpropertytotestifSIMDissupported:
Vector.IsHardwareAccelerated
ThispropertyisJITintrinsic,andthevalueissetbyRyuJITatruntime.
YoucaninstantiateagenerictypedVectororuseoneofthetwo/three/fourdimensionalconvenienceclasses.Forexample,tocreateasingleprecisionfloatingpointvector,youcouldusethefollowinggenericcode:
varvectorf=newVector<float>(11f);
Tocreateasingleprecisionfloatingpoint3Dvectorinstead,youcouldusethiscode:
varvector3d=newVector3(0f,1f,2f);
Tip
AtwodimensionaldoubleprecisionfloatingpointvectorcanbeagoodsubstituteforaComplexstructure.Itwillgivehigherperformanceonhardwareacceleratedsystems.Vector2onlysupportssingleprecisionfloatingpointnumbers,butyoucanusethegenerictypetospecifytherealandimaginarycomponentsofthecomplexnumberasadouble.Complexonlysupportsdoubleprecisionfloatingpointnumbers,but,ifyoudon'tneedhighprecision,youcouldstillusetheVector2convenienceclass.Unfortunately,thismeansthatit'snotsimplyadropinreplacement,butthemathisdifferentanyway.
Youcannowusestandardvectormathematics,butmodifyingyouralgorithmstotakeadvantageofvectorscanbecomplexandisn'tsomethingyoushouldtypicallybedoinginawebapplication.It
canbeusefulfordesktopapplications,but,ifaprocesstakesalongtimeinawebrequest,it'softenbesttorunitinthebackgroundandthenitdoesn'tneedtobeasquick.
Wewillcoverthisdistributedarchitectureapproachinthenextchapter.Forthisreason,wewon'tbegoingintoanymoredetailonSIMD,butyoucanreadmoreonitifyouwish,nowthatyouhaveatasteofit.Youcanreadsomebackgroundinformationatwikipedia.org/wiki/SIMDandyoucanfindthedocumentationforthe.NETimplementationonMSDNatmsdn.microsoft.com/en-us/library/dn858218.Youcouldalsotakealookattheexampleconsoleapplication,whichisavailablefordownloadalongwiththisbook,asasimplestarterforten.
ParallelprogrammingWhileSIMDisgoodatincreasingtheperformanceofasinglethreadrunningononecore,itdoesn'tworkacrossmultiplecoresorprocessorsanditsapplicationsarelimited.ModernscalingmeansaddingmoreCPUs,notsimplymakingasinglethreadfaster.Wedon'tjustwanttoparallelizeourdataasSIMDdoes;weshouldactuallyfocusmoreonparallelizingourprocessing,asthiscanscalebetter.
Therearevarious.NETtechnologiesavailabletohelpwithparallelprocessingsothatyoudon'thavetowriteyourownthreadingcode.TwosuchparallelextensionsareParallelLINQ(PLINQ),whichextendstheLINQoperationsyou'refamiliarwith,andtheTaskParallelLibrary(TPL).
TaskParallelLibraryOneofthemainfeaturesoftheTPListoextendloopstoruninparallel.However,youneedtobecarefulwithparallelprocessing,asitcanactuallymakeyoursoftwareslowerwhiledoingsimpletasks.Theoverheadsinvolvedwithmarshallingthemultipletaskscandwarftheexecutionoftheworkloadfortrivialoperations.
Forexample,takethefollowingsimpleforloop:
for(inti=0;i<array.Length;i++)
{
sum+=array[i];
}
Thearrayintheprecedingforloopcontains100,000integers,butaddingintegersisoneoftheeasiestthingsaCPUcandoandusingaforlooponanarrayisaveryquickwayofenumerating.Thisaccumulationwillcompleteinunderatenthofamillisecondonareasonablymodernmachine.
Youmaythinkthatyouwouldbeabletospeedthisupbyparallelizingtheoperation.Perhapsyoucouldsplitthearray,runthesummationontwocoresinparallelandaddtheresults.
Youmightusethefollowingcodetoattemptthis:
Parallel.For(0,array.Length,i=>
{
Interlocked.Add(refsum,array[i]);
});
Tip
Youmustuseaninterlockedaddoryouwillgetanincorrectsummationresult.Ifyoudon't,thethreadswillinterferewitheachother,corruptingthedatawhenwritingtothesamelocationinmemory.
However,thiscodeactuallyrunsover42timesslowerthanthefirstexample.Theextraoverhead,complexityofrunningmanythreads,andlockingthevariablesothatonlyonethreadcanwritetoitatatimeisjustnotworthitinthiscase.
Parallelizationcanbeusefulformorecomplexprocesses,especiallyifthebodyoftheloopperformssomeslowoperationsuchasaccessingthefilesystem.However,blockingI/Ooperationsmaybebetterdealtwithbyusingasynchronousaccess.Parallelaccesscancausecontention,becauseaccessmayeventuallyhavetobeperformedinseriesatsomepoint,forexample,atthehardwarelevel.
Ifwewanttoperformamoreprocessor-intensiveoperation,suchashashingmultiplepasswords,thenrunningthetasksinparallelcanbebeneficial.ThefollowingcodeperformsaPBKDF2hashoneachpasswordinalistandthencalculatestheBase64representationoftheresult:
foreach(varpasswordinpasswords)
{
varpbkdf2=newRfc2898DeriveBytes(password,256,10000);
Convert.ToBase64String(pbkdf2.GetBytes(256));
}
We'renotusingtheoutputinthisexample,butyoumaybedoingthistoupgradethesecurityofthepasswordsinyourdatabasebymigratingthemtoamoreresilientkey-stretchingalgorithm.Theinputmaybeplaintextpasswordsortheoutputofalegacyone-wayhashfunction,forexampleMD5oranunsaltedSHA.
WecanimprovethespeedofthisonamulticoresystembyusingtheParallel.ForEachloop,usingcodesuchasthefollowing:
Parallel.ForEach(passwords,password=>
{
varpbkdf2=newRfc2898DeriveBytes(password,256,10000);
Convert.ToBase64String(pbkdf2.GetBytes(256));
});
Thiswillspeeduptheprocess,butbyhowmuchwilldependonmanyfactors,suchasthenumberofpasswordsinthelist,thenumberoflogicalprocessorsandthenumberofCPUcores.Forexample,onaCorei5CPUwithtwocores,butfourlogicalprocessors,havingonlytwopasswordsinthelistdoesnotresultinamassiveimprovement(only1.5timesquicker).Withfourpasswords(ormore)inthelist,theimprovementisbetter(about1.9timesquicker).Thereisstillsomeoverhead,soyoucan'tgetdoublethespeedwithtwicetheCPUcores.
WecanseethereasonforthisdifferencebylookingattheCPUutilizationinthetaskmanagerduringbenchmarking.Withonlytwopasswordstohash,theCPUgraphlookslikethefollowing:
Intheprecedinggraph,wecanseethatinitially,whenhashinginseries,theCPUisrunningatabout25%,fullyusingonelogicalCPU.Whenhashingtwopasswordsinparallel,ituses50%,runningontwologicalprocessors.Thisdoesn'ttranslateintoatwofoldincreaseinspeedduetotheintrinsicoverheadsandthenatureofhyper-threading.
Note
Hyper-threadingisatechnologythattypicallyexposestwologicalprocessorstotheOSforeach
physicalcore.However,thetwologicalCPUsstillsharetheexecutionresourcesoftheirsinglecore.
AlthoughtherearetwocoresontheCPUdie,hyper-threadingexposesfourlogicalCPUstotheOS.Asweonlyhavetwothreads,becausewearehashingtwopasswords,wecanonlyusetwoprocessors.Ifthethreadsareexecutedondifferentcores,thenthespeedincreasecanbegood.Butiftheyareexecutedonprocessorssharingthesamecore,thenperformancewon'tbeasimpressive.Itisstillbetterthansingle-threadedhashingduetoschedulingimprovements,whichiswhathyper-threadingisdesignedfor.
Whenwehashfourpasswordsatthesametime,theCPUgraphlookslikethefollowing:
Wecanseethatnowtheinitial25%usagejumpstoalmostfullutilizationandwearemakinguseofmostoftheprocessor.Thistranslatestojustunderadoublingoftheperformanceascomparedtohashinginsequence.Therearestillsignificantoverheadsinvolved,but,asthemainoperationisnowsomuchquicker,thetradeoffisworthit.
ParallelLINQThereareotherwaystotakeadvantageofparallelprogramming,suchasLINQexpressions.WecouldrewritethepreviousexampleasaLINQexpressionanditmaylooksomethinglikethefollowing:
passwords.AsParallel().ForAll(p=>
{
varpbkdf2=newRfc2898DeriveBytes(p,256,10000);
Convert.ToBase64String(pbkdf2.GetBytes(256));
});
YoucanenablethesefeatureswiththeAsParallel()method.TheForAll()methodhasthesamepurposeastheloopsinpreviousexamplesandisusefuliftheorderisunimportant.Iforderingisimportant,thenthereisanAsOrdered()method,whichcanhelpsolvethis.However,thiscanreducetheperformancegainsduetotheextraprocessinginvolved.
Thisexampleperformssimilarlytothepreviousonethatusedaparallelloop,whichisunsurprising.Wecanalsolimitthenumberofoperationsthatcanoccurinparallel,usingtheWithDegreeOfParallelism()methodasfollows:
passwords.AsParallel().WithDegreeOfParallelism(2).ForAll(p=>
{
varpbkdf2=newRfc2898DeriveBytes(p,256,10000);
Convert.ToBase64String(pbkdf2.GetBytes(256));
});
Thisprecedingexamplelimitsthehashestotwoatatimeandperformssimilarlytowhenweonlyhadtwopasswordsinthelist,whichistobeexpected.Thiscanbeusefulifyoudon'twanttomaxouttheCPU,becausethereareotherimportantprocessesrunningonit.
YoucanachievethesameeffectwiththeTPLbysettingtheMaxDegreeOfParallelismpropertyonaninstanceoftheParallelOptionsclass.Thisobjectcanthenbepassedintooverloadedversionsoftheloopmethodsasaparameter,alongwiththemainbody.
Tip
It'simportant,whenyou'reusingparallelLINQtoquerydatasets,thatyoudon'tlosesightofthebestplaceforthequerytobeperformed.Youmayspeedupaqueryintheapplicationwithparallelization,butthebestplaceforthequerytooccurmaystillbeinthedatabase,whichcanbeevenfaster.Toreadmoreonthistopic,referbacktoChapter5,OptimizingI/OPerformance,andChapter3,FixingCommonPerformanceProblems.
ParallelbenchmarkingLet'shavealookattheoutputofasimple.NETCoreconsoleapplication,whichbenchmarksthetechniquesthatwehavejustdiscussed.Itshowsonesituationwhereparallelizationdoesn'thelpandactuallymakesthingsworse.Itthenshowsanothersituationwhereitdoeshelp.
Whencalculatingasum,byaccumulating100,000randomintegersbetweenzeroandten,thequickestwayistouseanarrayinasimpleforeachloop.Usingparallelizationheremakestheprocessmuchslower,andifusedNaïvely,withoutlocking,willgiveanincorrectresult,whichismuchworse.
Whenperformingamorecomputationallyintensiveworkload,suchasaPBKDF2hashing
functiononmultiplepasswords,parallelizationcanhelpsignificantly.Thetimeisalmosthalved,asitisrunningacrosstwocores.Thefinaloperation,whichlimitsthenumberofthreads,cantakeavaryingamountoftimeondifferentruns.Thisislikelyduetothethreadssometimessharingacoreandsometimesrunningondifferentcores.Itcanbealmostasquickasusingalllogicalcores,dependingonthework.
TheCPUgraphforthebenchmarklookslikethefollowing:
TheinitialparallelsummationsmaxouttheCPUandareveryinefficient.Next,thesingle-threadedhashingusesonlyonelogicalprocessor(25%),buttheother,laterhashesmakealmostfulluseofboththecores.Thefinalhashing,limitedtotwopasswordsatatime,onlymakesuseofhalftheCPUpower.
ParallelprogramminglimitationsPerformanceproblemswithwebapplicationsdon'ttypicallymeanincreasingspeedforasingleuseronthesysteminisolation.It'seasytomakeawebappperformwhenthere'sonlyoneuser,butthechallengeliesinmaintainingthatsingleuserperformanceasthenumberofusersscalesupandyouhavewall-to-wallrequests.
Theparallelprogrammingtechniquesdiscussedinthissectionhavelimiteduseinscalingwebapplications.Youalreadyhaveaparallelizedsystem,aseachuserrequestwillbeallocateditsownresources.Youcansimplyaddmoreinstances,agents,ormachinestomeetdemand.Theproblemthenisindistributingworkefficientlybetweenthemandavoidingbottlenecksforsharedresources.We'llcoverthismoreinthenextchapter,butfirstlet'slookatsomethingsthatyoushouldbeavoiding.
PracticestoavoidWe'veshownsomewaysofspeedingupsoftware,butit'softenbettertoillustratewhatnottodoandhowthingscangowrong.Webapplicationsgenerallyperformwellifnobadpracticeshavebeenfollowedandherewe'llhighlightafewthingsyoushouldwatchoutfor.
ReflectionReflectionistheprocessofprogrammaticallyinspectingyourcodewithothercode,anddiggingintoitsinternalsatruntime.Forexample,youcouldinspectanassemblywhenitisloadedtoseewhatclassesandinterfacesitimplementssothatyoucancallthem.Itisgenerallydiscouragedandshouldbeavoidedifpossible.Thereareusuallyotherwaystoachievethesameresultthatdon'trequirereflection,althoughitisoccasionallyuseful.
Reflectionisoftenbadforperformance,andthisiswell-documented,but,asusual,itdependsonwhatyou'reusingitfor.Whatisnewisthattherearesignificantchangestoreflectionfor.NETCore.TheAPIhaschangedanditisnowoptional.So,ifyoudon'tusereflection,youdon'thavetopaytheperformancepenalty.Thisallowsthenativetoolchaintooptimizecompilationbetter,asreflectionaddsrestrictionstowhatcanbedonewithstaticlinking.
ThereisanextramethodonthereflectionAPInow,so,whereaspreviouslyyouwouldhavecalledsomethinglikemyObject.GetType().GetMembers(),younowneedtocallitasmyObject.GetType().GetTypeInfo().GetMembers()byinsertingthenewGetTypeInfo()method,whichisintheSystem.Reflectionnamespace.
Ifyoumustusereflection,thenitisbestnottoperformitrepeatedlyorinatightloop.However,itwouldbefinetouseitonceduringthestartupofyourapplication.Yet,ifyoucanavoidusingitentirely,youcanbenefitfromsomeofthenewimprovementsin.NETCore,forexample,nativecompilationandtheperformanceboostthatitbrings.
RegularexpressionsAregularexpression(regex)canbeveryuseful,butcanperformbadlyandistypicallymisusedinsituationswhereanothersolutionwouldbebetter.Forexample,aregexisoftenusedfore-mailvalidationwhentherearemuchmorereliablewaystodothis.
Ifreusingaregexrepeatedly,youmaybebetteroffcompilingitforperformancebyspecifyingtheRegexOptions.Compiledoptionintheconstructor.Thisonlyhelpsifyou'reusingtheregexalotandinvolvesaninitialperformancepenalty.So,ensurethatyoucheckifthereisactuallyanimprovementanditisn'tnowslower.
TheRegexOptions.IgnoreCaseoptioncanalsoaffectperformance,butitmayinfactslowthingsdown,soalwaystestforyourinputs.CompilinghasaneffectonthistooandyoumaywanttouseRegexOptions.CultureInvariantinaddition,toavoidcomparisonissues.
Bewaryoftrustinguserinputtoaregex.Itispossibletogetthemtoperformalargeamountofbacktrackinganduseexcessiveresources.Youshouldn'tallowunconstrainedinputtoaregex,astheycanbemadetorunforhours.
Regexesareoftenusedfore-mailaddressvalidation,butthisisusuallyabadidea.Theonlywaytofullyvalidateane-mailaddressistosendane-mailtoit.Youcanthenhavetheuserclickalinkinthee-mailtoindicatethattheyhaveaccesstothatmailboxandhavereceivedit.E-mailaddressescanvaryalotfromthecommononesthatpeopleareregularlyexposedto,andthisiseventruerwiththenewtop-leveldomainsbeingadded.
Manyoftheregexesfore-mailaddressvalidationfoundonlinewillrejectperfectlyvalide-mailaddresses.Ifyouwanttoassisttheuser,andperformsomebasice-mailaddressvalidationonaform,thenallyoucansensiblydoischeckthatthereisan@symbolinit(anda.afterthat)sothatthee-mailisintheformx@y.z.Youcandothiswithasimplestringtestandavoidtheperformancepenaltyandsecurityriskofaregularexpression.
StringconcatenationintightloopsAsstringsareimmutableandcan'tchange,whenyouconcatenateastring,anewobjectiscreated.Thiscancauseperformanceproblemsandissueswithmemoryuseifyoudoitalotinsideatightloop.
Youmayfinditbettertouseastringbuilderoranotherapproach.However,don'tfrettoomuchaboutthis,asitonlyappliesatalargescale.Alwaystesttoseeifitisgenuinelyaproblemanddon'tmicro-optimizewhereyoudon'tneedto.
It'sgoodgeneraladvicetoworkoutwhereyourcodeisspendingmostofitstime,andfocusyouroptimizationthere.It'sobviouslymuchbettertooptimizecodeexecutedmillionsoftimesinsidealoopthancodethatonlyrunsoccasionally.
DynamictypingC#isastaticallytypedlanguageandvariabletypesarecheckedatcompiletime,butitdoeshavesomedynamicfeatures.YoucanusethedynamictypeandobjectssuchasExpandoObjecttogetsomeofthefeaturesofadynamicallytypedlanguage.Thevartypeisnotinfactdynamic,andissimplyinferredatcompiletime.
Dynamictypinghasaperformanceandsafetypenalty,soitisbestavoidedifyoucanfindanotherwaytosolveyourproblem.Forexample,theViewBaginASP.NETMVCisdynamic,soitisbestnottouseViewBag,anduseawell-definedviewmodelinstead.Thishasmanyotherbenefitsapartfromperformance,suchassafetyandconvenience.
SynchronousoperationsSynchronousmethodsblockexecution,andshouldbeavoidedifpossible,especiallyiftheyaresloworaccessI/O.We'vecoveredasynchronous(asyncforshort)operationsinpreviouschapters.Understandinghowtouseasyncisimportantformodernhighperformanceprogramming,andnewlanguagefeaturesmakeitmoreaccessiblethanever.Ifanasyncmethodisavailable,thenitshouldgenerallybeusedinpreferencetothesynchronousblockingversion.
Theasyncandawaitkeywordsmakeasynchronousprogrammingmucheasierthanitusedtobe,but,ascoveredinChapter3,FixingCommonPerformanceProblems,theeffectsonwebapplicationsarenotalwaysvisibleforaloneuser.Theseconvenientfeaturesallowyoutoservemoreuserssimultaneouslybyreturningthreadstothepoolduringdowntime,whilewaitingforoperationstocomplete.Thethreadscanthenbeusedtoserviceotherusers'requests,whichallowsyoutohandlemoreuserswithlessserversthanotherwise.
Asyncmethodscanbeuseful,butthebiggainscomenotfromwritingasynchronouscode,butfromhavinganasynchronousarchitecture.Wewillcoverdistributedarchitectureinthenextchapter,whenwediscussmessagequeuing.
ExceptionsExceptionsshould,asthenamesuggests,bereservedforexceptionalcircumstances.Exceptionsareslowandexpensiveandshouldn'tbeusedasflowcontrolinbusinesslogicifyouknowthataneventislikelytooccur.
Thisisn'ttosaythatyoushouldn'tuseexceptionhandling–youshould.However,itshouldbereservedforeventsthataregenuinelyunexpectedandrare.Ifyoucanpredictaheadoftimethataconditionmayoccurthenyoushouldhandleitexplicitly.
Forexample,thediskbecomingfullandyourcodenotbeingabletowriteafilebecausethereisnospaceisanexceptionalsituation.Youwouldnotexpectthistonormallyhappen,andyoucanjusttrythefileoperationandcatchanyexceptions.However,ifyouaretryingtoparseadatestringoraccessadictionary,thenyoushouldprobablyusethespecialTryParse()andTryGetValue()methodsandcheckfornullvaluesratherthanjustrelyingonexceptionhandling.
SummaryInthischapter,wediscussedsometechniquesthatcanimprovetheperformanceofcodeexecutionanddugintotheprojectsthatmakeup.NETCoreandASP.NETCore.Weexploreddatastructures,serialization,hashing,andparallelprogrammingandhowtobenchmarkformeasuringrelativeperformance.
Linearperformancecharacteristicsareeasiertoscaleandcodethatdoesnotexhibitthisbehaviorcanbeslowwhentheloadincreases.Codethathasanexponentialperformancecharacteristicorhaserraticoutliers(whicharerarebutveryslowwhentheyoccur)cancauseperformanceheadaches.Itisoftenbettertoaimforcode,thatwhilebeingslightlyslowerinnormalcasesismorepredictableandperformsconsistentlyoveralargerangeofloads.
Themainlessonhereistonotblindlyapplyparallelprogrammingandotherpotentiallyperformance-enhancingtechniques.Alwaystesttomakesurethattheymakeapositiveimpact,astheycaneasilymakethingsworse.Weaimforthesituationwhereeverythingisawesome,but,ifwe'renotcareful,wecanmakeeverythingawfulbymistake.
Inthenextchapter,you'lllearnaboutcachingandmessagequeuing–twoadvancedtechniquesthatcansignificantlyimprovetheperformanceofasystem.
Chapter7.LearningCachingandMessageQueuingCachingisincrediblyusefulandcanbeappliedtoalmostalllayersofanapplicationstack.However,it'shardtoalwaysgetcachingworkingcorrectly,so,inthischapter,wewillcovercachingattheweb,application,anddatabaselevels.Wewillshowyouhowtouseareverseproxyservertostoretheresultsofyourrenderedwebpagesandotherassets.We'llalsocovercachingatlowerlevels,usinganin-memorydatastoretospeedupaccess.Youwilllearnhowtoensurethatyoucanalwaysflush(orbust)yourcacheifyouneedtoforcethepropagationofupdates.
Thischapteralsocoversasynchronousarchitecturedesignusingmessagequeuingandabstractionsthatencapsulatevariousmessagingpatterns.Youwilllearnhowtoperformalongrunningoperation(suchasvideoencoding)inthebackground,whilekeepingtheuserinformedofitsprogress.
Youwilllearnhowtoapplycachingandmessagequeuingsoftwaredesignpatternstoslowoperationssothattheydon'thavetobeperformedinrealtime.You'llalsolearnaboutthecomplexitythatthesepatternscanadd,andunderstandthetradeoffsinvolved.We'llseehowtocombatthesecomplexitiesandmitigatethedownsides,inChapter8,TheDownsidesofPerformance-EnhancingTools.
Thetopicscoveredinthischapterincludethefollowing:
WebcachingbackgroundJavaScriptserviceworkersVarnishproxyandIISwebserversRedisandMemcachedin-memoryapplicationcachingMessageQueuingandmessagingpatternsRabbitMQanditsvariousclientlibraries
WhycachingishardCachingishard,butit'snothardbecauseit'sdifficulttocachesomething.Cachingindefinitelyiseasy,thehardpartisinvalidatingthecachewhenyouwanttomakeanupdate.There'sawell-usedquotefromthelatePhilKarltonofNetscapethatgoes:
"ThereareonlytwohardthingsinComputerScience:cacheinvalidationandnamingthings."
Therearealsomanyhumorousvariantsonit,asusedpreviouslythroughoutthisbook.Thissentimentmaybeaslightexaggeration,butithighlightshowcomplexremovingyour"done-computer-stuffTM"fromyour"quick-things-box2.0TM"isperceivedtobe.Namingthingsisgenuinelyveryhardthough.
Cachingistheprocessofstoringatemporarysnapshotofsomedata.Thistemporarycachecanthenbeusedinsteadofregeneratingtheoriginaldata(orretrievingitfromthecanonicalsource)everytimeitisrequired.Doingthishasobviousperformancebenefits,butitmakesyoursystemmorecomplicatedandhardertoconceptualize.Whenyouhavemanycachesinteracting,theresultscanappearalmostrandomunlessyouaredisciplinedinyourapproach.
Whenyouarereasoningaboutcaching(andmessagequeuing),itishelpfultodispeltheideathatdataonlyexistsinasingleconsistentstate.Itiseasierifyouembracetheconceptthatdatahasafreshness,andisalwaysstalebysomeamount.Thisisinfactalwaysthecase,buttheshorttimeframesinvolvedinasmallsystemmeanthatyoucantypicallyignoreitinordertosimplifyyourthinking.However,whenitcomestocaching,thetimescalesarelongerandso,freshnessismoreimportant.Asystematscalecanonlybeeventuallyconsistent,andvariouspartsofitwillhaveadifferenttemporalviewofthedata.Youneedtoacceptthatdatacanbeinmotion,otherwiseyou'rejustnotthinkingfour-dimensionally!
Asatrivialexample,consideratraditionalstaticwebsite.Avisitorloadsapageintheirbrowser,butthispageisnowinstantlyout-of-date.Thepageontheservercouldhavebeenupdatedjustafterthevisitorretrievedit,buttheywillnotknow,astheoldversionwillremainintheirbrowseruntiltheyrefreshthepage.
Ifweextendthisexampletoadatabase-backedwebapplication,suchasanASP.NETorWordPresswebsite,thenthesameprincipleapplies.Auserretrievesawebpagegeneratedfromdatainthedatabase,butitcouldbeout-of-dateassoonasitisloaded.Theunderlyingdatacouldhavechanged,butthepagecontainingtheolddataremainsinthebrowser.
Bydefault,webappstypicallyregenerateHTMLfromtheDBforeverypageload,butthisisincrediblyinefficientifthedatahasnotchanged.Itisonlydonelikethissothatwhenachangeismade,itshowsupimmediatelyassoonasthepageisrefreshed.
However,ausermayhaveanoldpageintheirbrowser,andyouhavelimitedcontroloverthis.
Soyoumayaswellcachethispageontheserveraswellandonlyremoveitwhentheunderlyingdatainthedatabasechanges.CachingtherenderedHTMLlikethisisoftenessentialformaintainingperformanceatascalebeyondsimplyasmallnumberofusers.
WebcachingThefirstcategoryofcachingthatwe'lldiscussisattheweblevel.Thisinvolvesstoringthefinaloutputofyourwebstackasitwouldbesenttouserssothat,whenrequestedagain,it'sreadytogoanddoesn'tneedtoberegenerated.CachingatthisstageremovestheneedforexpensivedatabaselookupsandCPU-intensiverenderingattheapplicationlayer.Thisreduceslatencyanddecreasestheworkloadonyourservers,allowingyoutohandlemoreusersandserveeachuserrapidly.
Webcachingtypicallyoccursonyourwebserversoronreverseproxyservers,whichyouhaveputinfrontofyourwebserverstoshieldthemfromexcessiveload.Youmightalsochoosetohandthistaskovertoathirdparty,suchasaCDN.Herewewillcovertwopiecesofwebserverandproxyserversoftware,IISandVarnish.However,manymorewebcachingandloadbalancingtechnologiesareavailable,forexample,NGINXorHAProxy.
CachingattheweblayerworksbestforstaticassetsandresourcessuchasJavaScript,CSS,andimages.YetitcanalsoworkforanonymousHTMLthatisrarelyupdatedbutregularlyaccessed,suchasahomepageorlandingpage,whichisunauthenticatedandnotcustomizedforauser.
WetoucheduponproxyserversinChapter3,FixingCommonPerformanceProblems,andcoveredweblayercachingalittleinChapter4,AddressingNetworkPerformance.However,inthischapter,we'llgointomoredetailonwebcaching.
Cachingbackground
Beforewedelveintotheimplementationdetails,ithelpstounderstandalittleabouthowcachingworksontheweb.Ifyoutakethetimetostudythemechanismsatwork,thencachingwillbelessconfusingandlessfrustratingthanifyoujustdivedstraightin.
ItishelpfultoreadandunderstandtherelevantHTTPspecifications.However,don'tassumethatsoftwarealwaysstrictlyadherestothesewebstandardsevenifitclaimsto.
First,let'slookatatypicalnetworksetupwhichyoumaybetraversingwithyourHTTPtraffic.Thefollowingdiagramillustratesanexampleofacommonconfigurationforawebapplication:
Asseenintheprecedingdiagram,thelaptopandtabletusersareconnectingthroughacachingforwardproxyserver(whichmaybeonacorporatenetworkoratanISP).Themobileuserisconnectingdirectlyovertheinternet.However,allusersaregoingthroughaCDNbeforereachingyourinfrastructure.
Afteryourfirewall(notshown),thereisanappliancewhichterminatestheTLSconnections,balancestheloadbetweenwebservers,andactsasacachingreverseproxy.Thesefunctionsareoftenperformedbyseparatedevices,butwe'vekeptthingssimplehere.
Copiesofyourresourceswillbekeptonyourwebservers,yourreverseproxy,yourCDN,anyforwardproxies,andinthebrowsersonalluserdevices.Thesimplestwaytocontrolthecachingbehavioroftheseresourcesistousein-bandsignalingandaddHTTPheaderstoyourcontent,declaringcachecontrolmetadataonlyinasingleplace.
It'sgoodpracticetoapplythesamestandardHTTPcachingtechniquestoyourownwebserversandproxieseventhoughyoucouldcustomizethemandflushtheircachesatwill.Thisnotonlycutsdownontheamountofconfigurationthatyouhavetodo,andavoidsduplicatedwork,butitalsoensuresthatanycachesthatyoudon'tcontrolshouldbehavecorrectlytoo.EvenwhenusingHTTPS,thebrowserwillstillperformcachingandtheremayalsobetransparentcorporateproxiesormeddlingISPcaptiveportalsintheway.
HTTPheaders
HTTPcachinginvolvessettingcachecontrolheadersinyourresponses.Therearemanyoftheseheaders,whichhavebeenaddedovertheyearsfromdifferentstandardsandvariousversionsoftheprotocol.Youshouldknowhowtheseareused,butyoushouldalsounderstandhowtheuniquenessofacacheableresourceisdetermined–forexample,byvaryingtheURLorbyalteringonlyapartofit,suchasquerystringparameters.
ManyoftheseheaderscanbecategorizedbyfunctionandtheversionofHTTPthattheywereintroducedwith.Someheadershavemultiplefunctionsandsomearenon-standard,yetarealmostuniversallyused.Wewon'tcoveralloftheseheaders,butwewillpickoutsomeofthemostimportantones.
Therearebroadlytwotypesofcachingheadercategories.Thefirstdefinesanabsolutetimeduringwhichthecachecanbereused,withoutcheckingwiththeserver.Theseconddefinesruleswhichtheclientcanusetotestwiththeserverifthecacheisstillvalid.
Mostinstructionalheaders(thosethatissuecachingcommands)fitintooneofthesetwoheadercategories.Inadditiontothese,therearemanypurelyinformationalheaders,whichprovidedetailsabouttheoriginalconnectionandclient,whichmayotherwisebeobscuredbyacache(forexample,theoriginalclientIPaddress).
Someheaders,suchasCache-Control,arepartofthelateststandard,butothers,suchasExpires,aretypicallyusedonlyforbackwardscompatibility,incasethereisanancientbrowseroranoldproxyserverintheway.However,thispracticeisbecomingincreasinglyunnecessaryasinfrastructureandsoftwareisupgraded.
Note
ThelatestcachingstandardinthiscaseisHTTP/1.1asHTTP/2usesthesamecachingdirectives(RFC7234).SomeheadersdatefromHTTP/1.0,whichisconsideredalegacyprotocol.VeryoldsoftwaremayonlysupportHTTP/1.0.
Standardsmaynotbeimplementedcorrectlyinallapplications.Itisasensibleideatotestthatanyobservedbehaviorisasexpected.
TheAgeheaderisusedtoindicatehowlong(inseconds)aresourcehasbeeninacache.Ontheotherhand,theETagheaderisusedtospecifyanidentifierforanindividualobjectoraparticularuniqueversionofthatobject.
TheCache-Controlheadertellscachesiftheresourcemaybecached.Itcanhavemanyvaluesincludingamax-age(inseconds)orno-cacheandno-storedirectives.Theconfusing,yetsubtle,differencebetweenno-cacheandno-storeisthatno-cacheindicatesthattheclientshouldcheckwiththeserverbeforeusingtheresource,whereasno-storeindicatesthattheresourceshouldn'tbecachedatall.Topreventcaching,youshouldgenerallyuseno-store.
TheASP.NETCoreResponseCacheactionattributesetstheCache-ControlheaderandiscoveredinChapter4,AddressingNetworkPerformance.However,thisheadermaybeignored
bysomeoldercaches.PragmaandExpiresareolderheadersusedforbackwardcompatibilityandtheyperformsomeofthesamefunctionsthattheCache-Controlheadernowhandles.
TheX-Forwarded-*headersareusedtoprovidemoreinformationabouttheoriginalconnectiontotheproxyorloadbalancer.Thesearenon-standard,butwidely-used,andarestandardizedasthecombinedForwardedheader(RFC7239).TheViaheaderalsoprovidessomeproxyinformation,andFront-End-Httpsisanon-standardMicrosoftheader,whichissimilartoX-Forwarded-Proto.TheseprotocolheadersareusefulfortellingyouiftheoriginalconnectionusedHTTPSwhenthisisstrippedattheloadbalancer.
Tip
IfyouareterminatingtheTLSconnectionsataloadbalancerorproxyserver,andarealsoredirectinguserstoHTTPSattheapplicationlevel,thenitisimportanttochecktheForwardedheaders.YoucangetstuckinaninfiniteredirectionloopifyourwebserversdesireHTTPSbutonlyreceiveHTTPfromtheloadbalancer.Ideally,youshouldcheckallvarietiesoftheheaders,but,ifyoucontroltheproxy,youcandecidewhatheaderstouse.
TherearelotsofdifferentHTTPheadersthatareinvolvedincaching.Thefollowinglistincludessomeoftheonesthatwehaven'tcoveredhere.Thelargequantityofheadersshouldgiveyouanideaofjusthowcomplicatedcachingcanbe.
If-Match
If-Modified-Since
If-None-Match
If-Range
If-Unmodified-Since
Last-Modified
Max-Forwards
Proxy-Authorization
Vary
Cachebusting
Cachebusting(alsoknownascachebursting,cacheflushing,orcacheinvalidation)isthehardpartofcaching.Itiseasytoputaniteminacache,but,ifyoudon'thaveastrategyaheadoftimetomanagetheinevitablechange,thenyoumaycomeunstuck.
Gettingcachebustingcorrectisusuallymoreimportantwithweb-levelcaching.Thisisbecause,withserversidecaching(whichwe'lldiscusslaterinthischapter),youareinfullcontrolandcanresetifyougetitwrong.Amistakeonthewebcanpersistandbedifficulttoremedy.
Inadditiontosettingthecorrectheaders,itishelpfultovarytheURLofresourceswhentheircontentchanges.Thiscanbedonebyaddingatimestamp,butoftenaconvenientsolutionistouseahashoftheresourcecontentandappendthisasaparameter.Manyframeworks,includingASP.NETCore,usethisapproach.Forexample,considerthefollowingJavaScripttaginawebpage:
<scriptsrc="js/site.js"></script>
Ifyoumakeachangetosite.js,thenthebrowser(orproxy)won'tknowthatithasalteredandmayuseapreviousversion.However,itwillre-requestitiftheoutputischangedtosomethinglikethefollowing:
<scriptsrc="js/site.js?v=EWaMeWsJBYWmL2g_KkgXZQ5nPe-a3Ichp0LEgzXczKo">
</script>
Herethev(version)parameteristheBase64URLencoded,SHA-256hashedcontentofthesite.jsfile.Makingasmallchangetothefilewillradicallyalterthehashduetotheavalancheeffect.
Note
Base64URLencodingisavariantonstandardBase64encoding.Itusesdifferentnon-alphanumericcharacters(+becomes-while/changesto_)andpercentencodesthe=character(whichisalsomadeoptional).Usingthissafealphabet(fromRFC4648)makestheoutputsuitableforuseinURLsandfilenames.
InASP.NETCore,youcaneasilyusethisfeaturebyaddingtheasp-append-versionattributewithavalueoftrueinyourRazorviewslikeso:
<scriptsrc="~/js/site.js"asp-append-version="true"></script>
Serviceworkers
Ifyouarewritingaclient-sidewebapp,ratherthanasimpledynamicwebsite,thenyoumaywishtoexertmorecontrolovercachingusingnewbrowserfeatures.YoucandothisbywritingyourcachecontrolinstructionsinJavaScript(technicallyECMAScript6(ES6)).Thisgivesyoumanymoreoptionswhenitcomestoavisitorusingyourwebappoffline.
AserviceworkergivesyougreatercontrolthanthepreviousAppCacheAPI.Italsoopensthedoortofeaturessuchasmobilewebappinstallbanners(whichpromptausertoaddyourwebapptotheirhomescreen).However,itisstillarelativelynewtechnology.
Tip
Serviceworkersareanewexperimentaltechnology,andassuch,arecurrentlyonlysupportedinsomerecentbrowsers(partiallyinChrome,Firefox,andOpera).YoumayprefertousethepreviousdeprecatedAppCachemethod(whichisalmostuniversallysupported)untiladoptionismorewidespread.
Informationoncurrentbrowsersupportisavailableatcaniuse.com/#feat=serviceworkersandcaniuse.com/#feat=offline-apps(forAppCache).Amoredetailedserviceworkerbreakdownisavailableatjakearchibald.github.io/isserviceworkerready.
Aserviceworkercandomanyusefulthings(suchasbackgroundsynchronizationandpush
notifications),buttheinterestingparts,fromourpointofview,arethescriptablecaches,whichenableofflineuse.Iteffectivelyactsasanin-browserproxyserverandcanbeusedtoimprovetheperformanceofawebapplicationinadditiontoallowinginteractionwithoutaninternetconnection(afterinitialinstallation,ofcourse).
Note
Thereareothertypesofwebworkersapartfromserviceworkers(forexample,audioworkers,dedicatedworkers,andsharedworkers),butwewon'tgointothesehere.Allwebworkersallowyoutooffloadworktoabackgroundtasksothatyoudon'tmakethebrowserunresponsive(byblockingthemainUIthreadwithyourwork).
ServiceworkersareasynchronousandrelyheavilyonJavaScriptpromises,whichwe'llassumeyouarefamiliarwith.Ifyou'renot,thenyoushouldreaduponthem,asthey'reusefulinmanyothercontextsinvolvingasynchronousandparallelscripting.
ServiceworkersrequiretheuseofHTTPS(yetanothergoodreasontouseTLSonyourentiresite).However,thereisanexceptionforlocalhost,soyoucanstilldeveloplocally.
Serviceworkerexample
Toinstallaserviceworker,firstcreateafileforit(whichisservedoverHTTPS).Inthefollowingexample,thisfileiscalledservice-worker.js.Theninsidea<script>tagonyourHTMLpage(alsoservedoverHTTPS),addthefollowingJavaScriptcode:
if('serviceWorker'innavigator){
navigator.serviceWorker.register('service-worker.js',{
scope:'/'
});
}
Theprecedingcodesnippetfirstcheckstoseeifserviceworkersaresupported,andiftheyare,registersyourworker.Youcannowfetchresourcesandaddthemtothecache.Aninterestingperformanceenhancingusecaseforthisisprefetchingresources(thattheusermayneed)aheadoftimeandputtingtheminthecache.Scopeisanoptionalparameterandisn'tstrictlynecessaryinthiscase,asthefileisintherootofthedomain.We'veshownitonlytodemonstrateusage,butitmaybeusefultospecifythisifthefilewasinasubfolder.
Beforegoinganyfurther,youshouldcheckthatyourworkerhasbeeninstalledcorrectly.InChrome,youcanopenthespecialURLchrome://inspect/#service-workerstoseeanyactiveserviceworkers.Forexample,afteropeninginstabail.ukinonetab,youcanopentheserviceworkerinspectorinanother;youshouldseesomethinglikethefollowingscreenshot:
Youcanalsovisitchrome://serviceworker-internalsinChrometoseethestatusofallserviceworkersthathavebeenregistered,evenifthesitesaren'tstillopen.Forexample,evenafterclosinginstabail.ukyoushouldcontinuetoseesomethinglikethefollowingscreenshot:
YoucanremoveserviceworkersbyclickingtheUnregisterbutton.Iftheserviceisrunning,youwillhaveStopandInspectbuttonsinplaceofStart.ThispagemayberemovedormergedintotheinspectorinafutureversionofChrome.
Tip
IfyouareusinganolderversionofChrome(earlierthan50),youmayseeanerror(net::ERR_FILE_EXISTS)againstyourserviceworkerfileintheconsole;butthisisfine,sodon'tworry.It'ssimplyabuginChromeasittriestoupdateyourserviceworker,butfindsthattherearen'tanychanges.
NowyoucanstartaddingcontenttoyourserviceworkerJavaScriptfile.Wefirstneedtoinstalltheworkerandcachesomefiles,whichisdonewithaneventlistener,asshowninthefollowingcode:
self.addEventListener('install',function(event){
event.waitUntil(
caches.open('cache-v01').then(function(cache){
returncache.addAll([
'/',
'/Content/bootstrap.min.css'
]);
})
);
});
Wehavenamedourcachecache-v01,andprovidedanarrayofresourcestocache.Youwouldprobablyhavemoreentrieshereanddefinethearrayoutsideofthefunction,butwehavekeptthingssimplehereforclarity.
Tip
Don'tcacheyourhomepageifitdynamicallyrenderslivecontent.Youmayalsowanttousecachebustingparametersforresources,asmentionedpreviously.
Wecanthenaddafetcheventlistenertoperformthemagicofcachingandfetchingresources.
self.addEventListener('fetch',function(event){
event.respondWith(
caches.match(event.request)
.then(function(response){
if(response)returnresponse;
varmyReq=event.request.clone();
returnfetch(myReq).then(
function(response){
varmyResp=response.clone();
caches.open('cache-v01')
.then(function(cache){
cache.put(event.request,myResp);
});
returnresponse;
}
);
}
)
);
});
Firstwecheckiftherequestedresourceisinthecacheandifitis,wereturnthis.Withpromises,youcanchainthethenfunctionstogetherandfallthroughthem.Ifthereisacachemissduetotheresourcenotbeinginthecache,weperformafetchtoourservertogettheresourceandreturnthis.Wethenaddtheresourcetotheothersbyputtingitinthesamecache.Weclonetherequestandresponse,becausetheyarestreamsandcanonlybeconsumedonce.
Note
ThefetchfunctionisthemodernversionofanXMLHttpRequest(XHR)andisusedtoretrievedataoverthenetwork.Youcan'tuseasynchronousXHRinsideofaserviceworker,asthey'redesignedtobeasynchronous.
Youcaninspectyourserviceworkerandthecachesinmoredetailbyusingthebrowserdevelopertools(F12).OntheResourcestab,selectServiceWorkersandyouwillseesomethinglikethefollowingscreenshot:
IfyouselectCacheStorage,youwillseethecontentsofthecache,whichwilllooksomethinglikethefollowing:
Youcanrefreshthecacheanddeleteitemsbyrightclicking.TheApplicationCache,aboveCacheStorage,wouldshowthedeprecatedAppCacheresources.Asyounavigatearound,yoursitepageswillbeaddedtothecache(thesepagesshouldbesuitableforcaching,astheywon'tberequestedfromtheserverafterthisifusingourdemocode).Afterthis,onceyourefreshthecacheview,youshouldseemoreentrieslisted,whichmaylooksomethinglikethefollowingscreenshot:
Youcanseethatthecacheentriesarelistedalphabeticallyandnotintheorderinwhichtheywereaddedtothecache.Thesepageswillnowbeasnapshot,fixedatthepointintimethattheywereretrieved.Thismaynotbethefunctionalitythatyouwant!
Forsimplicity,theserviceworkerthatwe'vebuilthereisatrivialexampleandyouwouldlikelywanttoexpandittoatleasthandlethecasewherethenetworkfetchfailsbyaddingacatchstatement.Forexample,youcouldserveapreviouslycachedofflinefallbackpageinitsplace.Youshouldalsocheckthatyou'renotcachingerrorpagesfromtheserver,sotesttheresponsestatuscode.
Youalsoneedtocarefullyconsideryourcacheinvalidationstrategy.Serviceworkersgiveyouthetoolstobuildthis,astheydon'tmakeasmanyassumptionsastheHTML5AppCachedid.Forexample,youcannowprogrammaticallydeleteentriesfromthecache.
We'llleaveithereforclient-sidescriptcontrolledcaching,butyoumaywanttolookintothisinmoredetail,especiallyoncethespecificationhasstabilizedandbrowsersupportismorewidespread.TherearemanyothernewfeaturesnowavailableinJavaScript,whichmakeasyncprograminglikethiseasierthanitusedtobe.Forexample,arrowfunctions,whicharesimilartoLINQlambdaexpressionsinC#.
Webandproxyservers
Cachingfromaserver'spointofviewisintimatelylinkedtoclient-sidecachinginthebrowser.In
additiontostoringresourcesontheserver,theheadersthatyousetwillbeusedtocontrolcacheseverywhere.
TheHTTPheadersthatyousetareusedbybothproxyserversandbrowsers,includingnotonlystandardbrowsing,butalsofetchingfromaserviceworker.Forexample,iftheCache-Controlheaderspecifiesno-store,thenyouwon'tbeabletoaddtheresourcetoacachefromyourworker.
IIS
InternetInformationServices(IIS)isMicrosoft'swebserver.ItcanbeusedtoservecontentfromyourASP.NETapplicationorasaproxyserveralongwithmanyotherthingssuchasFTP.AlthoughIISdoessupportoutputcaching,theOutputCacheactionattributeisnotavailableinASP.NETCore.Yet,youcanuseResponseCachetosetthecorrectheadersinstead,ascoveredinChapter4,AddressingNetworkPerformance.
IIScanalsobeusedasaproxy,forexample,infrontoftheKestrelwebserveronasinglemachine.However,whencachingformultiplewebservers,youmaybebetteroffusingdedicatedproxyserversoftwaresuchasVarnish.
Varnish
VarnishisafreereverseproxyserverthatrunsonUnix-likeoperatingsystemssuchasLinuxandFreeBSD.Youcaninstallitwithyourpackagemanager(forexample,aptoryum)orprovisionaproxyserverwithDevOpssoftwaresuchasCheforPuppet.ToconfigureVarnish,youuseadomain-specificlanguage(DSL)calledVarnishConfigurationLanguage(VCL).
Note
YoucanreadmoreaboutVarnishatvarnish-cache.org.
Youshouldn'tneedtoconfigureVarnishtoomuchifyouareusingHTTPcachingheaderscorrectly.YoucanalsousethecustomHTTPPURGEmethodtoremoveentriesfromthecache,whichworkswiththeSquidproxysoftwaretoo.YoumayoccasionallyseeacrypticgurumeditationerrorifVarnishisnotproperlyconfigured,butyoushouldbeabletotrackdowntheissueintheVarnishlogs.Itcouldindicatethatnohealthywebserversareavailable.
Varnishconfigurationisbeyondthescopeofthisbook,butit'sverywelldocumentedontheVarnishwebsite.Ifyoudon'twanttorunyourownproxyserver,thenyoucoulduseaCDN.YoumaystillwantyourownproxyinadditiontousingaCDN,aslargeCDNs,withmanypointsofpresence(PoP),mightrequestthesameresourceviaeachPoP,andnotshareassetsacrossthem.Thiscanbeanissueifyoupayalotforbandwidth,althoughsomeCDNshaveafeature(oftencalledoriginshielding)thatcanhelpwiththis.
Workingwithacontentdeliverynetwork
Acontentdeliverynetworkiscommonlyusedintwoways–asaproxyforoffloadingyourcontent
orasahostingproviderforcommonthirdpartylibrariesandframeworks.YoucanuseadynamicCDNservice,suchasCloudFlareorAkamai,forthefirstusecase,butthesecondsituation(usingastaticCDNfromGoogleorMicrosoft)ismorecommonandthat'swhatwe'llcoverhere.
AlthoughusingaCDNforyourlibraries,suchasjQueryandTwitterbootstrap,isbecominglessusefulwiththeadoptionofHTTP/2,itcanstillbehelpfulforreducingyourhostingcosts.IfyouuseapopularCDNandlibrary,thentheusermayalsoalreadyhaveacopy.Forexample,iftheuserhasbeentoanothersitethatusesjQueryfromGoogle'sCDN,thenitwillalreadybeintheirbrowsercache.
ItisessentialtohaveafallbackcopyofwhateverfilesyourequirefromaCDN.ThisiseasierthaneverwiththeRazorviewenginesupportbuiltintoASP.NETCore.
ThefollowingcodeshowshowjQueryisincludedinthedefaultMVCRazorlayout,fornon-developmentenvironments.BoththeCDNandlocalversionsarespecifiedalongwithatest.
<script
src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
Theprecedingcodesnippetnotonlyrendersthestandard<script>tagfortheMicrosoftCDN,butalsoaddsthefollowinginlineJavaScriptafterwards,whichincludesthelocalversioniftheCDNloadfails:
(window.jQuery||document.write(
"<scriptsrc="\/lib\/jquery\/dist\/jquery.min.js"><\/script>"));
Previously,youwouldhavetodothismanually,usuallyinahurrywhenyourCDNwentdown.ThisnewhelperalsoworksforotherscriptsandCSSfiles.Formoreexamples,takealookat_Layout.cshtmlinthedefaulttemplate.
Tip
It'simportanttouseasecureHTTPSconnectiontoCDNresourcesinordertoavoidmixedcontentwarningsorscriptloadingerrorsinbrowsers;mostpopularCDNsnowsupportHTTPS.ForadditionalinformationonCDNs,seeChapter4,AddressingNetworkPerformance.
Whennottocache
Therearecertainsituationswhenyoushouldn'tcachepagesoratleastyouneedtobeverycarefulinhowyougoaboutit.Asageneralruleofthumb,cachingtherenderedoutputofanauthorizedpageisabadidea.Inotherwords,ifauserhasloggedintoyoursite,andyouareservingthemcustomizedcontent(whichcouldeasilybesensitive),thenyouneedtoconsidercachingverycarefully.
Ifyouaccidentallyserveoneuser'scachedcontenttoanother,thenatbest,itwillbeannoying,as
thepersonalizationwillbeincorrect.Atworst,youcouldexposeprivateinformationtothewrongpersonandpotentiallygetintolegaltrouble.
Note
ThisissimilartothegeneralruleofnotuniversallyenablingCORSifyouserveauthenticatedcontent.Itcanbedonesuccessfully,butyouneedtounderstandthemechanismsinordertoconfigureittoworksafely.
Forcaching,youwouldneedauniqueidentifierintheURLthatcan'tbeguessed.Somedynamiccachecontrolsystems,usedbynetworkappliancesandCDNs,canmakeuseofcookiesforthis,butit'sbeyondnormalHTTP-basedcachecontrol.Itissimilartohowyoumightneedstickysessionsonaloadbalancer,becauseyourapplicationwasnotdesignedtobestateless.
Forauthenticatedcaching,itmaybebettertonotcacheattheweblevelandinsteadcacheattheapplicationlevelandbelow.Thisallowsyoutocachesmallerdiscretechunksratherthanawholepage,whichcanenhancereusability.
ApplicationlayercachingApplicationlevel(orlayer)cachingmeansstoringreusabledatatemporarilyinsideyourinfrastructure,butnotinthemaindatabase.Thiscanbeinthememoryofyourapplicationorwebservers,butwithmultipleservers,thistendstobeinadistributedin-memorystoresuchasMemcachedorRedis.
Youcan,ofcourse,usebothin-memorystoresonyourwebserversandacentralizedcache.However,ifyouhavemultiplewebservers,thenyouwillneedawaytosynchronizethecaches.Youcanusepublish-subscribe(pub/sub)messagingforthis,whichwewillcoverlaterinthischapter.
Thefollowingdiagramshowsasimplecentralizedcachingsetup.Inarealsituation,youwouldprobablyhavemultipleclusteredcacheservers.
Thewebserverscannowaskthecacheifthedatatheyneedisinthere,beforegoingtothedatabase.ThisreducesloadontheDBandisoftenquicker,asthedatawillbeinmemoryifpresent.Ifthereisacachemissandthedatabasedoesneedtobequeried,thentheresultcanbewrittentothecacheforotherserverstouse.
Redis
Redisisapopularin-memorystorethatcanalsopersistdatatodiskforpermanentstorage.ItrunsbestonLinux,butaversionisavailableonWindowsfordevelopmentpurposes.Redisadditionallysupportspub/submessaging,whichcanbeusefulforcacheinvalidation.YoucanreadmoreaboutRedisatredis.io.
YoumaywishtousetheWindowsversionofRedisforlocaldevelopmentwork,butstilldeploytothesupportedversiononLinux.YoucangettheWindowsversionatgithub.com/MSOpenTech/redisoryoucouldruntheLinuxversioninavirtualmachine,perhapsusingDockerorVagrant.
RediscacheisprovidedasaserviceonbothAzureandAWS(ElastiCacheoffersbothMemcachedandRedis).Youdon'tneedtomanageyourownserver,butbecausethetechnologyisnotcloud-specific,youwon'tgetlockedinifyouwanttomigrateinthefuture.
AsRediskeepstheentiredatasetinmemory,but,isalsoabletopersisttodisk,itcanbesuitableasaprimarydatastoreunlikeMemcached.However,itismorecommonlyusedonlyasacache,especiallyifacloudserviceisusedandit'spairedwithaclouddatabasesuchasAzureSQLDatabaseorAWSRelationalDatabaseService(RDS).
Therearetworecommended.NETC#clientsforRedisa–ServiceStack.RedisandStackExchange.Redis.TheStackExchangeclientisusedheavilyonsitessuchasStackOverflowandiseasiertousecorrectlythanthetheServiceStackone.Youcanreadmoreaboutitatgithub.com/StackExchange/StackExchange.RedisandinstallitviaNuGet.
Ifusingcachingattheapplicationlayer,thenyouwillprobablyneedtowriteasignificantamountofcustomcode.Youwillalsoneedtoworkoutwhatformattoserializeyourdataintoforstorageinthecache.Ifservingdirectlytobrowsers,thenJSONcouldbeuseful.Butifistobeusedinternally,thenyoumaypreferabinaryformatsuchasMSBondorProtocolBuffers.
Tip
SeeChapter6,UnderstandingCodeExecutionandAsynchronousOperations,formoreonserializationformatsandlibraries.
Databaseresultsetcaching
Cachingatthedatabaselevelissimilartoapplicationlevelcaching,anditusessimilarinfrastructure,butrequireslesscustomcode.YoucanusethecachingfeaturesbuiltintoanO/RM,whichmaymakeiteasiertoretrofit.
Note
Whenwetalkaboutdatabasecachinghere,wearenotreferringtocachingwithinthedatabaseengineitself.DBsuseextensiveperformanceenhancingtechniques,suchasquerycaching,and
holdlotsoftheirdatainmemory.However,thisisabstractedawayfromthedeveloper,andthecachingwementionherereferstostoringtheoutputofaqueryinanapplicationcache.Thisissimilarto,butsubtlydifferentfrom,theprevioussection,whereyouwouldbestoringcustomobjects.
InthecontextofO/RMs(suchasNHibernateandEntityFramework),thisisknownassecond-levelcaching.Firstlevelcachinggenerallyalreadyhappenspersession,bydefault,andisusedtohelpavoidthingslikeSelectN+1problems.Second-levelcachingoperatesatalevelhigherthanindividualtransactionsandallowsyoutosharecacheddataacrossmultipledatabasesessionsoveryourentireapplication.
MessagequeuingAmessagequeue(MQ)isanasynchronousandreliablewayofmovingdataaroundyoursystem.Itisusefulforoffloadingworkfromyourwebapplicationtoabackgroundservice,butcanalsobeusedtoupdatemultiplepartsofyoursystemconcurrently.Forexample,distributingcacheinvalidationdatatoallofyourwebservers.
MQsaddcomplexityandwewillcovermanagingthisinChapter8,TheDownsidesofPerformance-EnhancingTools.However,theycanalsoassistinimplementingamicroservicesarchitecturewhereyoubreakupyourmonolithintosmallerparts,interfacedagainstcontracts.Thiscanmakethingseasiertoreasonaboutwithinlargeorganizations,wheredifferentteamsmanagethevariouspartsoftheapplication.Wewilldiscussthisinmoredetailinthenextchapter,asqueuesaren'ttheonlywayofimplementingthisstyleofarchitecture.Forexample,HTTPAPIscanalsobeusedtodothis.
CoffeeshopanalogyIfusingMQs,thenyoumayneedtoimplementextrareconciliationlogicforerrorsoccurringinthebackground.Thisisbestexplainedwithacoffeeshopanalogy.
Ifyoupurchaseatakeawaycoffee,perhapsinabranchofapopularmultinationalchainoffranchisedcaffeinatedbeverageoutlets(thatdislikespayingtax),thenyourdrinkispreparedasynchronouslytothepaymentprocessing.Typically,youplaceyourorderandabaristawillstarttoprepareyourcoffee,beforeyouhavepaidforit.Additionally,youwillnormallypaybeforereceivingyourdrink.Therearemanythingsthatcouldgowronghere,buttheyarerareenoughfortheextracosttobeworthit,asitspeedsuptheordinaryworkflow.
Forexample,youmayfindthatyouareunabletopayafterplacingyourorder,butthecoffeecreationprocesshasalreadybegun.Thiswouldresultinwastedstock,unlessthereisanothercustomerwaitingwhomitcouldbeusedfor.Orperhaps,afteryouhavepaid,thebaristadiscoversthatakeyingredientforyourorderismissing.Theycouldeitherofferyouarefund,ornegotiateadifferentdrink.
Althoughmorecomplex,thisprocessisclearlysuperiortoperformingtheactionsinseries.Ifyouhadtodemonstratethatyouhadthemeanstopay,yourdrinkwasmade,andthenyoucompletedpaying,onlyonecustomercouldbeservedatatime.Assumingthereareenoughstaff,paymentprocessinganddrinkpreparationcanbeperformedinparallel,whichavoidsalongqueueofcustomers.
Runningacoffeeshopinthiswaymakesintuitivesenseandyet,inawebapplication,itiscommontohavearelativelylongrunningtransactioncompletebeforeinformingtheuseroftheresult.Insomesituations,itmaybebettertoassumetheactionwillsucceed,informtheuserofthisimmediatelyandhaveaprocessinplaceincaseitgoeswrong.
Forexample,paymentprocessinggatewayscanbeslowandunreliable,soitmaybebettertochargeauser'screditcardafteracceptinganorder.However,thismeansthatyoucannolongerhandleafailurebyshowingtheuseranerrormessage.Youwillhavetouseothermethodsofcommunication.
WhenyouorderitemsonAmazon,theytakepaymentdetailsimmediately,buttheyprocessthepaymentinthebackgroundandsendyoue-mailswiththeresults.Ifthepaymentfailed,theywouldneedtocanceltheorderfulfilmentandnotifyyou.Thisrequiresextralogic,butisquickerthanprocessingthepaymenttransactionandcheckingstockbeforeconfirmingtheorder.
MessagequeuingstylesThereare,broadly,twostylesofmessagequeuing–withandwithoutacentralbroker.Withabroker,allmessagesgothroughahub,whichmanagesthecommunication.ExamplesofthisstyleincludeRabbitMQ,ActiveMQ,andMSBizTalk.
Therearealsobrokerlessstyles(thatdon'tuseabroker),wherecommunicationbetweennodesisdirect.AnexampleofthisstyleincludesZeroMQ(ØMQ),whichhasanativeC#portcalledNetMQ.
Cloudqueuingservices,includingAzureServiceBus,AzureQueuestorage,andAWSSimpleQueueService(SQS),arealsoavailable.However,aswithallnon-genericcloudservices,youshouldbewaryofgettinglockedin.TherearecloudprovidersofstandardRabbitMQhosting,whichmakesmigrationtoyourowninfrastructureeasierdownthelineifyoudon'tinitiallywanttorunyourownserver.Forexample,CloudAMQPoffersRabbitMQhostingonmultiplecloudplatforms.
RabbitMQimplementstheAdvancedMessageQueuingProtocol(AMQP),whichhelpstoensureinteroperabilitybetweendifferentMQbrokers,forexample,toallowcommunicationwiththeJavaMessageService(JMS).AzureServiceBusalsosupportsAMQP,butabigbenefitofRabbitMQisthatyoucaninstallitonyourdevelopmentmachineforlocaluse,withoutaninternetconnection.
ThereisalsoMicrosoftMessageQueuing(MSMQ),whichisbuiltintoWindows.Whilethisisusefulforcommunicationbetweenprocessesonasinglemachine,itcanbetrickytogetitworkingreliablybetweenmultipleservers.
CommonmessagingpatternsTherearetwotypesofcommonmessagingpatterns:point-to-pointunicastandpublish-subscribe.Thesesendmessagestoasinglerecipientandmanyrecipientsrespectively.
Unicast
Unicastisthestandardmessagequeuingapproach.Amessageissentfromoneserviceprocessorsoftwareagenttoanother.Thequeuingframeworkwillensurethatthishappensreliablyandwillprovidecertainguaranteesaboutdelivery.
Thisapproachisdependable,butdoesn'tscalewellasasystemgrows,becauseeachnodewouldneedtoknowaboutallitsrecipients.Itwouldbebettertolooselycouplesystemcomponentstogethersothattheydon'tneedtohaveknowledgeaboutanyoftheothers.
Thisisoftenachievedbyusingabroker,whichhasthreemainadvantages:
Byusingabroker,youcandecoupleprocessesfromeachothersothattheyaren'trequiredtoknowaboutthesystemarchitectureorbealiveatthesametime.Theyonlycareaboutthemessagetypesandthebrokertakescareofroutingthemessagetothecorrectdestination.Brokerqueuesenableaneasydistributionofworkpattern,especiallywhencombiningmultipleproducers.Youcanhavemultipleprocessesconsumingthesamequeueandthebrokerwillallocatemessagestotheminaround-robinfashion.Thisisasimplewayofbuildingaparallelsystem,withouthavingtodoanyasynchronousprogrammingorworryingaboutthreads.Youcanjustrunmultiplecopiesofyourcode,perhapsonseparatemachinesifconstrainedbyhardwareandtheywillrunsimultaneously.Youcaneasilybroadcastormulticastaparticulartypeofmessage,perhapstoindicatethataneventhasoccurred.Otherprocessesthatcareaboutthiseventcanlistentothemessageswithoutthepublisherknowingaboutthem.Thisisknownasthepub/subpattern.
Pub/sub
Pub/sub,asthenamesuggests,iswhereasoftwareagentpublishesamessageontoaqueue,andotheragentscansubscribetothattypeofmessagetoreceiveit.Whenamessageispublished,allsubscribersreceiveit,butcruciallythepublisherdoesnotrequireanyknowledgeofthesubscribersorevenneedtoknowhowmanythereare(orevenifthereareanyatall).
Pub/subisbestdonewiththebrokerstyleofmessagequeuingarchitecture.Itcanbedonewithoutabroker,butitisnotparticularlyreliable.Ifyourusecasecantoleratemessageloss,thenyoumaybeabletogetawaywithoutabroker.But,ifyourequireguaranteeddelivery,thenyoushoulduseone.UsingtheRabbitMQbrokeralsoallowsyoutotakeadvantageofexchangeswhichcanperformcomplexroutingofmessages.
Ifyoudon'twanttolosemessages,thenyouneedtocarefullydesignyourpub/subsystem(evenifusingabroker).Apublishedmessagethathasnosubscribersmaysimplydisappearintotheetherwithoutatraceandthismightnotbewhatyouwant.
Thefollowingdiagramshowsthedifferencesbetweensimplemessageforwarding,workdistribution,andpub/sub:
Clearly,ifyourequireareliablebroker,thenitneedstobehighlyavailable.Typically,youwouldclustermultiplebrokerstogethertoprovideredundancy.Usingabrokeralsoallowsyoutowritecustomrulestodefinewhichsubscribersreceivewhatmessages.Forexample,yourpaymentsystemmayonlycareaboutorders,butyourloggingservermaywanttogetallmessagesfromallsystems.
Youwillwanttomonitornotonlyyourbrokerserversbutalsothelengthofthequeues.Inother
words,thenumberofmessagesineachqueueshouldalwaysbesteadyandclosetozero.Ifthenumberofmessagesinaqueueissteadilygrowing,thismightindicateaproblemwhichyouroperationsteamwillneedtoresolve.Itmaybethatyourconsumerscan'tprocessmessagesfasterthanyourproducersaresendingthemandyouneedtoaddmoreconsumers.ThiscouldbeautomatedandyourmonitoringsoftwarecouldSpin-upanextrainstancetoscaleyoursystem,meetingatemporaryspikeindemand.
RabbitMQRabbitMQisafreeandopensourcemessagequeuingserver.It'swritteninErlang,whichisthesamerobustlanguagethatWhatsAppusesforitsmessagingbackend.
RabbitMQiscurrentlymaintainedbyPivotal(whoselabsalsomakethePivotalTrackeragileprojectmanagementtool),butitwasoriginallymadebyLShift.ItwasthenacquiredbyVMwarebeforebeingspunoutasajointventure.It'sdistributedundertheMozillaPublicLicense(MPL)v1.1,anolderversionofthelicensethattheFirefoxwebbrowseruses.
ThemessagingservercanbeusedfrommanydifferentlanguagesandframeworkssuchasJava,Ruby,and.NET.Thiscanmakeithelpfulforlinkingdiverseapplicationstogether,forexample,aRailsappthatyouwanttointerfacewithanASP.NETCoreapporC#service.
Note
YoucanreadmoreaboutRabbitMQanddownloadbuildsfromrabbitmq.com.
RabbitMQismoremodernthansystemssuchasMSMQandincludesfeaturessuchasanHTTPAPIandawebadminmanagementinterface.AlongwithHTTPandAMQP,italsosupportsSimpleTextOrientatedMessagingProtocol(STOMP)andMQTT,whichisusefulforlightweightInternetofThings(IoT)hardwareapplications.AlloftheseprotocolsimproveinteroperabilitywithothermessagingsystemsandtheycannormallybesecuredusingstandardTLS.
Thewebmanagementinterfaceshowsyouhowmanymessagesareflowingthroughyourqueues,andhowtheyareconfigured.Italsoallowsyoutoadministeryourqueues(taskssuchaspurgingordeletingmessages)andlookssomethinglikethefollowingscreenshot:
QueuingframeworksandlibrariesYouwilltypicallywanttouseaprebuiltclientlibraryorframeworktointeractwithyourmessagequeues.Thereareofficiallibrariesinmanydifferentlanguagesforthevariousqueuingsystems,whichofferlow-levelaccess.Forexample,RabbitMQhasanofficial.NET/C#clientlibrary.
However,therearealsootheropinionatedclientsandframeworks,whichofferahigherlevelofabstractionforcommonmessagingtasks.Forexample,NServiceBus(NSB),whichsupportsRabbitMQ,MSMQ,SQLServer,andAzure,isacommercialoffering.
AfreealternativetoNSBisMassTransit(masstransit-project.com),whichisalightweightservicebusanddistributedapplicationframework.IthasalsospunoutthesuperconvenientTopshelfframework(topshelf-project.com),whichmakescreatingWindowsservicesreallyeasy.Neitheryetrunson.NETCore,butsupportforbothoftheseprojectsisinprogress.
OneinterestingfeatureofMassTransit(andNSB)issupportforsagas.Asagaisacomplexstatemachinethatallowsyoutomodelthestoryofanentireworkflow.Ratherthandefiningindividualmessagesanddocumentinghowtheyallfittogether,youcanimplicitlycapturethegoldenpathanderrorflowswithinasaga.
ThereisalsotheexcellentopensourcelibraryEasyNetQ,whichmakesimplementingpub/subonRabbitMQtrivial.YoucanreadaboutitatEasyNetQ.com.Unfortunately,neithertheofficialRabbitMQclientnorEasyNetQsupport.NETCoreatthetimeofwriting.However,workisinprogressfortheofficialclientandEasyNetQhastheissuelogged.
TheRabbitMQteamisworkingonanew,asynchronousofficial.NETclient,whichwillonlytarget.NETCoreandtheTaskParallelLibrary(TPL).WecoveredtheTPL,whichispartoftheparallelextensionsthatalsoincludePLINQ,inChapter6,UnderstandingCodeExecutionandAsynchronousOperations.
Hopefully,bythetimeyoureadthis,thingswillhavestabilizedandyouwillbeabletouseRabbitMQwith.NETCore.Otherwise,youcanusethetraditional.NETFramework,whichmaycurrentlybemoresuitablefortheenterprisestyleapplicationsthatnormallyrequiremessagequeuing.
However,youcouldlookintousingRestBus,whichisaRabbitMQlibrarythatsupportsASP.NETCore.Youcanreadmoreaboutitatrestbus.org;italsosupportsbothWebAPIandServiceStack.
Note
Libraryandframeworksupportfor.NETCoreandASP.NETCorecanchangerapidly,socheckANCLAFS.comforthelatestinformation.Feelfreetohelpoutandcontributetothislistortoanyoftheopensourceprojectsthatneedporting.
SummaryInthischapter,wehaveinvestigatedthevarioustoolsandmethodsusedforcachingandmessagequeuing.Thesetwotechniquesofferdifferentwaysofimprovingtheperformanceofyoursystembymovingdatatootherlocationsandnothavingonemassivemonolithdoeverything.
Thesearebothadvancedtopicsanddifficulttocoverinsuchasmallspace.Hopefully,youhavebeenintroducedtosomefreshideasthatcanhelpyouwithsolvingproblemsinoriginalways.Ifyouhavediscoveredanewtechnologythatyouthinkwillassist,you'reencouragedtoreadthedocumentationandspecificationsforalloftheimplementationdetails.
However,beforeyoudivein,youshouldunderstandthatadvancedtechniquesarecomplexandhavedownsides,whichcanreduceyourdevelopmentspeed.Inthenextchapter,we'lllearnaboutthesedownsidesanddiscoverapproachesformanagingcomplexitysuchasmicroservices.
Chapter8.TheDownsidesofPerformance-EnhancingToolsAlotofthetopicsthatwecoveredinthisbookimproveperformanceatacost.Yourapplicationwillbecomemorecomplicatedandhardertounderstandorreasonabout.Thischapterdiscussesthesetrade-offsandhowtomitigatetheirimpact.
Youshouldimplementmanyoftheapproachesthatyoulearnedsofarinthisbookonlyifyourequirethemandnotjustbecausetheyareinterestingorchallenging.It'softenpreferabletokeepthingssimpleiftheexistingperformanceisgoodenough.
Youwilllearnhowtomakepragmaticchoicesaboutwhattechnologiesandtechniquesyoushoulduse.You'llalsoseehowtomanagethecomplexitiesifyouchoosetouseadvancedmethods.
Topicscoveredinthischapterincludethefollowing:
ManagingcomplexitywithframeworksandarchitectureBuildingahealthyculturetodeliverhighperformanceDistributeddebuggingandperformanceloggingUnderstandingstatisticsandstaledata
Manybooksandguidesonlyfocusonthepositivesofnewtoolsandframeworks.However,nothingcomesforfree,andthereisalwaysapenalty,whichmaynotbeimmediatelyobvious.
Youmaynotfeeltheeffectsofthechoicesthatyoumake,particularlyintechnicalarchitecture,foralongtime.Youmightnotdiscoverthatadecisionwasbaduntilyoutrytobuildonit,perhapsyearslater.
ManagingcomplexityOneofthemainproblemswithperformance-enhancingtechniquesisthattheytypicallymakeasystemmorecomplicated.Thiscanmakeasystemhardertomodifyanditmayalsoreduceyourproductivity.Therefore,althoughyoursystemrunsfaster,yourdevelopmentisnowslower.
Wecommonlyfindthiscomplexityprobleminenterprisesoftware,althoughusuallyfordifferentreasons.Typically,manyunnecessarylayersofabstractionareused,supposedlytokeepthesoftwareflexible.Ironically,thisactuallymakesitslowertoaddnewfeatures.Thismayseemcounterintuitive,untilyourealizethatsimplicitymakeschangeeasier.
Note
There'sasatiricalenterpriseeditionofthepopularprogrammerinterviewcodingtestFizzBuzz,whichisavailableatfizzbuzz.enterprises.It'sgoodinspirationforhownottodothings.
Ifyoudon'tneedafeatureyet,thenit'softenbesttoleaveitoutratherthanbuildingitjustincaseyoumightneeditinthefuture.Themorecodeyouwrite,themorebugsitwillhave,andtheharderitwillbetounderstand.Over-engineeringisacommonnegativepsychologicaltraitthatiseasytofallvictimtoifyouaren'tawareofit,andmarketersoftenexploitthis.
Foranon-softwareexample,four-wheeldriveSUVsaresoldtopeoplewhowillneverneedtheiroff-roadcapabilitiesonthefalsepremisethatitmaypotentiallycomeinusefulsomeday.Yetthefinancial,safety,environmental,andparkingconveniencecostsoutweighthissupposedbenefitbecauseit'sneverused.
Weoftentermthisdevelopmentadvicefromtheextremeprogramming(XP)philosophy,YouAren'tGoingtoNeedIt(YAGNI).Althoughwesometimesuseslightlydifferentwords,themeaningisthesame.YAGNIadvocateskeepingthingssimpleandonlybuildingwhatyouimmediatelyneed.
Thisdoesn'tmeanthatyoushouldmakeyoursoftwarehardtomodify.It'sstillimportanttostayflexible,justdon'taddfeaturesbeforeyouneedthem.Forexample,addinganabstractioninterfacewhenthereisonlyasingleimplementationmaybeoverkill.Youcouldeasilyadditalongwiththesecondimplementationifandwhenyoubuildit.
It'sdifficulttomovefastyetnotbreakthingswhendoingso.Howyouachievehighreliabilityinadditiontoaconsistentlygooddevelopmentspeedwilldependonmanythingsthatarespecifictoyoursituation,suchasyourteamsize,organizationalstructure,andcompanyculture.
Onemethodistoembracechangeanddevelopasystemwhereyoucanrefactoryourcodeinconfidence.Usingastatically-compiledlanguage,suchasC#,isagoodstart,butyoushouldalsohaveacomprehensivetestsuitetoavoidregressions.
Youshoulddesignasystemsothatitislooselycoupled,whichmeansthatyoucanchangepartsin
isolationwithoutalotofknock-oneffects.Thisalsomakesiteasiertounittestandunittestsareinvaluabletorefactorinconfidenceandpreventfunctionalregressions.
WewillcovertestingandautomationwithaContinuousIntegration(CI)workflowinthenextchapter.Inthischapter,wewilltalkmoreaboutvariousarchitecturalstylesthatcanhelpyoumaintainyourapplication.
UnderstandingcomplexityWhenlearningaboutnewwaysofdoingthings,youshouldavoiddoingthemwithoutunderstandingthereasons.Youshouldknowthebenefitsanddownsidesandthenmeasurethechangestoprovethattheyarewhatyouexpect.Don'tjustblindlyimplementsomethingandassumeitimprovesthesituation.Trytoavoidcargocultprogrammingandalwaysobjectivelyevaluateanewapproach.
Note
Cargocultprogrammingisthepracticeofemulatingsomethingsuccessfulbutfailingtounderstandthereasonswhyitworks.ItsnamecomesfromthecargocultsofthePacificwhobuiltfalseairstripsaftertheSecondWorldWartoencouragecargodelivery.Weuseittodescribemanythingswherecorrelationhasbeenconfusedwithcausation.
Oneexampleisacompanyencouraginglonghourstodeliveraprojectbecausetheyhaveheardofsuccessfulprojectswhereemployeesworkedlonghours.However,theyfailtounderstandthatthesuccessfulprojectandlonghoursarebothindependentbyproductsofahighlymotivatedandcompetentworkforce,andtheyarenotdirectlyrelated.
It'simportanttokeepcodereadable,notjustforothersonyourteamornewmembersbutalsoforyourselfinthefuture(whenyouwillforgethowsomethingworksandwhyyouwroteitinthisway).Thisdoesn'tsimplymeanwritinghelpfulexplanatorycommentsinthecode,althoughthisisaverygoodpractice.Italsoappliestosourcecontrolcommentsandkeepingdocumentationuptodate.
Readabilityalsoinvolveskeepingthingssimplebyonlymakingthemascomplexastheyneedtobeandnothidingfunctionalityinunnecessarylayersofabstraction.Forexample,notusingcleverprogrammingtechniquestoreducethefileline-countwhenastandardstructure(forexample,alooporifstatement)wouldbemorereadableandonlyslightlylonger.
Ithelpstohaveastandardwayofdoingthingsinyourteamtoavoidsurprises.Usingthesamemethodeverywherecanbemorevaluablethanfindingabetterwayofdoingit,andthenhavinglotsofdifferentways.Ifthereisconsensus,thenyoucangobackandretrofitthebettermethodeverywherewhereyouneedit.
ComplexityreductionTherearevarioussolutionstomanagethecomplexitythatperformance-enhancingtechniquescanadd.Theseusuallyworkbyreducingtheamountoflogicthatyouneedtothinkaboutatanyonetimebyhidingthecomplications.
Oneoptionistouseframeworksthatstandardizehowyouwriteyourapplication,whichcanmakeiteasiertoreasonabout.Anotherapproachistouseanarchitecturethatallowsyoutoonlythinkaboutsmallpartsofyourcodebaseinisolation.Bybreakingupacomplexappintomanageablechunks,itbecomeseasiertoworkwith.
Note
ThisideaofmodularityisrelatedtotheSingleResponsibilityPrinciple(SRP),whichisthefirstoftheSOLIDprinciples(theothersareOpen/Closed,Liskovsubstitution,Interfacesegregation,andDependencyinversion).ItisalsosimilartothehigherlevelSeparationofConcerns(SoC)andtothesimplicityoftheUnixphilosophy.Itisbettertohavemanytoolsthateachdoonethingwell,ratherthanonetoolthatdoesmanythingsbadly.
Frameworks
Frontendframeworks,suchasReact(createdatFacebook),aredesignedtoreliablybuildwebapplicationviewsinJavaScript.Thesehelplargeteamsworkonaprojectbysimplifyingthedataflowandstandardizingtheapproach.
Tip
ReactcanbeintegratedwithASP.NETCoreusingtheReactJS.NETproject(reactjs.net).WecanuseReactNativetobuildcross-platformappsthatsharecodeacrossiOS,Android,andtheUniversalWindowsPlatform(UWP),targetingphone,desktop,andXbox(github.com/ReactWindows).There'salsoCodePushtoletyouliveupdateyourJavaScriptapps(includingCordova),withoutgoingthroughanappstore(microsoft.github.io/code-push).IfyouprefercodinginC#,thenyoucanbuildyourcross-platformmobileappswithXamarin(whichisnowfreeafterMicrosoftacquiredit).However,wewon'tgofurtherintoanyofthesetechnologiesinthisbook.
Onthebackend,wehavetheserver-sideframeworksof.NETCoreandASP.NETCore.AlongwithC#features,theseprovideconvenientwaysofsimplifyinghistorically-complicatedfeatures.Forexample,theasyncandawaitkeywordshidealotofthecomplicatedlogicassociatedwithasynchronousprogramming,andlambdafunctionsconciselyexpressintent.
Wecoveredmanyofthesefeaturesearlierinthisbook,sowewon'tgooverthemagainhere.Wealsohighlightedlibrariesthatcanmakeyourlifeeasierbyhidingboilerplatecodeforcomplexoperations,forexample,EasyNetQandRestBus.
Note
Hidingacomplexprocessisneverperfect,andyouwilloccasionallycomeacrossabstractionsthatleaksomeoftheirimplementationdetail.Forexample,whenhandlingexceptions,youmayfindthattheissueyou'reinterestedinisnowwrappedinanaggregateexception.Ifyou'renotcareful,thenyourerrorlogsmaynolongercontainthedetailthatyoudesire.
Whatwehaveyettotalkaboutindetailisthearchitectureofawebapplication.Splittingamonolithicsystemupintodiscretepartscannotonlyimproveperformance,butifdoneright,itcanalsomakeiteasiertomaintain.
Architecture
Inthepreviouschapter,whendiscussingmessagequeuing,webrieflycoveredthemicroservicesarchitecture.ThisstyleisamoremodernreimaginingofthetraditionalServiceOrientedArchitecture(SOA),andalthoughusingreliableMQcommunicationispreferred,wecanalsoperformthiswithrepresentationalstatetransfer(RESTful)HTTPAPIs.
Typically,webuildatraditionalwebappasasingleapplicationormonolith.Thisiscommoniftheapphasgrownorganicallyoveranextendedperiodoftime,andthisisaperfectlyacceptablepractice.It'sapoordecisiontoover-engineertooearlybeforethereisanyneed,whichmaynevermaterialize.
Excessivepopularityisaniceproblemtohave,butdon'toptimizeforthisprematurely.Thisisn'tanexcusetomakethingsunnecessarilyslow,sobesuretounderstandthetradeoffsinvolved.
Tip
Usingamonolithicarchitectureisnotanexcusetobuildsomethingbadly,andyoushouldplanforexpansion,evenifyoudonotimplementitimmediately.Youcankeepthingssimplewhilestillallowingforfuturegrowth.
Althoughtheapplicationisasingleunit,youshouldsplitthecodebaseintowell-organizedmodules,whicharelinkedtogetherinasimple,logical,andeasy-to-understandway.RefertotheSOLIDprinciples,mentionedpreviously.
Ifamonolithicapplicationcan'teasilyscaletomeetuserdemandandisperformingpoorlyasaresult,thenyoucansplititupintosmallerseparateservices.Youmayalsowishtosplitanappupifithasbecometoocumbersometoiterateonquicklyanddevelopmentspeedhasslowed.
Monolithversusmicroservices
Thefollowingdiagramshowssomedifferencesbetweenatypicalmonolithandamicroservicesarchitecture:
Here,theusermakesarequesttoanapplicationrunningonawebfarm.Wehaveomittedfirewalls,loadbalancers,anddatabasesforclarity,butmultiplewebserversareshowntoillustratethatthesamecodebaserunsonmultiplemachines.
Intheinitialmonolitharchitecture,theusercommunicatesdirectlywithasinglewebserver.Thisisideallyperrequest/responsepair.However,iftheapplicationwaspoorlydesignedandholdsstateinmemory,thenstickysessionsmaycausetheloadtopooloncertainservers.
Thesecondexampleinthediagramofamicroservicesarchitectureisobviouslymorecomplicatedbutalsomoreflexible.Theuseragainsendsarequesttoawebserver,butinsteadofdoingallofthework,theserverputsamessageintoaqueue.
Theworkinthisqueueisdistributedbetweenmultiplebackendservicesofwhichthefirstoneisbusy,soasecondservicepicksupthemessage.Whentheservicecompletes,itsendsamessagetoanexchangeonthemessagebroker,whichusesapub/subbroadcasttoinformallofthewebservers.
Oneaddedpieceofcomplexityisthatthearchitectureshouldhavealreadysenttheresponsetotheuser'soriginalwebrequest,soyouneedtoconsidertheuserexperience(UX)morecarefully.Forexample,youcandisplayaprogressindicatorandupdatethestatusofthiswithanasynchronousWebSocketconnection.
Architecturecomparison
Themonolithapproachissimple,andyoucanjustaddmorewebserverstohandleadditionalusers.However,thisapproachcanbecomecumbersomeasanapplication(anddevelopmentteam)growslargerbecausetheslightestchangerequiresafullredeploymenttoeachwebserver.
Inaddition,amonolithiseasytoscalevertically(up)buthardtoscalehorizontally(out),whichwecoveredpreviously.However,amonolithiseasiertodebug,soyouneedtobecarefulandhavegoodmonitoringandlogging.Youdon'twantanyrandomoutageinvestigationtoturnintoamurdermysteryhuntbecauseofunnecessarilyimplementedmicroservices.
Note
Historically,FacebookhadadeploymentprocessthatconsistedofslowlycompilingtheirPHPcodebasetoagiganticgigabyte-scalebinary(forruntimeperformancereasons).TheythenneededtodevelopamodifiedversionofBitTorrenttoefficientlydistributethishugeexecutabletoalloftheirwebservers.Althoughthiswasimpressiveinfrastructureengineering,itdidn'taddresstherootcauseoftheirtechnicaldebtproblem,andtheyhavesincemovedontobettersolutions,suchastheHipHopVirtualMachine(HHVM),whichissimilartothe.NETCLR.
Ifyouwishtopracticecontinuousdeliveryanddeploymultipletimesaweek(orevenmanytimesaday),thenit'sadvantageoustobreakyourwebapplicationup.Youcanthenmaintainanddeployeachpartseparately,communicatingwitheachotherusingmessagesagainstanagreedAPI.
Thisseparationcanalsohelpyouuseagiledevelopmentmethodologies–forexample,usingmanysmallerteams—€”ratherthanbigteamsbecausesmallerteamsperformbetter.
Yourinstrumentofcontroltoscaleamonolithisverycrude,asallworkisdoneinoneplace.Youcan'tscalepartsofyourappindependentlytotheothercomponents.Youcanonlyscalethewholethingevenifthehighloadisconcentratedinasmallpart.Thisisanalogoustoacentralbankonlyhavingcontrolofasingleinterestrateasalever,whichaffectsmanythingsatonce.Ifyourappisdistributed,thenyouonlyneedtoscalethepartthatrequiresit,avoidingoverprovisioningand
reducingcosts.
Awell-used(andoftenrephrased)quotefromAbrahamMaslowgoes:
"Isupposeitistempting,iftheonlytoolyouhaveisahammer,totreateverythingasifitwereanail."
Thisisknownasthelawoftheinstrumentandisrelatedtotheconfirmationbias.Ifyouonlyhaveonetool,thenyouarelikelytousethistoolforeverythingandonlyseethingsthatsupportyourexistingideas.Thiscommonlyappliestotoolsandframeworks,butitcanalsoapplytoscalingtechniques.
Thefirststeptowardsmodularitymaybetosplitabigwebapplicationintomanysmallerwebappssothatyoucandeploythemseparately.Thisstrategycanhavesomebenefits,butitalsohasmanylimitations.Somelogicmaybeunsuitabletohostinawebapp,forexample,long-runningprocesses,suchasthosemonitoringafilesystemorusedtomanipulatemedia.
Youmayalsofindthatyouneedtoduplicatecodethatwassharedintheoriginalmonolith.IfyouadheretotheDon'tRepeatYourself(DRY)doctrine,thenyoumightextractthisfunctionalitytoalibrary.Yet,nowyouhavedependenciesandversioningtomanage.You'llalsoneedprocessestobuild,packageandhostyourlibraryinaprivaterepository,allofwhichcanslowdowndevelopmentandreduceyouragility.
Note
Sometimes,wealsorefertoDRYasDuplicationIsEvil(DIE),andthisisthesensibleideathatanimplementationshouldonlyoccurinauniquelocation.Ifothercoderequiresthisfunctionality,thenitshouldcalltheoriginalfunctionandnothavecopiedcodepastedin.Thismeansthatyouonlyneedtomakeachangeinasingleplacetoapplyiteverywhere.
Amoreadvancedapproachistoextractfunctionalityintoaseparateservice,whichcanhandlemanydifferentwebapplications.Ifdesignedcorrectly,thenthisservicewon'tneedtohaveanyknowledgeoftheseappsandwillsimplyrespondtomessages.Thisallowsyoutoaddanewwebappwithoutmakingchangestothecodeofotherapplicationsorservices.
Refactoring
Refactoringamonolithintoservicescanbetrickyiftheapplicationhasbecomeatightly-coupledbig-ball-of-mud,butifit'sbeenwell-built(withplentyoftestcoverageandloosely-coupledcode),thenitshouldn'tbetootaxing.There'sabigdifferencebetweenawell-builtmonolithandabig-ball-of-mudmadewithlittlethought.
It'sworthexpandingontestcoverage,asunittestsareessentialforsuccessfulrefactoringwithoutintroducingregressionsornewbugs.Unittestsallowyoutorefactorandtidyupinconfidence,andtheypreventthecreationofcodethatisfragile,whichdevelopersareafraidtotouch.Wewillcovertestingingreaterdetail,includingautomation,inChapter9,MonitoringPerformance
Regressions.
Bothofthesedesignpatternsmayappearsuperficiallysimilar,butinternally,it'sadifferentstory.Thefollowingdiagramillustratesthedifferencesbetweenawell-architectedmonolithandamessybig-ball-of-mud:
Thelargeboxesrepresentthecoderunningoneachwebserver(theWebServerNboxesfromthemonolithexampleintheearlierdiagram).Fromtheoutside,theylookthesame,butthedifferenceisintheinternalcouplingofthecode.
Thebig-ball-of-mudisatangledmesswithcodereferencingotherfunctionsthroughouttheapplication.Themonolithiswell-structuredwithaclearseparationofconcernsbetweendifferentmodules.
Changestocodeinthebig-ball-of-mudcanhaveunexpectedsideeffectsbecauseotherpartsofitmayrelyontheimplementationdetailsofwhatyouaremodifying.Thismakesitbrittle,difficulttoalter,anddevelopersmaybeafraidoftouchingit.
Thewell-builtmonolithiseasytorefactorandsplitoutintoseparateservicesbecausethecodeisneatly-organized.Itusesabstractinterfacestocommunicatebetweenmodules,andcodedoesn'treachintoanotherclass'sconcreteimplementationdetails.Italsohasexcellentunittestcoverage,whichrunsautomatically.
Althoughbothareasinglecodebase,thequalityofthemonolithismuchhigherbecauseitiswell-distributedinternally.Gooddesignisimportantforfuture-proofing,aswebuildinandallowforexpansion.Themonolithhasn'tbeensplituptooearly(beforescalingwasrequired),butthedesignmakesthiseasytodolater.Incontrast,thebig-ball-of-mudhasaccumulatedalargeamountoftechnicaldebt,whichitneedstopayoffbeforewecanmakeanyfurtherprogress.
Tip
Technicaldebt(ortechdebtforshort)istheconceptofnotfinishingajoborcuttingcorners,whichcouldleadtomoredifficultiesuntilitispaidback.Forexample,failingtoproperlydocumentasystemwillmakealteringitlatermoredifficult.
Techdebtisnotnecessarilyabadthingifitisdeliberatelytakenoninfullknowledge,logged,andpaidbacklater.Forexample,waitingtowritedocumentationuntilafterareleasecanspeedupdelivery.However,techdebtthatisnotpaidbackorisaccumulatedwithoutknowledge(simplyduetosloppycoding),willgetworseovertimeandcausebiggerissueslater.
Thebestwaytodeliverahigh-qualityandflexibleapplication(that'seasytorefactor)istohaveacompetentandconscientiousdevelopmentteam.However,theseattributescanoftenbemoreaboutculture,communication,andmotivationthansimplyskillorrawtalent.Althoughthisisn'tabookaboutteammanagement,havingahealthycultureisveryimportant,sowe'llcoveralittleofthishere.Everyoneinanoperationsandsoftwaredevelopmentdepartmentcanhelpcreateapositiveandfriendlyculture,evenifyouusuallyneedbuy-infromhigherupaswell.
Tip
Toolsarealsoveryusefulinrefactoringandtesting.WecoveredtheVisualStudioIDEandReSharperpluginpreviously,buttherearemanymoretoolsfortesting.Wewillcovermoretestingtools,includingautomation,inChapter9,MonitoringPerformanceRegressions.
AcultureofhighperformanceIfyouwanttoachievehighperformance,thenit'simportanttofosteracompanyculturethatencouragesthisandrecognizesperformanceasvital.Culturecan'tjustcomefromthebottomuponlyinvolvingengineers,italsoneedstocomefromthetop-downandmanagementmustbuyintotheperformanceprerogative.
Note
Thissectionisnotverytechnical,sofeelfreetoskipitifyoudon'tcareaboutmanagementorthehumansideofsoftwaredevelopment.
AblamelesscultureThemostimportantattributesofahigh-performanceculturearethatitshouldbeopenandblameless.Everyoneneedstobefocusedonachievingthebestpossibleoutcomesthroughmeasuringandlearning.Attributingfaulttoindividualsistoxictodeliveringgreatsoftware,andthisisnotonlythecasewhenitcomestoperformance.
Ifsomethinggoeswrong,thenitisaprocessproblemandthefocusshouldbeonimprovingitandpreventingrepeatmistakesinthefuture,forexample,byautomatingit.Thisissimilartohowsafety-criticalindustries,suchasairtravel,behavebecausetheyrecognizethatblamingpeoplediscouragesthemfromraisingissuesearlybeforeadisasteroccurs.
ArelatedphilosophyistheJapaneseprocessofKaizen,whichencouragescontinuousimprovementbyeveryone.ThecarmanufacturerToyotapioneeredKaizenpracticestoimprovetheefficiencyoftheirproductionline,andmostautomotivecompaniesandmanyotherdifferentindustrieshavesinceadoptedthem.
Someindustriesalsohaveprocessestoencouragewhistle-blowingthatprotecttheindividualsraisingconcerns.However,ifthisisrequiredinwebapplicationdevelopment,thenit'sasuresignthatthecultureneedswork.Developersshouldfeelthattheyareabletodirectlyraiseconcernsbypassingtheirlinemanagerwithoutconsequence.Ifeveryone'sopinionisrespected,thenthisshouldn'tevenbenecessary.
IntellectualdishonestyIfteammembersgetdefensivewhenideasarechallenged,thenthisisasignthatthingsmaynotbeworkingwell.Everybodymakesmistakesandhasgapsintheirknowledge,atruththebestengineersembrace.Youshouldstriveforaculturewhereeveryoneisopentonewideasandisalwaysaskingquestions.
Ifpeopleareunabletoacceptconstructivecriticismandhavetheirideaschallenged,thentheymaylackconfidenceandbecoveringupalackofcompetence.Experienceddevelopersknowthatyouneverstoplearning,theyadmittheirignoranceandarealwaysopentooffersofimprovements.
Beingclosedtosuggestionsaltersthebehaviorofothers,andtheywillstopraisingsmallissuesearly.Thisresultsinopensecretsaboutpoorquality,andthefirstthatisknownaboutaproblemisatreleasetime,atwhichpointeverythingismuchworse(oronfire).
Thisisnotanexcusetobenastytopeople,soalwaystrytobeniceandgentlyexplainthereasonsbehindyourcriticism.It'seasytofindfaultinanything,soalwaysproposeanalternativeapproach.Ifyouarepatient,thenareasonablepersonwillbegratefulforthelearningopportunityandappreciategainingexperience.
Agoodruletofollowis"don'tbeajerk"andtreatothersasyouwouldliketobetreated,sobekindandthinkabouthowyouwouldfeelifthesituationwasreversed.Justrememberthatbeingniceisnotalwayscompatiblewithdoingtherightthing.
Alittleself-deprecationcangoalongwaytomakingyoumoreapproachable,ratherthansimplydictatingtheone-true-way.However,youshouldmakeitclearwhensomethingisajokeortongueincheek,especiallywhendealingwithculturesthataremoredirectorwhencommunicatingtextually.
Forexample,NorthAmericansareoftenlesssubtlethanandnotassarcasticastheBritish(whoalsospellsomeworddifferently,andsomewouldsaymorecorrectly).Obviously,useyourownjudgmentbecausethismaybeterribleadviceandcouldcauseoffenseor,evenworse,afull-ondiplomaticincident.Hopefully,itisself-evidentthatthiswholeparagraphistongueincheek.
Peoplewhohaveintegrityandconfidenceintheirideascanaffordtobemodestandself-deprecating,butinternalcompanyculturecaninfluencethistoo.Aparticularlybadpracticeistoconductperformancereviewsbyladdering(alsoknownasstackranking),whichinvolvesputtingeveryoneinorder,relativetoeverybodyelse.Thisistoxicbecauseitrewardspeoplewhofocusmoreonmarketingthemselvesthanthosewhorecognizethedeficienciesintheirtechnicalskillsandtrytoimprovethem.Inthepathologicalcase,allofthebestpeopleareforcedout,andyouendupwithacompanyfullofsociopathicsharpsuits,whoaretechnicallyilliterateorevenmorallybankrupt.
SlowdowntogofasterSometimes,thecompanymustallowthedevelopmentteamtoslowdownonfeaturedeliveryinordertofocusonperformanceandresolvingtechnicaldebt.Theyshouldbegiventimetobethoughtfulaboutdesigndecisionssothattheycancogitateavoidingprematuregeneralizationorcarelessoptimization.
Performanceisasignificantsellingpointofsoftware,anditismucheasiertobuildqualitythroughoutthedevelopmentprocessthaninapolishingphaseattheend.ThereisasignificantbodyofevidencethatsuggeststhatgoodperformanceimprovesReturnonInvestment(RoI)andcreatescustomers.Thisisespeciallytrueontheweb,wherepoorperformancedecreasesconversionrateandsearchengineranking.
Havingahealthycultureisnotonlyimportantfortheruntimeperformanceofyoursoftwarebutalsoforthespeedatwhichyoucandevelopit.Theteamshouldbeencouragedtobehaverigorouslyandwriteprecise,butalsoconcise,code.
Yougetwhatyoumeasure,andifyouonlymeasuretherateoffeaturedelivery,orevenworsesimplyLinesofCode(LoC)written,thenqualitywillsuffer.Thiswillhurtyouinthelongrunandisafalseeconomy.
Falseeconomiesarewhenyoumakeshorttermcostsavingmeasuresthatactuallyloseyoumoremoneyinthelongterm.Examplesofthisareskimpingonhardwarefordevelopersorinterruptingsomeoneinthemiddleofcodingwithsomethingtrivial,whichcouldeasilywaituntillater,andforcingthemtoswitchcontexts.
Anothernonsoftwareexampleisashortsightedgovernmentmakingcutstoinvestmentinresearchbysacrificinglong-termgrowthforshort-termgain,possiblyduetothelackofanylong-termeconomicplan.
Note
Hardwareissignificantlycheaperthandevelopertime.Therefore,ifeveryoneonyourteamdoesn'thaveabeefyboxandmultiplemassivemonitors,thenproductivityisbeingneedlesslydiminished.Evenoveradecadeago,Facebook'ssoftwaredeveloperjobadvertslisteddual24-inchwidescreenmonitorsasaperk.
FromthegroundupInahealthyandprogressiveculture,itcanbetemptingtorewritepoorqualitysoftwarefromscratch,perhapsinthelatesttrendyframework,butthisisusuallyamistake.Releasedsoftwareisbattle-hardened(nomatterhowbadlyitwasbuilt),andifyourewriteit,thenyouwillprobablymakethesamemistakesagain,forexample,re-implementingbugsthatyoualreadypatched.Thisisespeciallytrueifthesoftwarewasnotbuiltwithgoodunittestcoverage,whichcanhelppreventregressions.
Theonlycasewhereyoucouldreasonablyrewriteanapplicationfromthegroundupisifyouhaddeliberatelymadeaprototypetoexploretheproblemspacewiththesoleintentionofthrowingitaway.However,youshouldbeverycarefulbecauseifyou'veactuallybuiltaMinimumViableProduct(MVP)instead,thenthesehaveahabitofstickingaroundforalongtimeandformingthefoundationsoflargerapplications.
Abetterapproachtoafullrewriteistoaddteststotheapplication(ifitdoesn'talreadyhavethem)andgraduallyrefactorittoimprovethequalityandperformance.Ifyoubuiltanapplicationinsuchawayastomakeitdifficulttounittest,thenyoucanstartwithUserInterface(UI)tests,perhapsusingaheadlesswebbrowser.Wewillcovertestingmore,includingperformancetesting,inthenextchapter.
SharedvaluesCultureisreallyjustasetofsharedvalues–thingssuchasopenness,sustainability,inclusivity,diversity,andethicalbehavior.Itcanhelphavingthesevaluesformallydocumentedsothateveryoneknowswhatyoustandfor.
Youmayhaveaprogressiveopensalarypolicysothatotherscan'tusesecretearninginformationasatooltopaypeopleless.However,thiswouldneedtoapplyuniversally,asit'sunhealthytohavemultipleconflictingculturesbecausethiscanprecipitateanus-versus-themattitude.
There'splentymoretosayaboutculture,but,asyoucansee,therearemanycompetingconcernstobalance.Themostimportantideaistomakeintentionalandthoughtfultradeoffs.Thereisn'tonecorrectchoice,butyoushouldalwaysbeconsciousoftheconsequencesandappreciatehowtinyactionscanalterteamperformance.
ThepriceofperformanceDevelopersshouldhaveanideaoftheavailablebudgetforperformanceandunderstandthecostofthecodethattheywrite,notjustinexecutionthroughputbutinreadability,maintainability,andpowerefficiency.Throwingmorecoresataunitofworkisnotnearlyasgoodasrefactoringittobesimpler.
Efficiencyhasbecomeincreasinglyimportant,especiallywiththeriseofmobiledevicesandcloudcomputingtime-basedusagebilling.Parallelizinganinefficientalgorithmmaysolveaperformanceprobleminthetimedomain,butit'sacrudebrute-forceapproachandalteringtheunderlyingimplementationmaybebetter.
Lessisoftenmoreandsometimesdoingnothingisthebestapproach.Softwareengineeringisnotonlyaboutknowingwhattobuildbutwhatnottobuild.Keepingthingssimplehelpsothersonyourteamuseyourwork.Youshouldaimtoavoidsurprisinganyonewithnonobviousbehavior.Forexample,considerthatyoubuildanAPIandthengiveitconventionaldefaults;ifthiscouldpotentiallytakealongtime,thenmakethemethodsasynchronoustoindicatethisfact.
Youshouldaimtomakeiteasytosucceedandhardtofailwhenbuildingonyourcode.Makeitdifficulttodothewrongthing,forexample,ifamethodisunsafe,nameittodocumentthisfact.Beingacompetentprogrammerisonlyasmallpartofbeingagooddeveloper,youalsoneedtobehelpfulandproficientatcommunicatingclearly.
Infact,beinganexpertprogrammercanbeadownsideifyoudon'tdeliberatelykeepthingssimpletoaidtheunderstandingofothersonyourteam.Youshouldalwaysbalanceperformanceimprovementsagainstthesideeffects,andyoushouldn'tmakethemattheexpenseoffuturedevelopmentefficiencywithoutgoodreason.
DistributeddebuggingDistributedsystemscanmakeitdifficulttodebugproblems,andyouneedtoplanforthisinadvancebyintegratingtechnologythatcanhelpwithvisibility.Youshouldknowwhatmetricsyouwanttomeasureandwhatparametersareimportanttorecord.
Asyourunawebapplication,itisn'tacaseofdeployandforgetasitmightbewithmobileappsordesktopsoftware.Youwillneedtokeepaconstantautomatedeyeonyourapplicationtoensurethatitisalwaysavailable.Ifyoumonitorthecorrectperformancemetrics,thenyoucangetearlywarningsignsofproblemsandcantakepreventativeaction.Ifyouonlymeasureuptimeorresponsiveness,thenthefirstthatyoumayknowofaproblemisanoutagenotification,probablyatanunsociablehour.
Youmayoutsourceyourinfrastructuretoacloud-hostingcompanysothatyoudon'thavetoworryabouthardwareorplatformfailures.However,thisdoesn'tcompletelyabsolveyouofresponsibilityandyoursoftwarewillstillneedcontinuousmonitoring.Youmayneedtoarchitectyourapplicationdifferentlytoworkinharmonywithyourhostingplatformandscaleorself-healwhenissuesarise.
Ifyoudesignyoursystemcorrectly,thenyourwebapplicationwillrunitself,andyou'llrarelygetnotifiedofactionsthatrequireyourattention.Ifyoucansuccessfullyautomateallofthethings,ratherthanbabysittingalivedeployment,thenthat'smoretimeyoucanusetobuildthefuture.
Inadistributedarchitecture,youcan'tsimplyattachadebuggertothelivewebserver,notthatthisisagoodideaevenwhenpossible.Thereisnoliveserveranymore,therearenowmanyliveserversandevenmoreprocesses.Togetaholisticpictureofthesystem,youwillneedtosimultaneouslyexaminethestateofmultiplemodules.
Therearemanytoolsthatyoucanusetohelpwithcentralizingyourdebuginformation.Youcanretrofitsomeofthem.However,togetthemostoutofthem,youshoulddecidewhattomeasureupfrontandbuildtelemetrycapabilitiesintoyoursoftwarefromthestart.
LoggingLoggingisvitaltoahigh-performanceapplication,sowhileitistruethatloggingaddssomeoverheadandcanslowdownexecution,omittingitwouldbeshort-sightedandafalseeconomy.Withoutlogging,youwon'tknowwhatisslowandrequiresimprovement.Youwillalsohaveotherconcerns,suchasreliability,forwhichloggingisessential.
Errorlogging
Youmayhaveused(oratleastbefamiliarwith)theexcellentASP.NETpackagecalledErrorLoggingModulesandHandlers(ELMAH)tocatchunhandledexceptions(elmah.github.io).ELMAHisgreatforalreadyexistingapplications,asyoucandropitintoaliverunningwebapp.However,it'spreferabletohaveerrorloggingbuiltintoyoursoftwarefromthestart.
Unfortunately,ASP.NETCoredoesnotsupportELMAH,butthereisasimilarpackagecalledErrorLoggingMiddleware(ELM).AddingthistoyourwebapplicationisjustassimpleasinstallingGlimpse,butitisreallyjustaprototypeanddoesn'thaveallthefeaturesofELMAH.First,addtheMicrosoft.AspNetCore.Diagnostics.ElmNuGetpackagetoyourproject,asshowninthefollowingimage:
Then,intheConfigureServicesmethodoftheStartupclass,addthefollowinglineofcode:
services.AddElm();
YoualsoneedtoaddthefollowinglinestotheConfiguremethodofthesameclass:
app.UseElmPage();
app.UseElmCapture();
Tip
Tostartwith,youmaywanttoputtheseintheenv.IsDevelopment()ifstatementsothattheyareonlyactiveonyourworkstation.IfyouuseELMonproduction,thentheselogswilldefinitelyneedsecuring.
Youcannowvisitthe/Elmpathofyourwebapplicationinyourbrowsertoseethelogs,asshowninthefollowingimage.Usethesearchboxtofilterresults,clickonvattheendofeachline(notshown)toexpandtheentry'sdetails,andclickon^tocollapseitagain:
Note
WhenusingELM,ELMAH,oreventhedefaulterrorpages,youshouldbecarefultonotshowdetailedexceptionsorstacktracestorealusers.Thisisn'tsimplybecausethey'reunfriendlyandunhelpful,theyareagenuinesecurityconcern.Errorlogsandstacktracescanrevealtheinternalworkingsofyourapplication,whichmaliciousactorscanexploit.
ELMisfairlybasic,butitcanstillbeuseful.However,therearebettersolutionsalreadybuiltintothedefaulttemplates–things,suchastheintegratedsupportforloggingandApplicationInsights.
ApplicationInsights
ApplicationInsightsallowsyoutomonitortheperformanceofyourapplicationandviewrequestsorexceptions.YoucanuseitwithAzure,butitwillalsoworklocallywithoutneedinganAzureaccount.YoucaneasilyenableApplicationInsightsbykeepingtherelevantcheckboxticked,asshowninthefollowingimage,whenyoucreateanewASP.NETCorewebapplicationprojectinVisualStudio,andyoudon'tneedtosignintoAzuretodothis:
Tip
TheApplicationInsightstemplateoptionisonlyavailableundertheWebtemplatesnotthe.NETCoretemplates.
Buildandrunthenewproject,thenopentheApplicationInsightsSearchwindowtoseetheoutput.Navigatearoundthewebappinyourbrowser,andyouwillseerecordsstarttoappear,whichshouldlooksomethinglikethefollowing:
Tip
Ifyoudon'tseeanyrecordsintheoutput,thenyoumayneedtoupdatetheNuGetpackage(Microsoft.ApplicationInsights.AspNetCore)orclickontheSearchicon.
Youcanfilterbyeventtype,forexample,requestsorexceptions,andtherearemoredetailedfilterstorefineyoursearch.Youcanselectanindividualrecordtoseemoredetails,whichwilllooksomethinglikethefollowing:
AlthoughyoucanaccessthisinformationlocallywithoutAzure,youcanchoosetoselectConfigureApplicationInsightsandsetuploggingofdatatoyourAzureaccount.
Ifyouknowwhatyou'redoing,thenyoucanuseAdvancedModeandenteryourSubscriptionIDandInstrumentationKeymanually:
Note
Secretconfigurationinformation,suchasthis,isnowstoredoutsideofthesourcetreetohelppreventitleaking.Youcannowdefinesecretsasenvironmentvariablesorinasecretsstoreheldinyouruserprofile.
OnceyousetupAzure,thenyoucanviewthetelemetryresultsonlineandaggregateinformationfrommanydiversesystems.Wedon'thavespacetocoverthisinmoredetailhere,butyoucanfindmoreinformationonlineatazure.microsoft.com/en-us/documentation/services/application-insights.
Integratedlogging
LoggingisnowbuiltintoASP.NETCore(intheMicrosoft.Extensions.Loggingpackage)aswellasDependencyInjection(DI),andbothareincludedinthedefaulttemplates.Thisreduces
thebarriertoentry,andit'snowtrivialtousethesehelpfultechnologiesineventhesmallestofprojects.
Previously,youwouldhavetoaddloggingandDIlibrariesbeforeyoustarted,whichcouldputmanypeopleoffusingthem.Ifyoudidn'talreadyhaveastandardchoiceforboth,thenyouwouldneedtowadethroughtheplethoraofprojectsandresearchthemeritsofeach.
Tip
Youcanstilluseyourpreferredlibrariesifyouarealreadyacquaintedwiththem.It'sjustthattherearenowsensibledefaults,whichyoucanoverride.
LoggingisconfiguredintheStartupclass,andifyouusethestandardwebapplicationtemplate,thenthiswillalreadybeincludedforyou.Theloggerfactoryreadssettingsfromtheappsettings.jsonfile.Inhere,youcanconfigurethelogginglevel,andbydefault,therelevantsectionlookslikethefollowing:
"Logging":{
"IncludeScopes":false,
"LogLevel":{
"Default":"Debug",
"System":"Information",
"Microsoft":"Information"
}
}
Thissetsaverychattyloglevel,whichisusefulfordevelopment,butyouwillprobablywanttoonlylogwarnings,anderrorswhenyourunthisinproduction.
Note
AlongwithApplicationInsightsandlogging,usefuldebuggingtoolsincludedbydefaultintheStartupclassincludeadeveloperexceptionpage,whichislikeanadvancedversionoftheoldYellowScreenOfDeath(YSOD)ASP.NETerrorpage.Alsoincludedisadatabaseerrorpage,whichcanhelpfullyapplyEFmigrationsandmitigatesacommonpitfallofpreviousEFcode-firstmigrationdeployments.
ToaddtheloggertoyourMVChomecontrollerviaconstructorinjection,youcanusethefollowingcode(afteraddingusingMicrosoft.Extensions.Logging;toyourusingstatementsatthetopofthefile):
privatereadonlyILoggerLogger;
publicHomeController(ILoggerFactoryloggerFactory)
{
Logger=loggerFactory.CreateLogger<HomeController>();
}
Afterthis,youcanuseLoggertologeventsinsideactionmethods,asfollows:
Logger.LogDebug("Homepageloaded");
Therearemanymorelogginglevelsavailableandoverloadedmethodssothatyoucanlogadditionalinformation,forexample,exceptions.Wewon'tgointoanymoredetailhere,butyoudon'tsimplyhavetologtextevents,youcanalsorecordexecutiontimes(perhapswithastopwatch)orincrementcounterstoseehowoftencertaineventsoccur.Next,we'llseehowtoviewthesenumberscentrallyandreadthemcorrectly.
Note
Formoreexamplesofhowtouselogging,youcanexaminethedefaultaccountcontroller(ifyouincludedindividualuseraccountsauthenticationinthetemplate).Formoreinformation,youcanreadthedocumentationatdocs.asp.net/en/latest/fundamentals/logging.html.
Centralizedlogging
Loggingisgreat.However,inadistributedsystem,youwillwanttofeedallofyourlogsandexceptionsintoasinglelocation,whereyoucaneasilyanalyzethemandgeneratealerts.OnepotentialoptionforthisisLogstash(elastic.co/products/logstash),whichwefleetinglymentionedinChapter2,MeasuringPerformanceBottlenecks.
Ifyoupreferamoremodularapproachandwanttorecordperformancecountersandmetrics,thenthereisStatsD,whichlistensforUDPpacketsandpushestoGraphiteforstorageandgraphing.Youcangetitatgithub.com/etsy/statsdandthereareafew.NETclientslistedonthewiki,alongwithexampleC#codeinthemainrepository.
Youmaywishtousemessagequeuingforloggingsothatyoucanquicklyputaloggedeventintoaqueueandforgetaboutit,ratherthandirectlyhittingaloggingserver.IfyoudirectlycallanAPI(andaren'tusingUDP),thenmakesurethatit'sasynchronousandnonblocking.Youdon'twanttoslowdownyourapplicationbylogginginefficiently.
Therearealsocloudoptionsavailable,althoughtheusualcaveatsaboutlock-inapply.AWShasCloudWatch,whichyoucanreadmoreaboutataws.amazon.com/cloudwatch.AzureDiagnosticsissimilar,andyoucanintegrateitwithApplicationInsights,readmoreatazure.microsoft.com/en-us/documentation/articles/azure-diagnostics.
Thereareothercross-platformcloudservicesavailable,suchasNewRelicorStackify,butthesecanbequiteexpensive,andyoumaywishtokeepyourloggingwithinyourowninfrastructure.Youcouldshoehornthedataintoanalyticssoftware,suchasGoogleAnalyticsortheprivacy-focusedPiwik(whichisopensourceandcanbeself-hosted),butthesearelesssuitablebecausethey'redesignedforaslightlydifferentpurpose.
StatisticsWheninterpretingyourcollectedmetrics,ithelpstoknowsomebasicstatisticsinordertoreadthemcorrectly.Takingasimplemeanaveragecanmisleadyouandmaynotbeasimportantassomeothercharacteristics.
Wheninstrumentingyourcodetocollectmetadata,youshouldhavearoughideaofhowoftenparticularloggingstatementswillbecalled.Thisdoesn'thavetobeexact,andaroughorderofmagnitudeapproximation(orFermiestimate)willusuallysuffice.
Thequestionyoushouldtrytoanswerishowmuchofthedatashouldbecollected,allofitorarandomsample?Ifyouneedtoperformsampling,thenyoushouldcalculatehowbigthesamplesizeshouldbe.WecoveredsamplinginrelationtoSQLinChapter5,OptimizingI/OPerformance,andtheideaissimilarhere.Performancestatisticsrequirethesamelevelofrigorasbenchmarkingdoes,andyoucaneasilybemisledordrawincorrectconclusions.
StatsDincludesbuilt-insupportforsampling,buttherearemanyotherapproachesavailableifyouwanttoinvestigatethem.Forexample,onlinestreamingalgorithmsandreservoirsaretwooptions.Theimportantthingtokeepinmindforperformanceistouseafastrandomnumbergenerator(RNG).As,forsampling,thisdoesn'tneedtobecryptographicallysecure,apseudorandomnumbergenerator(PRNG)isfine.In.NET,youcanusenewRandom()foraPRNG,ratherthanthemoresecureoptionofRandomNumberGenerator.Create().SeeChapter6,UnderstandingCodeExecutionandAsynchronousOperations,formoreexamplesofhowtousebothofthese.
Whenlookingatyourresults,theoutliersmaybemoreinterestingthantheaverage.Althoughthemedianismorevaluablethanthemean,inthiscase,youshouldreallylookatthepercentiles,forexample,the90th,95th,and99thpercentiles.Thesedatapointscanrepresentonlyasmallfractionofyourdata,butatscale,theycanoccurfrequently.Youwanttooptimizefortheseworstcasescenariosbecauseifyourusersexperiencepagesloadstakingoverfivesecondstenpercentofthetime(eventhoughtheaveragelooksfast),thentheymaygoelsewhere.
There'smuchmoretosayonstatistics,butbeyondthebasics,therearediminishingreturns.Ifyourmathisrusty,thenitisprobablywisetohavearefresher(Wikipediaisgreatforthis).Then,youcanexploresomemoreadvancedtechniques,forexample,thehigh-performanceHyperLogLog(HLL)algorithm,whichcanestimatethesizeofalargesetofelementsusingverylittlememory.RedissupportstheHLLdatastructure(withthePFADD,PFCOUNT,andPFMERGEcommands).Formoreondifferentdatastructures,refertoChapter6,UnderstandingCodeExecutionandAsynchronousOperations.
Note
Thisisonlyabriefintroductiontoperformancelogging,butthereismuchmoreforyoutoexplore.Forexample,ifyouwanttostandardizeyourapproach,thenyoucanlookintoAPDEX(apdex.org),whichsetsastandardmethodtorecordtheperformanceofapplicationsandcompute
scores.
ManagingstalecachesIt'sworthprovidingaquickremindertostillconsidersimpleissuesafterallofthiscomplexity.Itisfartooeasytogetlostinthedetailsofacomplicatedbugorperformancetweakandmisstheobvious.
Tip
Agoodtechniquetohelpwiththisisrubberduckdebugging,whichgetsitsnamefromtheprocessofexplainingyourproblemtoarubberduckonyourdesk.Mostofushaveexperiencedsolvingaproblemafteraskingforhelp,eventhoughtheotherpersonhasn'tsaidanything.Theprocessofexplainingtheproblemtosomeone(orsomething)elseclarifiesit,andthesolutionbecomesobvious.
Ifsomethingappearstonotbeworkingafterafix,thenchecksimplethingsfirst.Seewhetherthepatchhasactuallybeendeliveredanddeployed.Youmaybeseeingstalecodefromacacheinsteadofyournewversion.
Whenmanagingcaches,versioningisausefultooltohelpyouidentifystaleassets.Youcanalterfilenamesoraddcommentstoincludeauniqueversionstring.ThiscanbeSematicVersioning(SemVer),anISOdateandtimestamp,orahashofthecontents.Formoreoncachebusting,refertoChapter7,LearningCachingandMessageQueuing.
Note
SemVer,isagreatwaytoversionyourcodebecauseitimplicitlycapturesinformationoncompatibilityandbreakingchanges.YoucanreadmoreaboutSemVeratsemver.org.
SummaryInthischapter,wesawhowtherearealwaysdownsidestoeverydecisionandeverychoicehasacostattachedbecausenothingcomesforfree.Therearealwaystradeoffsinvolved,andyouneedtobeawareoftheconsequencesofyouractions,whichmaybesmallandsubtle.
Thekeylessonistotakeathoughtfulandrigorousapproachtoaddinganyperformance-enhancingtechnique.Measurementiscrucialtoachievingthis,butyoualsoneedtoknowhowdatacanmisleadyouifyoucollectorinterpretitincorrectly.
Inthenextchapter,wewillcontinuewiththemeasurementthemeandlearnhowtouseteststomonitorforperformanceregressions.Youwillseehowtousetesting(includingunittesting),automation,andcontinuousintegrationtoensurethatonceyousolveaperformanceproblem,itstaysthisway.
Chapter9.MonitoringPerformanceRegressionsThischapterwillcoverwritingautomatedteststomonitorperformancealongwithaddingthesetoaContinuousIntegration(CI)anddeploymentsystem.Byconstantlycheckingforregressions,you'llavoidaccidentallybuildingaslowapplication.We'llalsocoverhowtosafelyloadtestasystemwithoutforcingitofflineandhowtoensurethattestsmimicreallifeusageasfaraspossible.
Topicscoveredinthischapterincludethefollowing:
ProfilingLoadtestingAutomatedtestingPerformancemonitoringContinuousintegrationanddeploymentRealisticenvironmentsandproduction-likedataUItestingwithseleniumandphantomheadlessbrowsersA/BtestingforconversionoptimizationCloudservicesandhostingDevOps
Youwillseehowtoautomateperformancemonitoringandtestingsothatyoudon'tneedtoremembertokeepdoingitmanually.You'lllearnhowtocatchregressionsearlybeforetheycausetroubleandhowtosafelybackthemoutforrework.
ProfilingandmeasurementWestartedthisbookbyhighlightingtheimportanceofmeasurementandprofilingbycoveringsomesimpletechniquesinChapter2,MeasuringPerformanceBottlenecks.Wecontinuedthisthemethroughout,andwe'llendthebookonitaswellbecauseit'simpossibletooverstatehowimportantmeasuringandanalyzingreliableevidenceis.
Previously,wecoveredusingGlimpsetoprovideinsightsintotherunningofyourwebapplication.WealsodemonstratedtheVisualStudiodiagnosticstoolsandtheApplicationInsightsSoftwareDevelopmentKit(SDK).There'sanothertoolthat'sworthmentioningandthat'sthePrefixprofiler,whichyoucangetatprefix.io.
Prefixisafreeweb-basedASP.NETprofilerthatsupportsASP.NETCore.However,itdoesn'tsupport.NETCoreyet(althoughthisisplanned),soyou'llneedtorunASP.NETCoreon.NETFramework4.6fornow.There'salivedemoontheirwebsite(atdemo.prefix.io)ifyouwanttoquicklycheckitoutanditlookslikethefollowing:
Note
ASP.NETCorecanrunontopofeither.NETCoreortheexistingstableframework.Forarefresheronhoweverythingfitstogether,referbacktoChapter1,WhyPerformanceIsaFeature,orformoredetails,refertoChapter6,UnderstandingCodeExecutionandAsynchronousOperations.
YoumayalsowanttolookatthePerfViewperformanceanalysistoolfromMicrosoft,whichisusedinthedevelopmentof.NETCore.YoucandownloadPerfViewfrommicrosoft.com/download/details.aspx?id=28567asaZIPfilethatyoucanjustextractandrun.Itisusefultoanalyzethememoryof.NETapplicationsamongotherthings,anditlookslikethiswhenyoulaunchit:
YoucanusePerfViewformanydebuggingactivities,forexample,totakeasnapshotoftheheaporforceGCruns.Wedon'thavespaceforadetailedwalkthroughhere,buttheincludedinstructionsaregood,andthereareblogsonMSDNwithguidesandmanyvideotutorialsonChannel9atchannel9.msdn.com/Series/PerfView-Tutorialifyouneedmoreinformation.
Tip
Sysinternalstools(technet.microsoft.com/sysinternals)canalsobehelpful,butastheydonotfocusmuchon.NET,theyarelessusefulinthiscontext.
Whiletoolssuchasthesearegreat,whatwouldbeevenbetteristobuildperformancemonitoringintoyourdevelopmentworkflow.Automateeverythingthatyoucan,andthismakesperformancecheckstransparent,routine,andrunbydefault.
Manualprocessesarebadbecauseyoucanskipsteps,andyoucaneasilymakeerrors.Youwouldn'tdreamofdevelopingsoftwarebye-mailingfilesaroundoreditingcodedirectlyonaproductionserver,sowhynotautomateyourperformanceteststoo.
Changecontrolprocessesexisttoensureconsistencyandreduceerrors.ThisiswhyusingaSourceControlManagement(SCM)system,suchasGitorTeamFoundationServer(TFS)isessential.It'salsoextremelyusefultohaveabuildserverandperformCIorevenfully-automateddeployments.
Note
Sourcecontrolallowsmultiplepeopletoworkonafilesimultaneouslyandmergethechangeslater.It'slikeWord'strackchangesfeature,butactuallyusable.Weassumethatwe'repreachingtotheconvertedandyoualreadyusesourcecontrol.Ifnot,stopreadingrightnowandgoinstallanSCMsystem.
Ifthecodedeployedinproductiondiffersfromwhatyouhaveonyourlocalworkstation,thenyouhaveverylittlechanceofsuccess.ThisisoneofthereasonswhySQLStoredProcedures(SPs/sprocs)aredifficulttoworkwith,atleastwithoutrigorousversioncontrol.It'sfartooeasytomodifyanoldversionofanSPonadevelopmentDB,accidentallyrevertabugfix,andendupwitharegression.IfyoumustuseSPs,thenyouwillneedaversioningsystem,suchasReadyRoll(whichRedgatehasnowacquired).
Asthisisn'tabookonContinuousDelivery(CD),wewillassumethatyouarealreadypracticingCIandhaveabuildserver,suchasJetBrainsTeamCity,ThoughtWorksGoCD,CruiseControl.NET,oracloudservice,suchasAppVeyor.Perhapsyou'reevenautomatingyourdeploymentsusingatool,suchasOctopusDeploy,andyouhaveyourowninternalNuGetfeeds,usingsoftwaresuchasTheMotleyFool'sKlondike,oracloudservice,suchasMyGet(whichalsosupportsnpm,bower,andVSIXpackages).
Tip
NuGetpackagesareagreatwayofmanaginginternalprojects.InnewversionsofVisualStudio,youcanseethesourcecodeofpackagesanddebugintothem.Thismeansnomorehugesolutionscontainingaludicrousnumberofprojects.
Bypassingprocessesanddoingthingsmanuallywillcauseproblems,evenifyouarefollowingascript.Ifitcanbeautomatedthenitprobablyshouldbe,andthisincludestesting.
TestingTestingisessentialtoproducinghigh-qualityandwell-performingsoftware.Thesecrettoproductivetestingistomakeiteasy,reliable,androutine.Iftestingisdifficultortestsregularlyfailbecauseofissuesunrelatedtothesoftware(forexample,environmentalproblems),thentestswillnotbeperformedortheresultswillbeignored.Thiswillcauseyoutomissgenuineproblemsandshipbugsthatyoucouldhaveeasilyavoided.
Therearemanydifferentvarietiesoftesting,andyoumaybefamiliarwiththemorecommoncasesusedforfunctionalverification.Inthisbook,wewillmainlyfocusontestspertainingtoperformance.However,theadvicehereisapplicabletomanytypesoftesting.
AutomatedtestingAspreviouslymentioned,thekeytoimprovingalmosteverythingisautomation.Teststhatareonlyrunmanuallyondeveloperworkstationsaddverylittlevalue.Ofcourse,itshouldbepossibletorunthetestsondesktops,butthisshouldn'tbetheofficialresultbecausethere'snoguaranteethattheywillpassonaserver(wherethecorrectfunctioningmattersmore).
Tip
Althoughautomationusuallyoccursonservers,itcanbeusefultoautomateteststhatrunondeveloperworkstationstoo.OnewayofdoingthisinVisualStudioistouseaplugin,suchasNCrunch.Thisrunsyourtestsasyouwork,whichcanbeveryusefulifyoupracticeTest-DrivenDevelopment(TDD)andwriteyourtestsbeforeyourimplementations.YoucanreadmoreaboutNCrunchandseethepricingatncrunch.net,orthere'sasimilaropensourceprojectatcontinuoustests.com.
Onewayofenforcingtestingistousegatedcheck-insinTFS,butthiscanbealittledraconian,andifyouuseanSCM,suchasGit,thenit'seasiertoworkonbranchesandsimplyblockmergesuntilallthetestspass.Youwanttoencouragedeveloperstocheck-inearlyandoftenbecausethismakesmergeseasier.Therefore,it'sabadideatohavefeaturesinprogresssittingonworkstationsforalongtime(generallynolongerthanaday).
ContinuousintegrationCIsystemsautomaticallybuildandtestallofyourbranchesandfeedthisinformationbacktoyourversioncontrolsystem.Forexample,usingtheGitHubAPI,youcanblockthemergingofpullrequestsuntilthebuildserverreportsasuccessfullytestedmergeresult.
BothBitbucketandGitLabofferfreeCIsystems,calledpipelines,soyoumaynotneedanyextrasystemsinadditiontooneforsourcecontrolbecauseeverythingisinoneplace.GitLabalsooffersanintegratedDockercontainerregistry,andthereisanopensourceversionthatyoucaninstalllocally..NETCoreandVisualStudiosupportDockerwell,andwe'llcoverthisagainlaterinthechapter.
YoucandosomethingsimilarwithVisualStudioTeamServicesforCIbuildsandunittesting.VisualStudioalsohasGitservicesbuiltintoit.
Thisprocessworkswellforunittestingbecauseunittestsmustbequicksothatyougetfeedbackearly.Shorteningtheiterationcycleisagoodwayofincreasingproductivity,andyou'llwantthelagtobeassmallaspossible.
However,runningtestsoneachbuildisn'tsuitableforalltypesoftestingbecausenotalltestscanbequick.Inthiscase,you'llneedanadditionalstrategysoasnottoslowdownyourfeedbackloop.
Note
Therearemanyunittestingframeworksavailablefor.NET,forexample,NUnit,xUnit,andMSTest(Microsoft'sunittestframework)alongwithmultiplegraphicalwaysofrunningtestslocally,suchastheVisualStudioTestExplorerandtheReSharperplugin.Peoplehavetheirfavorites,butitdoesn'treallymatterwhatyouchoosebecausemostCIsystemswillsupportallofthem.
SlowtestingSometestsareslow,butevenifeachtestisfast,theycaneasilyadduptoalengthytimeifyouhavealotofthem.Thisisespeciallytrueiftheycan'tbeparallelizedandneedtoberuninsequence,soyoushouldalwaysaimtohaveeachteststandonitsownwithoutanydependenciesonothers.
It'sgoodpracticetodivideyourtestsintoringsofimportancesothatyoucanatleastrunasubsetofthemostcrucialoneveryCIbuild.However,ifyouhavealargetestsuiteorsometeststhatareunavoidablyslow,thenyoumaychoosetoonlyruntheseonceaday(perhapsovernight)oreveryweek(maybeovertheweekend).
Sometestingissimplyslowbynatureandperformancetestingcanoftenfallintothiscategory,forexample,loadtestingorUserInterface(UI)testing.Weusuallyclassthisasintegrationtesting,ratherthanunittestingbecausetheyrequireyourcodetobedeployedtoanenvironmentfortestingandthetestscan'tsimplyexercisethebinaries.
Tomakeuseofsuchautomatedtesting,youwillneedtohaveanautomateddeploymentsysteminadditiontoyourCIsystem.Ifyouhaveenoughconfidenceinyourtestsystem,thenyoucanevenhavelivedeploymentshappenautomatically.Thisworkswellifyoualsousefeatureswitchingtocontroltherolloutofnewfeatures.
Wewon'tgointotheimplementationdetailsofContinuousIntegrationorautomateddeploymentsinthisbook.However,wewillcoverfeatureswitching,howtoapplyperformancetestingtoCIprocesses,andwhattodowhenyoudiscoveraregression.
FixingperformanceregressionsIfyoudiscoveraperformanceissueattheunittestingstage,thenyoucansimplyreworkthisfeature,butit'smorelikelythattheseproblemswillsurfaceinalatertestingphase.Thiscanmakeitmorechallengingtoremedytheproblembecausetheworkmayalreadyhavebeenbuiltuponandhaveothercommitsontopofit.
Thecorrectcourseofactionisoftentoback-outregressionsimmediatelyoratleastassoonaspossibleupondiscovery.Delayswillonlymaketheissuehardertofixlater,whichiswhyit'simportanttogetfastfeedbackandhighlightproblemsquickly.
It'simportanttobedisciplinedandalwaysremoveregressions,eventhoughitmaybepainful.Ifyoulettheoccasionalminorregressionin,thenyoucaneasilybecomesloppyandletmoreseriousonesinovertimebecauseoftheprecedentitsets.
LoadtestingLoadtestingistheprocessofdiscoveringhowmanyconcurrentusersyourwebappcansupport.Yougenerallyperformitonatestenvironmentwithatoolthatgraduallyrampsupasimulatedload,forexample,JMeter(jmeter.apache.org).Perhaps,you'dpreferusingaJMetercompatiblecloudservice,suchasBlazeMeter,oranalternative,suchasLoader.io,ifyourtestsystemsareweb-facing.
Loadtestingcantakeasignificantamountoftimedependingonthescaleofyourservicebecauseitcanbeconfiguredtocontinueuntilthetestenvironmentgetsunacceptablyslowforusersorfallsoverandbecomesunresponsive.Youneedtobeextremelycarefulwithloadtestingandnotonlyfromthepointofviewofaccidentallytestingyourlivesystemstodestructionwhilethey'reinuse.
Youalsoneedtobewaryofgettingfalseresults,whichmaymisleadyouintoconcludingthatyoursystemcanhandlemoreloadthanitactuallywill.Balancingthesetwocompetingconcernsofsafetyandrealismcanbedifficult.It'simportanttogetrealisticresults,butyouneedtobalancethisagainstnotstressingyourproductionenvironmentandimpactingtheexperienceofrealusers.
RealismKeepingitrealisanimportantprincipleofperformancetesting.Ifyoudon'tusearealisticenvironmentandworkload,thenyourresultsmaybeworsethanhavingnodatabecausetheycouldmisleadyouintobaddecisions.Whenyouhavenoinformation,youatleastknowthatyou'reinthedarkandjustguessing.
We'llcoverworkloadsandfeatureswitchingshortly,includinganexampleofhowtoimplementyourownsimpleversionfromscratch.First,let'slookathowtomakeyourtestenvironmentsrepresentativeofproduction.
Realisticenvironments
Usingatestenvironmentthatisasclosetoproduction(oraslive-like)aspossibleisagoodsteptowardensuringreliableresults.Youcantryanduseasmallersetofserversandthenscaleyourresultsuptogetanestimateofliveperformance.However,thisassumesthatyouhaveanintimateknowledgeofhowyourapplicationscalesandwhathardwareconstraintswillbethebottlenecks.
Abetteroptionistouseyourliveenvironmentorratherwhatwillbecomeyourproductionstack.Youfirstcreateastagingenvironmentthatisidenticaltolive,thenyoudeployyourcodetoit,andthenyourunyourfulltestsuite,includingacomprehensiveperformancetest,ensuringthatitbehavescorrectly.Onceyouarehappy,thenyousimplyswapstagingandproduction,perhapsusingDNSorAzurestagingslots.
Thefollowingdiagramshowshowyoufirstreleasetostagingandgolivesimplybymakingstagingbecomeproduction:
Youroldliveenvironmentnoweitherbecomesyourtestenvironmentorifyouuseimmutable
cloudinstances,thenyoucansimplyterminateitandSpin-upanewstagingsystem.Thisconceptisknownasblue-greendeployment,butunfortunatelyspecificimplementationinstructionsarebeyondthescopeofthisbook.
Youdon'tnecessarilyhavetomoveallusersacrossatonceinabigbang,andyoucanmoveafewoverfirsttotestwhethereverythingiscorrect.We'llcoverthisshortlyinthesectiononfeatureswitching.
Realisticworkloads
Anotherimportantpartofperformingrealistictestingistouserealdataandrealworkloads.Syntheticdataoftenwon'texerciseasystemfullyorfindexoticedgecases.Youcanusefuzzingtogeneraterandomdata,butifyouhaveaproductionsystem,thenyoucansimplyusethedatafromthisandparseyourlogstogeneratearealisticworkloadtoreplay.
Obviously,don'treplayactionsontoalivesystemthatcouldmodifyuserdataandbewaryofdataprivacyconcernsoranyactionthatcouldgenerateanexternalevent,forexample,sendingamasse-mailorchargingacreditcard.Youcanuseadedicatedtestsystem,butyoustillneedtobecarefultostuboutanyexternalAPIsthatdon'thaveatestversion.
Anotherapproachistousedummyusersforyourtestingifyoudon'tmindyourusersdiscoveringthefakesandpossiblyinteractingwiththem.OnecaseofthisapproachisNetflix'scultExampleShow,whichisahomemadevideoofanemployeerunningaroundtheirofficegroundswithalaptop.
Featureswitching
Analternativetofakeusersortestenvironmentsistorunperformancetestsonyourrealliveenvironmentusinggenuineusersastheyinteractwithyourwebapplication.Youcanusefeatureswitchingtograduallyrolloutanewfeaturetoasmallsubsetofyouruserbaseandmonitorthesystemforexcessiveload.Ifeverythingseemsnormal,thenyoucancontinuetherollout;otherwise,youcanrollback.
Note
Youmayhearsimilarideasreferredtobyothernames,suchasFeatureFlags,FeatureToggles,CanaryReleases,orBranchbyAbstraction.Someofthesemayhavesubtlydifferentmeaningsbutthegeneralguidingprincipleofgraduallyreleasingachangeismuchthesame.
Thefollowingdiagramshowshowyoucouldprogressivelymigrateuserstoanewfeaturebydeployingitbutnotinitiallyenablingit.Yourfirstuserscouldbemembersofstaffsothatanyissuesaredetectedearly:
Onceallusersareconsumingthenewfeature,thenyoucansafelyremovetheoldfeature(andthefeatureswitchitself).It'sagoodideatoregularlytidyuplikethistoavoidclutterandmakelaterworkeasier.
Ifyoudiscoverthatyoursystemexperiencesexcessiveloadasyouslowlyincreasethepercentageofusersonthenewfeature,thenyoucanhalttherolloutandavoidyourserversbecomingoverloadedandunresponsive.Youthenhavetimetoinvestigateandeitherbackoutof
thechangeorincreaseavailableresources.
Onevariationonthisthemeiswhenanewfeaturerequiresadatamigrationandthismigrationiscomputationallyornetworking-intensive,forexample,migratinguser-submittedvideostoanewhomeandtranscodingthemintheprocess.Inthiscase,theexcessiveloadthatyouaremonitoringwillonlybetransient,andyoudon'tneedtobackoutofafeature.Youonlyneedtoensurethattherateofmigrationislowenoughtonotexcessivelytaxyourinfrastructure.
Althoughthenewfeatureisusuallybranchedtoincode,youcaninsteadperformswitchingatthenetworklevelifyouuseblue-greendeployment.ThisisknownasacanaryreleaseandcanbedoneattheDNSorloadbalancerlevel.However,specificimplementationdetailsareagainbeyondtheremitofthisbook.
Youcanfindmanyopensourcefeatureswitchinglibrariesonlineoryoucouldwriteyourown,whichwewillshowyouhowtodolater.Acoupleof.NETfeature-switchinglibrariesaregithub.com/mexx/FeatureSwitcherandgithub.com/Jason-roberts/FeatureToggle.Unfortunately,neitheroftheseworkon.NETCoreyet,althoughsupportisplannedforFeatureToggle.Therearealsopaidcloudservicesavailable,whichoffereasymanagementinterfaces,suchasLaunchDarkly.
Note
Libraryandframeworksupportfor.NETCoreandASP.NETCorechangerapidly,socheckANCLAFS.comforthelatestinformation.
Toillustratefeatureswitching,let'sbuildourownextremelysimpleimplementationforanASP.NETCorewebapplication.Tostartwith,wetakethedefaultexistinghomepageview(Index.cshtml)andmakeacopy(IndexOld.cshtml).WethenmakeourchangestoIndex.cshtml,butthesearen'timportantforthepurposesofthisdemo.
InHomeController.cs,wechangethelogictoreturnthenewviewarelativelysmallpercentageofthetime,andtheoldoneotherwise.Theoriginalcodewassimplythefollowing:
publicIActionResultIndex()
{
returnView();
}
Wechangethisactiontoreturnthenewviewinaquarterofthecases,likethefollowing:
publicIActionResultIndex()
{
varrand=newRandom();
if(rand.Next(99)<25)
{
returnView();
}
returnView("IndexOld");
}
Thiscodepicksarandomnumberoutofahundred,andifitislessthan25,thenitloadsthenewview.Clearly,youwouldn'thardcodevalueslikethis,andyouwouldprobablyuseadatabasetostoreconfigurationandcontrolitwithawebadminpage.
Ifyouloadthepageinabrowser,thenthreeoutoffourtimesyoushouldgettheoriginalpage,whichlookslikethefollowing:
However,roughlyoneeveryfourpageloads,youwillgetthenewpage,whichlookslikethefollowing:
Weremovedthecarouselandcutthenumberofimageloadsinhalf.Youcanseethedifferenceinthebrowserdevelopertools,forexample,theFirefoxperformanceanalysisfortheoriginallookslikethefollowing:
Whereasforthenewversionitlookslikethis.
Youcanseethatthenumberofimagesdecreased,whichhasreducedthepagesizeandthetotalnumberofrequestsrequired.
Note
ThesemeasurementsweretakenwiththehostingenvironmentsettoProduction.IfyouremainwiththedefaultofDevelopment,thenyourresultswilldiffer.Refertothefollowingdocumentationpageforhowtochangethis:docs.asp.net/en/latest/fundamentals/environments.html.
Oncethenewviewhasbeenprogressivelyrolledouttoallusers(withnoperformanceproblems),thentheactionmethodcodecanberevertedtotheoriginalstateandtheoldviewdeleted.Obviously,thisisatrivialexample.Hopefully,youcannowseehowfeatureswitchingcanbeperformed.
Usingfeatureswitchingtorolloutinthiswayworkswellforperformancetesting,butyouneedtobeconfidentthatyournewcodeisfunctionallycorrectoratleastsafetodeploy.However,in
certaincircumstancesyoucanalsotestfunctionalitybyextendingthisapproachandperformingexperiments.
ExperimentingforscienceIfyoutakethefeatureswitchingrollouttoitslogicalconclusion,thenyoucanswitchonanewrefactoredversionforasmallpercentageofusers,butnotactuallyexposetheoutput.Youwillruntheexistingversioninparallelasacontrolandshowthistotheuser.However,youwillcollecttheresultsofbothversions,includingperformancedata.Youcanthencomparethemtoensurethatthenew(hopefullyhigherperformance)versioniscorrectandconsistentwiththeexistingbehavior.
GitHubhaveanopensourceRubylibrary,calledScientist,whichtheyusedtosuccessfullyrefactortheirpermissionsandmergingcode.Intheprocess,theydiscoveredexistinglegacybugs,foundmissingfeatures,optimizeddatabasequeries,andswappedasearchsystem.Scientistnotonlydisplaysthecorrectnessofnewcodebutalsoitsperformancerelativetotheoldimplementation.
Tip
AnimportantconcernwithScientist(oranymethodusingthisexperimentationapproach)istonotchangedata.Alloperationsshouldberead-onlyandhavenosideeffects;otherwise,youwillperformthemodificationmorethanonce,whichcouldhaveundesirableconsequences.
There'sa.NETportofScientistbyGitHubemployeePhilHaack,calledScientist.NET,andyoucangetitatgithub.com/Haacked/Scientist.net.YoucouldalsoinstallitviaNuGet.However,it'scurrentlyaprereleaseasit'sstillaworkinprogress,butitshouldsupport.NETCore.CheckANCLAFS.comforthelatestinformation.
ThisideaofexperimentingonusersissimilartothemarketingconceptofA/Btesting,whichisusedtodiscoverconversioneffectiveness.However,withScientist,youdon'ttypicallyshowtheusersdifferentoutputsorevenintendtheoutputtochange,youjustrecordthenewoutputforthesubsetofusersthatyouhaveitenabledfor.
A/BtestingA/Btestingissimilartofeatureswitching,butweusuallyuseittotesttheeffectivenessofdifferentwebpagedesignsandhowtheyaffecttheconversionfunnelanalytics.Wenormallyuseitfordigitalmarketingratherthanforsoftwaredevelopmentbecauseit'slessaboutwhatiscorrectandmoreaboutwhatcustomersprefer.However,theunderlyingtechnicalprincipalsarecomparabletofeatureswitchingandexperimenting.
Inasimpleexample,youservehalfofyourvisitorstheoldversionofapageandtheotherhalfanewversiondesignedtoincreaseengagement.Youthenrecordhowmanyvisitorsclickthroughorperformsomeactiononeachvariant.Ifthenewversionperformsbetter,thenyoukeepitandrollitouttoeveryone.However,ifitconvertedworse,yourollbacktotheoldversionandtryagain.
Youcanseethatthisisverysimilartohowfeatureswitchingworks,andyoucanusethesametoolstodoboth.Theonlydifferenceiswhatyouaremeasuring,useranalyticsorthehealthofyourinfrastructure.
A/BtestingisnotnormallyusedforbackendfeaturesandissimplytoassessUIalternatives.However,itisdifferenttofunctionallytestingyourwebinterface,solet'scoverthebasicsofUItestingnow.
UserinterfacetestingThere'soneareaofanapplicationthatistraditionallydifficulttotest,andthat'stheUI.ThisisparticularlythecaseforGUIs,asusedinwebapplications.Onereasonforthisisthatuserstypicallyhavealotofflexibilityinhowtheydisplaytheirinterface,andthisisespeciallytrueforwebbrowsers.Anaïvepixel-basedtestingapproachisgoingtobeextremelyfragile.
Youneedtodesignyourapplicationtobeeasilytestable,andtheUIisnoexception.WhileitispossibletotesttheUIofapoorly-designedlegacyapplicationandthismayevenbetheeasiesttestingapproach,ifyouconsiderUItestingupfront,thenlifewillbealoteasier.Forexample,includingsensibleIDsonyourHTMLDocumentObjectModel(DOM)elementsmakestestingmuchmorestraightforwardandlessfragile.
Checkingyourapplicationfromawebbrowserperspectivecanbeausefuladditionalstepontopofautomatedunitandintegrationtesting.Youcanuseitnotonlytotestforfunctionalcorrectnessandregressionsbutalsotomeasureclientsideperformance,whichisincreasinglyimportant.TherearemanyUItestingtoolsavailable,mostofwhichyoucanintegrateintoyourCIpipelinetoautomatetesting.
WebUItestingtools
Oneofthemostpopularweb-testingtoolsisSelenium,whichallowsyoutoeasilywritetestsandautomatewebbrowsersusingWebDriver.Seleniumisusefulformanyothertasksapartfromtesting,andyoucanreadmoreaboutitatdocs.seleniumhq.org.
Note
WebDriverisaprotocoltoremotecontrolwebbrowsers,andyoucanreadaboutitatw3c.github.io/webdriver/webdriver-spec.html.
Seleniumusesrealbrowsers,thesameversionsyouruserswillaccessyourwebapplicationwith.Thismakesitexcellenttogetrepresentativeresults,butitcancauseissuesifitrunsfromthecommandlineinanunattendedfashion.Forexample,youmayfindyourtestserver'smemoryfullofdeadbrowserprocesseswhichtimedout.
Youmayfinditeasiertouseadedicatedheadlesstestbrowser,which,whilenotexactlythesameaswhatyouruserswillsee,ismoresuitableforautomation.Ofcourse,thebestapproachistouseacombinationofboth,perhapsrunningheadlesstestsfirstandthenrunningthesametestsonrealbrowserswithWebDriver.
Oneofthemostwell-knownheadlesstestbrowsersisPhantomJS.ThisisbasedontheWebKitengine,soitshouldgiveyousimilarresultstoChromeandSafari.PhantomJSisusefulformanythingsapartfromtesting,suchascapturingscreenshots,andyoucandriveitwithmanydifferenttestingframeworks.Asthenamesuggests,youcancontrolPhantomJSwithJavaScript,andyoucanreadmoreaboutitatphantomjs.org.
Note
WebKitisanopensourceengineforwebbrowsers,whichwasoriginallypartoftheKDELinuxdesktopenvironment.ItismainlyusedinApple'sSafaribrowser,butaforkcalledBlinkisusedinGoogleChrome,Chromium,andOpera.Youcanreadmoreatwebkit.org.
Otherautomatabletestingbrowsers,basedondifferentengines,areavailable,buttheyhavesomelimitations.Forexample,SlimerJS(slimerjs.org)isbasedontheGeckoengineusedbyFirefox,butisnotfullyheadless.
Youprobablywanttouseahigher-leveltestingutilityratherthanscriptingbrowserenginesdirectly.OnesuchutilitythatprovidesmanyusefulabstractionsisCasperJS(casperjs.org),whichsupportsrunningonbothPhantomJSandSlimerJS.
AnothertoolisCapybara,whichallowsyoutoeasilysimulateuserinteractionsinRuby.ItsupportsSelenium,WebKit,Rack,andPhantomJS(viaPoltergeist),althoughit'smoresuitableforRailsapps.Youcanreadmoreatjnicklas.github.io/capybara.
ThereisalsoTrifleJS(triflejs.org),whichusesthe.NETWebBrowserclass(theInternetExplorerTridentengine),butthisisaworkinprogress.Additionally,there'sWatir(watir.com),whichisasetofRubylibrariestargetingInternetExplorerandWebDriver.However,neitherhavebeenupdatedinawhile,andIEhaschangedalotrecently.
Note
MicrosoftEdge(codenamedSpartan)isthenewversionofIE,andtheTridentenginewasforkedtoEdgeHTML.TheJavaScriptengine(Chakra)wasopensourcedasChakraCore(github.com/Microsoft/ChakraCore).
Itshouldn'tmattertoomuchwhatbrowserengineyouuse,andPhantomJSwillworkfineasafirstpassforautomatedtests.Youcanalwaystestwithrealbrowsersafterusingaheadlessone,perhapswithSeleniumorwithPhantomJSusingWebDriver.
Tip
Whenwerefertobrowserengines(WebKit/Blink,Gecko,orTrident/EdgeHTML),wegenerallymeanonlytherenderingandlayoutengine,nottheJavaScriptengine(SFX/Nitro/FTL/B3,V8,SpiderMonkey,orChakra/ChakraCore).
You'llprobablystillwanttouseautilitysuchasCasperJStomakewritingtestseasier,andyou'lllikelyneedatestframework,suchasJasmine(jasmine.github.io)orQUnit(qunitjs.com)too.YoucanalsouseatestrunnerthatsupportsbothJasmineandQUnit,suchasChutzpah(mmanela.github.io/chutzpah).
YoucanintegrateyourautomatedtestswithmanydifferentCIsystems,forexample,JenkinsorJetBrainsTeamCity.Ifyoupreferacloud-hostedoption,thenthere'sTravisCI(travis-ci.org)and
AppVeyor(appveyor.com),whichisalsosuitabletobuild.NETapps.
YoumayprefertorunyourintegrationandUItestsfromyourdeploymentsystem,forexample,toverifyasuccessfuldeploymentinOctopusDeploy.Therearealsodedicated,cloud-basedweb-applicationUItestingservicesavailable,suchasBrowserStack(browserstack.com).
AutomatingUIperformancetests
AutomatedUItestsareclearlygreattocheckforfunctionalregressions,buttheyarealsousefultotestperformance.Youhaveprogrammaticaccesstothesameinformationprovidedbythenetworkinspectorinthebrowserdevelopertools.
YoucanintegratetheYSlow(yslow.org)performanceanalyzerwithPhantomJS,enablingyourCIsystemtocheckforcommonweb-performancemistakesoneverycommit.YSlowcameoutofYahoo!,anditprovidesrulesusedtoidentifybadpractices,whichcanslowdownwebapplicationsforusers.It'sasimilarideatoGoogle'sPageSpeedInsightsservice(whichyoucanautomateviaitsAPI).
However,YSlowisprettyold,andthingshavemovedoninwebdevelopmentrecently,forexample,HTTP/2.Amodernalternativeis"thecoach"fromsitespeed.io,andyoucanreadmoreatgithub.com/sitespeedio/coach.Youshouldcheckouttheirotheropensourcetoolstoo,suchasthedashboardatdashboard.sitespeed.io,whichusesGraphiteandGrafana.
Youcanalsoexportthenetworkresults(inindustrystandardHARformat)andanalyzethemhoweveryoulike,forexample,visualizingthemgraphicallyinwaterfallformat,asyoumightdomanuallywithyourbrowserdevelopertools.
Note
TheHTTPArchive(HAR)formatisastandardwayofrepresentingthecontentofmonitorednetworkdatatoexportittoothersoftware.YoucancopyorsaveasHARinsomebrowserdevelopertoolsbyright-clickinganetworkrequest.
StayingalertWheneveryouperformtesting,particularlyUIorperformancetesting,youwillgetnoisyresults.Reliabilityisnotperfect,andtherewillalwaysbefailuresthatarenotduetobugsinthecode.Youshouldn'tletthesefalsepositivescauseyoutoignorefailingtests,andalthoughtheeasiestcourseofactionmaybedisablingthem,thecorrectthingtodotomakethemmorereliable.
Tip
Thescientificallymindedknowthatthereisnosuchthingasaperfectfilterinbinaryclassification,andalwayslookattheprecisionandrecallofasystem.Knowingtherateoffalsepositivesandnegativesisimportanttogetagoodideaoftheaccuracyandtradeoffsinvolved.
Toavoidtestingfatigue,itcanbehelpfultoengagedevelopersandinstillaresponsibilitytofixfailingtests.Youdon'twanteveryonethinkingthatit'ssomebodyelse'sproblem.Itshouldbeprettyeasytoseewhobrokeatestbythecommitinversioncontrol,andit'sthentheirjobtofixthebrokentest.
Youcanhaveabitoffunwiththisandcreatesomethingabitmoreinterestingthanawallmounteddashboard.Althoughhavinginformationradiatorsisusefulifyoudon'tgetdesensitizedtothem.There'splentyofcheapInternetofThings(IoT)hardwareavailabletoday,whichallowsyoutoturnsomeinterestingthingsintobuildortestfailurealarms.Forexample,anArduino-controlledtrafficlight,anESP8266-operatedfoam-missileturret,oraRaspberryPi-poweredanimatronicfigure.
DevOpsWhenusingautomationandtechniquessuchasfeatureswitching,itisessentialtohaveagoodviewofyourenvironmentssothatyouknowtheutilizationofallthehardware.Goodtoolingisimportanttoperformthismonitoring,andyouwanttoeasilybeabletoseethevitalstatisticsofeveryserver.ThiswillconsistofatleasttheCPU,memory,anddiskspaceconsumption,butitmayincludemore,andyouwillwantalarmssetuptoalertyouifanyofthesestrayoutsideallowedbands.
ThepracticeofDevOpsistheculminationofalloftheautomationwecoveredpreviouslywithdevelopment,operations,andquality-assurancetestingteamsallcollaborating.Theonlymissingpiecesleftnowaretoprovisionandconfigureinfrastructureandthenmonitoritwhileinuse.AlthoughDevOpsisaculture,thereisplentyoftoolingthatcanhelp.
DevOpstoolingOneoftheprimarythemesofDevOpstoolingisdefininginfrastructureascode.Theideaisthatyoushouldn'tmanuallyperformatask,suchassettingupaserver,whenyoucancreatesoftwaretodoitforyou.Youcanthenreusetheseprovisioningscripts,whichwillnotonlysaveyoutimebutwillalsoensurethatallofthemachinesareconsistentandfreeofmistakesormissedsteps.
Provisioning
Therearemanysystemsavailabletocommissionandconfigurenewmachines.Somepopularconfiguration-managementautomationtoolsareAnsible(ansible.com),Chef(chef.io),andPuppet(puppet.com).
NotallofthesetoolsworkgreatonWindowsservers,partlybecauseLinuxiseasiertoautomate.However,youcanrunASP.NETCoreonLinuxandstilldeveloponWindows,usingVisualStudiowhiletestinginaVM.DevelopingforaVMisagreatideabecauseitsolvestheproblemsinsettingupenvironmentsandissueswhereit"worksonmymachine"butnotinproduction.
Vagrant(vagrantup.com)isagreatcommandlinetooltomanagedeveloperVMs.Itallowsyoutoeasilycreate,Spin-up,andsharedeveloperenvironments.ThesuccessortoVagrant,Otto(ottoproject.io)takesthisastepfurtherandabstractsdeploymenttoosothatyoucanpushtomultiplecloudproviderswithoutworryingabouttheintricaciesofCloudFormation,OpsWorks,oranythingelse.
Ifyoucreateyourinfrastructureascode,thenyourscriptscanbeversionedandtested,justlikeyourapplicationcode.We'llstopbeforewegettoofarofftopic,butthepointisthatifyouhavereliableenvironments,whichyoucaneasilyverify,instantiate,andperformtestingon,thenCIisaloteasier.
Monitoring
Monitoringisessential,especiallyforwebapplications,andtherearemanytoolsavailabletohelpwithit.Apopularopensourceinfrastructure-monitoringsystemisNagios(nagios.org).AnothermoremodernopensourcealertingandmetricstoolisPrometheus(prometheus.io).
Ifyouuseacloudplatform,thentherewillbemonitoringbuiltin,forexample,AWSCloudWatchorAzureDiagnostics.Therearealsocloudservicestodirectlymonitoryourwebsite,suchasPingdom(pingdom.com),UptimeRobot(uptimerobot.com),Datadog(datadoghq.com),andPagerDuty(pagerduty.com).
Youprobablyalreadyhaveasysteminplacetomeasureavailability,butyoucanalsousethesamesystemstomonitorperformance.Thisisnotonlyhelpfultoensurearesponsiveuserexperience,butitcanalsoprovideearlywarningsignsthatafailureisimminent.Ifyouareproactiveandtakepreventativeaction,thenyoucansaveyourselfalotoftroublereactivelyfightingfires.
Thisisn'tabookonoperations,butithelpstoconsiderapplicationsupportrequirementsatdesigntime.Development,testing,andoperationsaren'tcompetingdisciplines,andyouwillsucceedmoreoftenifyouworkasoneteamratherthansimplythrowinganapplicationoverthefenceandsayingit"workedintest,opsproblemnow."
HostingIt'swellworthconsideringtheimplicationsofvarioushostingoptionsbecauseifdeveloperscan'teasilyaccesstheenvironmentstheyneed,thenthiswillreducetheiragility.Theymayhavetoworkaroundanavailabilityproblemandendupusinginsufficientorunsuitablehardware,whichwillhamperprogressandcausefuturemaintenanceproblems.Ortheirworkwillsimplybeblockedanddeliverysetback.
Unlessyouareaverylargeorganization,hostingin-houseisgenerallyabadideaforreliability,flexibility,andcostreasons.Unlessyouhavesomeverysensitivedata,thenyoushouldprobablyuseadatacenter.
Youcanco-locateserversinadatacenter,butthenyouneedstafftobeoncalltofixhardwareproblems.Oryoucanrentaphysicalserverandrunyourapplicationon"baremetal",butyoumaystillneedremotehandstoperformresetsorothertasksonthemachine.
Themostflexiblesituationistorentself-servicevirtualmachines,commonlyknownascloudhosting.Therearemanyhostingcompaniesthatofferthis,butthebigplayersareAmazon,Google,andMicrosoft.
Microsoft'sAzureistheobviouschoicefora.NETshopandithasimprovedimmenselysincelaunchcomparedtoitsoriginaloffering.ItsPlatformasaService(PaaS)tohost.NETapplicationsisthemostpolishedandtheeasiesttogetrunningonquickly.ItalsoofferslotsofextraservicesthatgobeyondsimpleVMs.
However,.NETCoreandASP.NETCorearenewtypesofframework,whicharenotaimedsolelyatC#developers,whowouldusuallypickthedefaultoptionofferedbyMicrosoft.Thetargetedmarketisdeveloperswhomaybeusedtochoosingalternativeplatformsandopensourceframeworks.Therefore,itmakessensetocoverotheroptions,whichpeoplenewto.NETmaybemorefamiliarwith.
Note
ThedifferencebetweenPaaSandInfrastructureasaService(IaaS)isthatPaaSishigherlevelandprovidesaservicetorunapplications,notcomputers.IaaSsimplyprovidesyouwithaVM.However,withPaaS,thisisabstractedaway,andyoudon'tneedtoworryaboutsettingupandupdatinganinstance.
AmazonWebServices(AWS)isthemostestablishedcloudhost,anditstartedbyonlyofferingIaaS,althoughtheynowofferPaaSoptions.Forexample,ElasticBeanstalksupports.NET.EventhoughWindows(andSQLServer)supporthasimproved,itisstillnotfirstclass,andLinuxisclearlytheirmainplatform.
However,nowthat.NETCoreandSQLServer2016runonLinux,thismaybelessofaproblem.YouwillpayapremiumforWindowsserverinstances,butyou'realsochargedmoreforsome
enterpriseLinuxdistributions(RedhatandSUSE).However,youcanrunotherLinuxdistributions,suchasUbuntuorCentOSwithoutpayingapremium.
GoogleCloudPlatformusedtoconsistofAppEngine(GAE),whichwasquitearestrictivePaaS,butitisgettingmoreflexible.TheynowofferagenericIaaScalledComputeEngine(GCE),andthere'sanewflexibleversionofGAE,whichismorelikeGCE.Thesenewofferingsareuseful,asyoucouldn'ttraditionallyrun.NETonGAE,andtheyalsoprovideotherproductssuchaspre-emptibleVMsandacloudCDN(withHTTPSatnoextracost).
Azuremaystillbethebestchoiceforyou,anditintegrateswellwithotherMicrosoftproducts,suchasVisualStudio.However,itisworthhavinghealthycompetitionbecausethiskeepseveryoneinnovating.It'sdefinitelyagoodideatofrequentlylookatthepricingofalloptions,(whichchangesregularly)becauseyoucansavealotofmoneydependingontheworkloadthatyourun.Youcanavoidvendorlock-inbyavoidingcustomservices.
Tip
IfyouareeligibleforMicrosoft'sBizSparkprogram,thenyoucangetthreeyearsofAzurecredits(suitabletohostasmallapplication).YoualsogetanMSDNsubscriptionforfreesoftwarelicenses.
Whateverhostingprovideryouchoosetouse,itissensibletoavoidvendorlock-inanduseservicesthataregeneric,whichyoucaneasilyswapforanalternative.Forexample,usinghostedopensourcesoftware,suchasPostgreSQL,Redis,orRabbitMQ,ratherthananequivalentcustomcloudproviderproduct.Youcanalsotakearesilientmulticloudapproachtoprotectyourselffromanoutageofasingleprovider.
Dockerisagreattechnologyforthispurposebecausemanydifferentcloudservicessupportit.Forexample,youcanrunthesamecontaineronAzureContainerService,DockerCloud,AWSEC2ContainerService,andGoogle'sKubernetesContainerEngine.
DockeralsorunsonWindows(usingHyper-V),andinthenewversionofVisualStudioyoucandeploytoanddebugintoacontainer.ThiscanrunASP.NETCoreonLinux,andwhenyouarereadytodeploy,youcanjustpushtoproductionandhaveconfidencethatitwillworkasitdidonyourmachine.Youcanreadmoreaboutthisatdocker.com/Microsoft,andtherearesomeinterestingvideosontheDockerblog.
Note
Whenchoosingacloud(orevenaregion),it'simportanttonotonlyconsiderthemonetarycost.Youshouldalsofactorinenvironmentalconcerns,suchasthemainfuelusedforthepowersupply.Forexample,someregionscanbecheaper,butthismaybebecausetheyusedirtycoalpower,whichcontributestoclimatechangeandourfuturesecurity.
SummaryInthischapter,yousawhowyoumightintegrateautomatedtestingintoaCIsysteminordertomonitorforperformanceregressions.Youalsolearnedsomestrategiestorolloutchangesandensurethattestsaccuratelyreflectreallife.WealsobrieflycoveredsomeoptionsforDevOpspracticesandcloud-hostingproviders,whichtogethermakecontinuousperformancetestingmucheasier.
Inthenextchapter,we'llwrap-upeverythingthatwecoveredthroughoutthisbookandsuggestsomeareasforfurtherinvestigation.We'llreinforceourlearningssofar,giveyousomeinterestingideastothinkabout,contemplatepossiblefuturesfor.NET,andconsidertheexcitingdirectiontheplatformistaking.
Chapter10.TheWayAheadThischaptersumsupwhatyoulearnedbyreadingthisbook.Itrefreshesthemaintenetsofperformanceanditremindsyouthatyoushouldalwaysremainpragmatic.We'llrecapwhyyoushouldn'toptimizejustforoptimization'ssakeandwhyyoushouldalwaysmeasuretheproblemsandresults.Thischapteralsointroducesmoreadvancedandexotictechniquesthatyoumaywishtoconsiderlearningaboutifyouneedmorespeedorareaseriousperformanceenthusiast.
Topicscoveredinthischapterincludethefollowing:
Asummaryofpreviously-coveredtopicsPlatforminvokeandnativecodeAlternativearchitectures,suchasARMAdvancedhardware(GPUs,FPGAs,ASICs,SSDs,andRAMSANs)MachinelearningandAIBigdataandMapReduceTheOrleansvirtualactormodelCustomtransportlayersAdvancedhashingfunctionsLibraryandframeworksupportThefutureof.NETCore
We'llreinforcehowtoassessandsolveperformanceissuesbyrefreshingyourmemoryofthelessonsinthepreviouschapters.You'llalsogainanawarenessofotheradvancedtechnologythat'savailabletoassistyouwithdeliveringhighperformance,whichyoumaywishtoinvestigatefurther.Finally,we'llhighlightwhatlibrariesandframeworkssupport.NETCoreandASP.NETCore,andtrytohypothesizepossiblefuturedirectionsfortheseexcitingnewplatforms.
ReviewingwhatwelearnedLet'sbrieflyrecapwhatwecoveredearlierinthisbooktoserveasanaide-mémoire.
InChapter1,WhyPerformanceIsaFeature,wediscussedthebasicpremiseofthisbookandshowedyouwhyyouneedtocareabouttheperformanceofyoursoftware.Then,inChapter2,MeasuringPerformanceBottlenecks,weshowedyouthattheonlywayyoucansolveperformanceproblemsistocarefullymeasureyourapplication.
InChapter3,FixingCommonPerformanceProblems,welookedatsomeofthemostfrequentperformancemistakesandhowtofixthem.Afterthis,wewentalittledeeperinChapter4,AddressingNetworkPerformance,anddugintothenetworkinglayerthatunderpinsallwebapplications.TheninChapter5,OptimizingI/OPerformance,wefocusedoninput/outputandhowthiscannegativelyaffectperformance.
InChapter6,UnderstandingCodeExecutionandAsynchronousOperations,wejumpedintotheintricaciesofC#codeandlookedathowitsexecutioncanalterperformance.TheninChapter7,LearningCachingandMessageQueuing,weinitiallylookedatcaching,whichiswidelyregardedtobequitehard.Then,weinvestigatedmessagequeuingasawaytobuildadistributedandreliablesystem.
InChapter8,TheDownsidesofPerformanceEnhancingTools,weconcentratedonthenegativesofthetechniquesthatwepreviouslycovered,asnothingcomesforfree.TheninChapter9,MonitoringPerformanceRegressions,welookedatmeasuringperformanceagainbut,inthiscase,fromanautomationandContinuousIntegration(CI)perspective.
FurtherreadingIfyou'vereadthisfar,thenyouwillprobablywantsomepointersforotherthingstoresearchandreadupon.Fortherestofthischapter,we'llhighlightsomeinterestingtopicsthatyoumaywanttolookintofurther,butwecouldn'tcoverinmoredetailinthisbook.
GoingnativeOneoftheproblemswiththeoldASP.NETisthatitwasreallyslow,whichiswhyoneofthemainguidingprinciplesofASP.NETCorehasbeenperformance.Impressiveprogresshasalreadybeenmade,butthereareplentymoreopportunitiesforfurtherenhancements.
Oneofthemostpromisingareasisthenativetoolchain,whichwebrieflymentionedinChapter6,UnderstandingCodeExecutionandAsynchronousOperations.It'sstillinitsearlydaysbutitlookslikeitcouldbeverysignificant.
Previously,ifyouwantedtocallunmanagednativecodefrommanaged.NETcode,youneededtousePlatformInvoke(PInvoke),butthishadperformanceoverheadsandsafetyconcerns.Evenifyournativecodewasfaster,theoverheadsoftenmeantitwasnotworthbotheringabout.
Thenativetoolchainshouldgivenativelevelsofperformance,butwiththesafetyandconvenienceofamanagedruntime.Ahead-of-timecompilationisfascinatingandverytechnical,butitcanofferaperformanceboostalongwithsimplifieddeploymentsifweknowthearchitecture.
It'salsopossibletooptimizefordifferentprocessorsthatmayofferspecialperformancefeaturesandinstructions.Forexample,targetinglow-energyARMchipsinsteadoftheusualIntelstyleprocessors.
ProcessorarchitectureTypically,whenwritingdesktoporserversoftware,youwilltargetanIntel-basedarchitecture,suchasx86orx64.However,ARM-basedchipsaregainingpopularity,andtheycanofferfantasticpowerefficiency.Ifsoftwareisspeciallyoptimizedforthem,thentheycanalsoofferexcellentperformance.
Forexample,theScratchgraphicalprogramminglanguage,usedtoteachcomputing,hasbeenoptimizedforaRaspberryPi3anditnowrunsroughlytwiceasquickasitdoesonanIntelCorei5.OthersoftwarehasalsobeenoptimizedfortheARMprocessor,forexample,theKodiopensourcemediaplayer.
ARMHoldingsissimplyanintellectualpropertycompanyandtheydon'tmakeanyprocessorsthemselves.Othercompanies,suchasAppleandBroadcom,licensethedesignsorarchitectureandfabricatetheirSystemonaChip(SoC)products.
Thismeansthattherearemanydifferentchipsavailable,whichrunmultipledifferentversionsoftheARMarchitectureandinstructionset.Thisfragmentationcanmakeithardertosupportunlessyoupickaspecificplatform.
Windows10IoTCorerunsontheRaspberryPi(version2and3)anditcannowbesetupusingthestandardNewOutOftheBoxSoftware(NOOBS)installer.Windows10IoTCoreisnotafulldesktopenvironmenttorunnormalapplications,butitdoesallowyoutomakehardwareprojectsandprogramthemwithC#and.NET.However,forwebapplications,youwouldprobablyrun.NETCoreonLinux,suchasRaspbian(basedonDebian).
HardwareishardWepreviouslymentionedadditionalhardwarethatcanbeusedforcomputationinChapter6,UnderstandingCodeExecutionandAsynchronousOperations,includingGraphicsProcessingUnits(GPUs),FieldProgrammableGateArrays(FPGAs),andApplicationSpecificIntegratedCircuits(ASICs).
Notonlycanthesedevicesbeusedforspecificprocessingtasks,buttheirstoragecanbeusedaswell.Forexample,youcanborrowtheRAMfromaGPUifmainmemoryisexhausted.However,thistechniqueisnotrequiredasmuchasitusedtobewhenmemorywasmorelimited.
YoumayhaveheardofRAMSANs,whichwereSANsusingstandardRAMforpermanentstorage(withabatterybackup).However,thesehavebecomelessrelevantasSSDs(basedonflashmemory)improvedinspeedandincreasedincapacitytothepointofreplacingmechanicaldrivesformanycommontasks.
YoucanstillpurchasehighperformanceSANs,buttheywillprobablybebasedonflashmemoryratherthanRAM.IfyouuseRAMasyourmainstorage(forexample,withRedis),thenitisimportanttouseerror-correctingcodememory(ECC).ECCRAMismoreexpensive,butitisbettersuitedforserveruse.However,somecloudinstancesdon'tuseitorit'shardtofindoutwhetherit'sevenofferedbecauseitisn'tlistedinthespecification.
OneapplicationofcustomcomputationhardwareisMachineLearning(ML),specificallythedeeplearningbranchofML,usingmultilevelneuralnetworks.Thistechnologysawimpressiveadvancesinrecentyearsandthisledtoproducts,suchasself-drivingvehicles.MLapplicationscanmakeverygooduseofnon-CPUprocessing,particularlyGPUs,andNVIDIAprovidesmanytoolsandlibrariestohelpwiththis.
GooglealsorecentlyannouncedthattheybuiltacustomASIC,calledaTensorProcessingUnit(TPU),toacceleratetheirTensorFlowmachinelearninglibraryandcloudservices.Youcanreadmoreattensorflow.organdcloud.google.com/ml.
MachinelearningYoudon'tonlyhavetouseArtificialIntelligence(AI)toreplacedriversandotherjobs,suchascallcenterstafforevendoctors.YoucanusesomebasicMLinyourownwebapplicationstoprovideproductsuggestionsrelevanttoyourcustomersoranalyzemarketingeffectiveness,justlikeAmazonorNetflixdo.
Youdon'tevenneedtobuildyourownMLsystems,asyoucanusecloudservices,suchasAzureML.ThisallowsyoutouseagraphicaldraganddropinterfacetobuildyourMLsystems,althoughyoucanalsousePythonandR.
Youstillneedtoknowalittlebitaboutdatascience,suchastheelementaryprinciplesofbinaryclassificationandtrainingdata,butevenso,itsignificantlyreducesthebarriertoentry.Yet,ifyouwanttofullyexploreMLandbigdatapossibilities,thenyouprobablyneedadedicateddatascientist.
YoucantryoutAzureMLatstudio.azureml.netandyoudon'tevenneedtoregister.Thefollowingscreenshotshowsanexampleofwhatitlookslike:
BigdataandMapReduceBigdataisprobablyanoverusedtermthesedaysandwhatissometimesdescribedasbigisusuallymorelikemediumdata.Bigdataiswhenyouhavesomuchinformationthatitisdifficulttoprocess,orevenstore,onasinglemachine.Traditionalapproachesoftenbreakdownwithbigdata,astheyarenotadequateforthehugeautomatically-acquireddatasetsthatarecommontoday.Forexample,theamountofdataconstantlycollectedbyIoTsensorsorbyourinteractionswithonlineservicescanbevast.
OnecaveatofbigdataandMListhat,althoughtheyaregoodatfindingcorrelationsinlargesetsofdatapoints,youcannotusethemtofindcausations.Youalsoneedtobemindfulofdataprivacyconcernsandbeverycarefulofnotjudgingsomeonebeforetheyhaveacted,basedonlyonapredictedpredisposition.
Note
Anonymizingdataisincrediblydifficultandisnotnearlyassimpleasremovingpersonalcontactdetails.Therehavebeenmanycasesoflarge"anonymized"datasetsbeingreleasedwhereindividualswerelatereasilyidentifiedfromtherecords.
OnetechnologythatisusefultoanalyzebigdataisMapReduce,whichisawayofsimplifyinganoperationsothatitissuitabletoruninparallelonadistributedinfrastructure.ApopularimplementationofMapReduceisApacheHadoopandyoucanusethisinAzurewithHDInsight,whichalsosupportsrelatedtools,includingApacheSparkandApacheStorm.OtheroptionstohandlelargedatasetsincludeGoogle'sCloudBigtableorBigQuery.
YoucanseetheavailableoptionsforAzureHDInsightintheportal,asshowninthefollowingimage.Somefeaturesarestillinprevieworhaverestrictions,buttheymayhavemovedtogeneralavailabilitybythetimeyoureadthis.
YoucanseefromthisimagethatSparkisinpreviewandiscurrentlyavailableonlyonLinux.HadoopismoreestablishedandisalsoavailableonWindows,asshowninthefollowingscreenshot:
ThenextimageshowsthatStormisalsoavailablebutnotonthepremiumpreview(includingMicrosoftRServer):
OrleansAnotherinterestingprojectisanopensourceframeworkfromMicrosoftcalledOrleans,whichisadistributedvirtualactormodelthatwasusedtopowerthecloudservicesofHaloXboxgames.Whatthismeansisthat,ifyoubuildyoursystembyseparatingyourlogicintoseparateactors,thisallowsittoeasilyscale,basedondemand.
InOrleans,actorsareknownasgrainsandyoucanwritetheminC#byinheritingfromaninterface.ThesearethenexecutedbyanOrleansserver,calledasilo.Grainscanbepersistedtostorage,suchasSQLorAzureTables,tosavetheirstateandtoreactivatelater.OrleanscanalsomakeuseoftheBondserializerforgreaterefficiency.
Unfortunately,Orleansdoesnotcurrentlysupport.NETCore,buttheportingworkisinprogress.Orleansallowsyoutowritesimpleandscalablesystemswithlowlatencyandyoucanreadmoreatdotnet.github.io/orleans.
CustomtransportsInChapter4,AddressingNetworkPerformance,westartedwithanintroductiontoTCP/IPandbrieflymentionedUDP.WealsocoveredTLSencryptionandhowtominimizetheimpactofsecureconnectionswhilestillreapingperformancebenefits.
UDPissimplerandquickerthanTCP,butyoueitherneedtonotcareaboutreliabledelivery(multiplayergamesandvoice/videochat)orbuildyourownlayertoprovidethis.InChapter8,TheDownsidesofPerformance-EnhancingTools,wehighlightedStatsD,whichusesUDPtoavoidblockinglatencywhileloggingtoaremotecentralserver.
TherearealternativestoTLSifyouaren'tconstrainedtoabrowser,butifyou'redevelopingawebapplication,thiswillprobablyonlyapplyinsideofyourserverinfrastructure.Forexample,theWhatsAppmessagingappusesNoisePipesandCurve25519fromtheNoiseProtocolFramework(noiseprotocol.org)betweenthesmartphoneappandtheirserversinadditiontotheSignalProtocolforend-to-endencryption.
UsingNoisePipesinsteadofTLSincreasesperformancebecausefewerroundtripsarerequiredtosetupaconnection.Anotheroptionwithsimilarbenefitsisthesecurepipedaemon(spiped),asusedbyandcreatedforthesecureLinuxbackupsoftware,Tarsnap.However,youdoneedtopresharethekeys,butyoucanreadmoreaboutthisatwww.tarsnap.com/spiped.html.
AdvancedhashingWecoveredhashingfunctionsafairamountinthisbook,especiallyinChapter6,UnderstandingCodeExecutionandAsynchronousOperations.Thisareaisconstantlyadvancinganditisusefultokeepaneyeonthefuturetoseewhat'scoming.AlthoughtodayitisreasonabletouseamemberoftheSHA-2familyforquickhashingandPBKDF2forslow(password)hashing,thisisunlikelytoalwaysbethecase.
Forfasthashing,thereisanewfamilyofalgorithmscalledSHA-3,whichshouldnotbeconfusedwithSHA-384orSHA-512(whicharebothintheSHA-2family).SHA-3isbasedonanalgorithmcalledKeccak,whichwasthewinnerofacompetitiontofindasuitablealgorithmforthenewstandard.OtherfinalistsincludedSkein(skein-hash.info)andBLAKE2(blake2.net),whichisfasterthanMD5,butactuallysecure.
AnalgorithmcalledArgon2wonasimilarcompetitionforpasswordhashing(password-hashing.net).Toseewhythismatters,youcanvisithaveibeenpwned.com(runby.NETsecurityguruTroyHunt)toseewhetheryourdetailsareinoneofthelargenumberofdatabreaches.Forexample,LinkedInwasbreachedanddidn'tusesecurepasswordhashing(onlyanunsaltedSHA-1hash).Consequently,mostoftheplaintextpasswordswerecracked.Therefore,ifaLinkedInaccountpasswordwasreusedonothersites,thentheseaccountscanbetakenover.
It'saverygoodideatouseapasswordmanagerandcreatestronguniquepasswordsforeverysite.Itisalsobeneficialtousetwo-factorauthentication(sometimesalsocalledtwo-stepverification)ifavailable.Forexample,youcandothisbyenteringacodefromasmartphoneappinadditiontoapassword.Thisisparticularlyusefulfore-mailaccounts,astheycannormallybeusedtorecoverotheraccounts.
LibraryandframeworksupportTherehavebeensomesignificantchangesto.NETCoreandASP.NETCorebetweenRC1andRC2,morethannormalforreleasecandidates.Sensibly,manypopularlibrariesandframeworkswerewaitingforRC2,orlater,beforeaddingsupport.
Obviously,abookisabadplacetokeepupwiththechanges,sotheauthorhasputtogetherawebsitetodisplaythelatestcompatibilityinformation.YoucanfindtheASP.NETCoreLibraryandFrameworkSupportlistatANCLAFS.com.
Ifyouwouldliketoupdateanythingoraddalibraryorframework,thenpleasesendapullrequest.Therepositoryislocatedatgithub.com/jpsingleton/ANCLAFSanditincludeslotsofusefultools,libraries,frameworks,andmore.Wementionedmanyoftheseearlierinthisbookandthefollowingsampleisjustasmallselectionofwhatislistedbecausepackagesupportwillgrowovertime:
Scientist.NETFeatureSwitcherFeatureToggleMiniProfilerGlimpsePrefixDapperSimple.DataEFCoreHangfireImageResizerDynamicImageImageProcessorCoreRestBusEasyNetQRabbitMQClientMassTransitTopshelfNancySignalROrleans
ThefutureAquoteoftenattributedtothephysicistNielsBohrgoes,asfollows:
"Predictionisverydifficult,especiallyaboutthefuture."
However,we'llhaveagoatthisanyway,startingwiththemorestraightforwardbits.TheofficialASP.NETCoreroadmaplistsSignalR,WebPages,andVisualBasicsupportshippingaftertheversion1.0ReleaseToManufacturing/Marketing(RTM).
Afterthis,itisfairlysafetoassumethatfeatureswillbeaddedtobringtheCorelineclosertotheexistingframeworks.ThisincludesEntityFramework,whichiscurrentlymissingsomeofthebigfeaturesofthefullEF,forexample,lazyloading.
Thereisalsothemovetowardsthe.NETPlatformStandard,toenhanceportabilityacross.NETCore,the.NETFrameworkandMono.Forexample,.NETCore1.0and.NETFramework4.6.3bothimplement.NETPlatformStandard1.6(netstandard1.6).However,youprobablydon'tneedtoworryaboutthisunlessyouarewritingalibrary.Refertothedocumentsatdotnet.github.io/docs/core-concepts/librariesifyouare.
Microsofthassaiditwilllistentouserfeedbackanduseittodrivethedirectionoftheplatforms,soyouhaveavoice.Evenifyoudon't,then,asthecodeisallopensource,youcanhelpshapethefuturebyaddingthefeaturesthatyouwant.
Furtherintothefutureishardertopredict,buttherehasbeenasteadystreamofprojectsbeingopensourcedbyMicrosoftfromtheearlyofferingsofASP.NETMVCtotheXamarinframeworkforcross-platformappdevelopment.
It'sanexcitingtimetobeworkingwithC#and.NET,especiallyifyouwanttobranchoutfromwebdevelopment.TheUnitygameengineisnowpartofthe.NETfoundation,andtherearesomeinterestingrecentdevelopmentsinVirtualReality(VR)orAugmentedReality(AR)hardware.Forexample,MicrosoftHololens,OculusRift,SamsungGearVR,andHTCViveareallunbelievablybetterthanthebasicVRthatcameoutacoupleofdecadesago.
It'salsoagreattimetobelookingatIoT,which,whileitmaystillbelookingforitskillerapp,hassomuchmorecheapandpowerfulhardwareavailable.ARaspberryPiZerocostsonly$5anditnowsupportsanupgradedcameramodule.WithacomputersuchastheRaspberryPi3,whichoffersalmostdesktopclassperformancefor$35,anyonecannoweasilylearntocode(perhapsinC#or.NET)andmakethings,especiallychildren.
FollowingthewisdomofAlanKay:
"Thebestwaytopredictthefutureistoinventit."
So,getoutthereandmakeit!Andmakesurethatyousharewhatyou'vedone.
SummaryWehopethatyouenjoyedthisbookandlearnedhowtomakeyourwebapplicationshigh-performingandeasytomaintain,particularlywhenyouuseC#,ASP.NETCoreand.NETCore.Wetriedtokeepasmuchadviceaspossibleapplicabletogeneralwebappdevelopment,whilegentlyintroducingyoutothelatestopensourceframeworksfromMicrosoftandothers.
Clearlyatopicsuchasthischangesquiterapidly,sokeepyoureyesopenonlineforupdates.ThereisanannouncementsrepositoryonGitHubthatisworthwatchingatgithub.com/aspnet/announcements.Hopefully,alotofthelessonsinthisbookaregenerallygoodideasandtheywillstillbesensibleforalongtimetocome.
Alwayskeepinmindthatoptimizingforitsownsakeispointless,unlessit'sjustanacademicexercise.Youneedtomeasureandweighthebenefitsagainstthedownsides;otherwise,youmayendupmakingthingsworse.Itiseasytomakethingsmorecomplex,hardertounderstand,difficulttomaintain,orallofthese.
It'simportanttoinstillthesepragmaticperformanceideasintoteamculture,orelseteamswon'talwaysadheretothem.However,aboveall,remembertostillhavefun!