Top Banner
DEV326 Building High- Performance Applications with .NET Juval Löwy www.idesign.net
61
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: DEV326 Building High-Performance Applications with.NET Juval Löwy .

DEV326

Building High-Performance Applications with .NET

Juval Löwy

www.idesign.net

Page 2: DEV326 Building High-Performance Applications with.NET Juval Löwy .

About Juval LöwySoftware architect

Consults and trains on .NET migration and design

MS Regional Director for the Silicon Valley

AuthoredProgramming .NET components (2003, O’Reilly)

COM and .NET component services (2001, O’Reilly)

Participates in the .NET design reviews

Contributing editor and columnist to the Visual Studio Magazine

Contact at www.idesign.net

Page 3: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Agenda

Definitions

.NET benchmarks

Design and measurement

Examples in everyday Code

Less known/understood examples and best practices

Resources

Page 4: DEV326 Building High-Performance Applications with.NET Juval Löwy .

What is Performance

My Answer: how the application performs Not just raw “performance”

Performance How long it take to perform a request

ScalabilityHow many outstanding clients

ThroughputHow many concurrent request

Page 5: DEV326 Building High-Performance Applications with.NET Juval Löwy .

What is Performance

Responsiveness How long a client waits to be serviced

AvailabilityHow much of the time the app is up

ConsistencyProportion of aborted transactions

Security How secure is the application

Cost Hardware is expensive

Page 6: DEV326 Building High-Performance Applications with.NET Juval Löwy .

.NET Benchmarks

Pets shop.NET 1.0Done by Microsoft Partner

Pets shop.NET 2.0Done by Middleware Company

J2EE industry and community leader

Suspected Web Sphere and Web Logic

http://www.middleware-company.com/j2eedotnetbench/

Page 7: DEV326 Building High-Performance Applications with.NET Juval Löwy .

.NET Benchmarks Highlights (.NET 1.1 on Windows Server 2003)

PerformanceOutperforms J2EE by 339%

Outperforms J2EE by 98% on distributed transactionat 1/4 cost per transaction

Outperforms J2EE by 331% in XML Web Service testing

Productivity

Productivity1/6 cost to implement in .NET

Optimizing/configuring J2EE application server 10 man-weeks per application server with .NET at 2 man-weeks

Page 8: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Web Pages ThroughputWindows 2000 vs. Windows 2003

0

1000

2000

3000

4000

5000

6000

7000

2CPU 4CPU 8CPU

Pa

ge

s/se

c

J2EE Application Server A J2EE Application Server B .NET 1.0/W2K .NET 1.1/Windows.NET

91%91%

34%34%

70%70%

http://www.middleware-company.com/documents/j2eedotnetbenchmark.pdf

Page 9: DEV326 Building High-Performance Applications with.NET Juval Löwy .

ASP.NET Benchmarks

Baseline: ASP.NET is 3x faster than Active Server Pages

ASP.NET + OutputCaching: 3x faster than baseline

ASP.NET + OutputCaching + IIS 6.0: 6x faster than baseline

Credit: Rob Howard, http://www.gotdotnet.com/team/rhoward/

Page 10: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Design for Performance

Have GoalsBusiness process metrics

Runtime performance

Understand the platformFramework

O/S

Application architectures

Juval’s rule: 10x

Page 11: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Measuring Performance

GetTickCount APIMilliseconds since system startup

System.DateTime

Highest ResolutionQueryPerformanceCounter API

Returns frequency per second

Returns current time value

Page 12: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Analyzing Performance

PerformanceCounter classWork with existing system countersCreate application specific counters

.NET-provided countersInteropExceptionsJITLock and threadNetworkingRemotingSecurity

Page 13: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Analyzing Performance3rd Party Profilers

Intel: VTunehttp://developer.intel.com/

NuMega: DevPartner Profilerhttp://www.compuware.com/products/numega/dps/profiler/

Rational Software: Quantifyhttp://www.rational.com/

Plus more…

Page 14: DEV326 Building High-Performance Applications with.NET Juval Löwy .

CLR ProfilerCLR Profiler

demodemo

Page 15: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Examples in Everyday Code

Late Binding

String vs StringBuilder

Boxed Unknowingly

Collections

Binding

ASP.NET Web Server Controls

Cache

Page 16: DEV326 Building High-Performance Applications with.NET Juval Löwy .

JIT Optimization

CPU-specific instructionsCross assembly cache optimization Range check eliminationConstant foldingConstant/copy propagationMethod incliningCode hoistingLoop unrollingDead code removalPlus more…

Page 17: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Generics

Amateur benchmark Push/Pop on stack in tight loop

Type-safe generic value type vs boxed value type

73% faster

Type-safe generic ref-type vs just object 5% faster

Bottom line – use generics

Page 18: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Less known Practices

But just as important Allocation and finalization

Remoting

Security

Transactions

Page 19: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Memory AllocationEvery process has a managed heap

New objects allocated off the heap, and the pointer moves up

When the heap is exhausted, GC takes place

Multi generation allocationNew object part of younger generation

Younger generations are more collectable

Heap is pre-allocatedAllocation is much faster than nativeallocation

Obj 1

Obj 2

Obj 3

Obj 4

New Object

Managed Heap

Page 20: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Garbage Collection

Dispose of unreachable objectsObject that no one can reach no client has a reference to

Nobody can use them OK to kill

.NET keeps list of rootsTop-level objects: static, global, local variable, GC objects

JIT compiler maintains the list

When GC starts, it deems everything as garbage

Page 21: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Garbage Collection

GC traverses recursively from rootsBuilds a graph of reachable objects

Adds to graph just once (cyclic references)

All threads must suspend during GC

Page 22: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Dispose of unreachable objectsTreated as empty space

Moved to finalized queue if required

CompactionMove reachable objects down

Patch references

Obj 1

Obj 2

Obj 3

Obj 4

Obj 8

Obj 10

New Object

Obj 1

Obj 2

Obj 3

Obj 4

Obj 8

Obj 8

Obj 10

Garbage

GarbageCollection

Garbage Collection

New Object

Page 23: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Garbage Collection

Intelligent Cleanup

Generational mark and sweep

Self-Tuning

Limited control in System.GC

GC.CollectForces a full collection

Hurts performance

Impacts tuning algorithm

Page 24: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Garbage Collection GenerationsGen0

New objects, short livedSized based on processor cache10ms collection time

Gen1Middle aged objectsSized based on app allocation rate10ms to 30ms collection time

Gen2The oldest objectsSized based on app allocation rateCollection time is the most expensive

Large ObjectFor objects > 80KbCollected, but not relocatedCollected during Gen2 collections

Page 25: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Garbage Collection Types

Workstation GCHosted by console or Windows forms applications

Can take advantage of MP

Server GCParallel MP Capable

GC Thread per CPU

Multiple Heaps for Scalability

Page 26: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Finalization

Object can optionally implement Finalize() method

void Finalize(){…}

GC knows about Finalize() from Metadata

GC calls Finalize()

Page 27: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Finalization and Destructor

In C#, even if you add a destructor, the compilers converts it to Finalize()

In C#, do not use Finalize(), always use destructor

Page 28: DEV326 Building High-Performance Applications with.NET Juval Löwy .

public class MyClass{ public MyClass(){} ~MyClass(){}} /// code that is actually generated:

public class MyClass{ public MyClass(){} protected virtual void Finalize() {

try { //Your destructor code goes here } finally { base.Finalize();//everybody has one, from Object } }}

Page 29: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Finalization

Finalization postpones releasing resources to undetermined point in the future

Usually till next GC

Can severely hamper application scalability

Use deterministic finalization if an issue

Page 30: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Deterministic Finalization

Unlike COM, there is no way the object knows when is not required by its clients

Unless you implement your own reference count

Object has to be explicitly told by client when not required

Two programming patternsClose/Open

IDisposable

Page 31: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Object implements System.IDisposable interface

public interface IDisposable{ void Dispose();}public interface IMyInterface{ void MyMethod();} public class MyClass : IMyInterface,IDisposable{ public void MyMethod(){} public void Dispose() { //do object cleanup, call base.Dispose() if has one } }

IDisposable

Page 32: DEV326 Building High-Performance Applications with.NET Juval Löwy .

IDisposable

AdvantagesClients are decoupled from finalization mechanism

Disadvantages Makes sharing objects complicated

Couples clients to clients All your base classes should implement Dispose() or IDisposable

Page 33: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Advanced Examples

RemotingProtocols

Activation models

Leasing

Transaction

Security

Page 34: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Remoting Performance Binary over TCP is comparable to DCOM over RPC

i.e very fast

SOAP is slowerAt least order of magnitude

Performance matter lessProductivity

Extensibility

Interoperability

Scalability

Throughput

Page 35: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Remoting Single Call Object

Key to scalability

Object exist only while call in progress

Dealing with expensive objects and greedy clients

Only accessed when client makes call, not during construction

Cannot have parameterized constructors

Page 36: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Client ProxySingle Call

Object

3 5

Client Proxy

2

Client ProxySingle Call

Object

1

4

1 Object executes call on behalf of a remote client1 Object executes call on behalf of a remote client

2 When call returns, .NET calls 2 When call returns, .NET calls IDisposable.Dispose()IDisposable.Dispose(), then releases , then releases all references, making it a candidate for garbage collectionall references, making it a candidate for garbage collection

3 Client makes another call on the proxy3 Client makes another call on the proxy

4 Proxy forwards call to the remote domain4 Proxy forwards call to the remote domain

5 .NET creates an object, and calls the method on it5 .NET creates an object, and calls the method on it

Single Call ObjectSingle Call Object

Page 37: DEV326 Building High-Performance Applications with.NET Juval Löwy .

public class Param{…} public class MySingleCallComponent : MarshalByRefObject,IDisposable{ public MySingleCallComponent(){…} public void MyMethod(Param objectIdentifier) { GetState(objectIdentifier); DoWork(); SaveState(objectIdentifier); } protected void GetState(Param objectIdentifier){…} protected void DoWork(){…} protected void SaveState(Param objectIdentifier){…} public void Dispose(){…} /* Class members/state */ }

Single Call ObjectSingle Call Object

Cannot have state in memory between callsCannot have state in memory between callsMust be state-aware object Must be state-aware object

Page 38: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Single CallSingle Call

demodemo

Page 39: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Leasing

GC is per process

Who keeps remote objects alive?

Each app domain has lease managerFor exposed remote objects

Each remote object is associated with a lease object

Lease keeps object alive

Lease manager maintains list of leases

Reachable, so not collected

Page 40: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Leasing

Passing object ref outside process creates a lease

Lease is for client activated objects and singletons

Lease has lease timeoutWhen expires, object is garbage

Lease has default timeout: 5 minutes

Client and object can control lease timeout

Page 41: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Lease Interface

Defines lease properties and policy

Lease class implements ILease System.Runtime.Remoting.Lifetime

public interface ILease { TimeSpan CurrentLeaseTime {get;} LeaseState CurrentState {get;} TimeSpan InitialLeaseTime {get;set;} TimeSpan RenewOnCallTime {get;set;} TimeSpan SponsorshipTimeout {get;set;}   void Register(ISponsor obj); void Register(ISponsor obj,TimeSpan renewalTime); TimeSpan Renew(TimeSpan renewalTime); void Unregister(ISponsor obj);}

Page 42: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Object-Provided Lease

public class MyServer : MarshalByRefObject{ public override object InitializeLifetimeService()

{ ILease lease = (ILease)base.InitializeLifetimeService(); Debug.Assert(lease.CurrentState == LeaseState.Initial);

  //Set lease properties lease.InitialLeaseTime = TimeSpan.FromMinutes(30); lease.RenewOnCallTime = TimeSpan.FromMinutes(10); lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); return lease;

}}

Page 43: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Sponsor is a third party, consulted when lease expires

Given opportunity to renew lease

Sponsor implements ISponsor

A lease can have multiple sponsors Lease manager maintains a list per lease, in ascending order

One or more invoked, given an opportunity to renew lease

Lease Sponsors

public interface ISponsor { TimeSpan Renewal(ILease lease);}

Page 44: DEV326 Building High-Performance Applications with.NET Juval Löwy .

public class MySponsor : MarshalByRefObject,ISponsor { public TimeSpan Renewal(ILease lease) { Debug.Assert(lease.CurrentState == LeaseState.Active);  //Renew lease by 5 minutes return TimeSpan.FromMinutes(5); }}

ISponsor sponsor = new MySponsor();

//Create the remote object - after registration MyServer obj = new MyServer();

/Register the sponsorILease lease = (ILease)RemotingServices.GetLifetimeService(obj);lease.Register(sponsor);

Implementing SponsorImplementing Sponsor

Page 45: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Implementing Sponsor

Sponsor should return the initial lease time

public class GenericSponsor : MarshalByRefObject,ISponsor { public TimeSpan Renewal(ILease lease) { Debug.Assert(lease.CurrentState == LeaseState.Active) return lease.InitialLeaseTime; }}

Page 46: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Security and Performance

Framework classes have built-in security demands

Indicate type of operation requested

Indicate security action and time

When assembly tries to perform operationGranted access to resource orSecurity exception

Page 47: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Security and Performance

CLR must verify permission of chain of callers

Not good enough if component has permission but not upstream caller

Verify using stack walk

Resource demand for security permission verification triggers stack walk

If even one caller does not have permission -> security exception

Page 48: DEV326 Building High-Performance Applications with.NET Juval Löwy .

class MyClass{ void SaveString(string str,string fileName) { StreamWriter stream = new StreamWriter(fileName,true);//append stream.WriteLine(str); stream.Close(); } void WriteToFile() { string fileName = @"C:\Temp\MyStrings.txt"; string[] array = new string[9]; array[0] = "Every"; array[1] = "string"; array[2] = "in"; array[3] = "this"; array[4] = "array"; array[5] = "causes"; array[6] = "a"; array[7] = "stack"; array[8] = "walk"; foreach(string str in array) { SaveString(str,fileName); } }}

Page 49: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Security and Performance

Can assert permission, to stop stack walk

Requires assertion permission

void WriteToFile(){ string fileName = @"C:\Temp\MyStrings.txt"; string[] array = {"Now","the","stack","walk","stops","here"}; IStackWalk stackWalker; stackWalker = new FileIOPermission(FileIOPermissionAccess.Write, fileName); stackWalker.Assert(); foreach(string str in array) { SaveString(str,fileName); }}

Page 50: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Transaction and Performance

Throughput more than just performance

Use Enterprise Services Gain in scalability

Voting is possibleSet the static property MyTransactionVote of ContextUtil

ContextUtil.MyTransactionVote = TransactionVote.Commit;

Page 51: DEV326 Building High-Performance Applications with.NET Juval Löwy .

[Transaction]public class MyComponent : ServicedComponent{ public void MyMethod(long objectIdentifier) { try { GetState(objectIdentifier); DoWork(); SaveState(objectIdentifier); ContextUtil.MyTransactionVote = TransactionVote.Commit; } catch { ContextUtil.MyTransactionVote = TransactionVote.Abort; } //Let ES deactivate the object once the method returns ContextUtil.DeactivateOnReturn = true; } //other methods protected void GetState(long objectIdentifier){…} protected void DoWork(){…} protected void SaveState(long objectIdentifier){…}}

Transaction and Performance Transaction and Performance

Page 52: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Transaction and Performance

Voting without exception-handling

[Transaction]public class MyComponent :ServicedComponent{ public void MyMethod(long objectIdentifier) { //Let ES deactivate the object once the method returns //and abort. Can use ContextUtil.SetAbort() as well ContextUtil.DeactivateOnReturn = true; ContextUtil.MyTransactionVote = TransactionVote.Abort;  GetState(objectIdentifier); DoWork(); SaveState(objectIdentifier); ContextUtil.MyTransactionVote = TransactionVote.Commit; }} 

Page 53: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Transaction and PerformanceTransaction and Performance

Best: useBest: use AutoCompleteAutoComplete method-attributemethod-attribute

Sets done and consistency bits to Sets done and consistency bits to true if the method did not throw an true if the method did not throw an exception, and the consistency bit exception, and the consistency bit to false if it did to false if it did

Deactivates JITA objects Deactivates JITA objects

Page 54: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Transaction and Performance

[Transaction]public class MyComponent : ServicedComponent{ [AutoComplete] public void MyMethod(long objectIdentifier) { GetState(objectIdentifier); DoWork(); SaveState(objectIdentifier); }}

Page 55: DEV326 Building High-Performance Applications with.NET Juval Löwy .

More at TechEd

C# Best Practices DEV312

Distributed Security PracticesDEV354

Building High-Performance Applications with Visual Studio .NET

DEV326

Application and Library VersioningDEV343

Software Legends – VS.NET and C# tips and tricksSWL004

Page 56: DEV326 Building High-Performance Applications with.NET Juval Löwy .

microsoft.public.dotnet.framework.performance“Performance Testing .NET Web Applications”, Microsoft ACE Team, MSPRESGotDotNet - CLR Profiler"Performance Considerations for Run-Time Technologies in the .NET Framework"

http://msdn.microsoft.com/library/en-us/dndotnet/html/dotnetperftechs.asp

"Performance Tips and Tricks in .NET Applications"http://msdn.microsoft.com/library/en-us/dndotnet/html/dotnetperftips.asp

.NET CF Perf WhitePaper on www.microsoftdev.com“CIL Programming: Under the Hood of .NET”, Jason Brock, APress

ResourcesResources

Page 57: DEV326 Building High-Performance Applications with.NET Juval Löwy .

ResourcesResources

Programming .NET components By Juval Lowy, O'Reilly April 2003

www.idesign.net

.NET Master Class3-4 annually

Upcoming events onwww.idesign.net

Page 58: DEV326 Building High-Performance Applications with.NET Juval Löwy .

Community Resources

Community Resourceshttp://www.microsoft.com/communities/default.mspx

Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/

NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx

User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx

Page 59: DEV326 Building High-Performance Applications with.NET Juval Löwy .

evaluationsevaluations

Page 60: DEV326 Building High-Performance Applications with.NET Juval Löwy .

SOFTWARE LEGENDSOFTWARE LEGENDJuval LowyJuval Lowy

THURSDAY 3rd JULY at 16.15-16.45 hrs

Meet the Author’sMeet the Author’s Book signingBook signing

Page 61: DEV326 Building High-Performance Applications with.NET Juval Löwy .

© 2003 Microsoft Corporation. All rights reserved.© 2003 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.