Satisfy Your Technical Curiosity Profiling and Optimizing.NET Applications Ingo Rammer
Satisfy Your Technical Curiosity Ingo Rammer and Ingo Rammer and Support and consulting for software architects and developers Application Optimization and Tuning Developer-Coaching and -Mentoring Architecture and Code Reviews Prototyping and Architectural Consulting
Satisfy Your Technical Curiosity Scenario I Architecture Design Initial Coding and Load Testing
Satisfy Your Technical Curiosity Load Testing Pitfalls It’s important to test the right thing Double-check that network link and client CPUs are not overloaded Run test clients in the same LAN as the servers Two ways of testing with very different results Simulated user load (including think times, etc.) Maximum Request Load (no think time, just load) Include ramp-up time (“step user load”)
Satisfy Your Technical Curiosity Load Testing in Practice Track counters of multiple servers Test clients, Web servers, DB servers Liebig’s Law of the Minimum is applicable here as well “The scarcest resource will limit growth” After the resource is identified, take action
Satisfy Your Technical Curiosity Scenario II Architecture Design Coding Test Deployment
Satisfy Your Technical Curiosity Users
Don‘t assume anything
Satisfy Your Technical Curiosity 1 st - Trace the Network Interactions The wire never lies Wireshark/Ethereal (Sniffing) TcpTrace (Explicit Port-Forwarding) Fiddler, ProxyTrace (HTTP Proxies) Caution: Some companies do not allow sniffing!
Satisfy Your Technical Curiosity Things you might find out Overhead you didn’t expect Authentication, sub-optimal bindings, … Roundtrips you didn’t expect Cookies Images (check your IE settings!) MarshalByRefObject-roundtrips General: Too many roundtrips, or too big Latency vs. Bandwidth
Satisfy Your Technical Curiosity 2 nd - Trace your SQL Most SQL today is generated DataSets and Adapters O/R Mappers Suboptimal SQL: main reason for scalability probs Today's databases are (unfortunately?) very good: Hide a lot of problems in single-user access during DEV
Satisfy Your Technical Curiosity Invoicing Application Subset Invoice InvoiceId InvoiceDate CustomerId Status InvoiceItems InvoiceId Itemld ProductId ProductName Quantity Price Status SerialNumbers InvoiceID ItemId SerialNumber Status SerialNumberAudit AuditId EntryDate Username SerialNumber Description
Satisfy Your Technical Curiosity Invoicing - Requirements Cancel (Status=2) Copy
Satisfy Your Technical Curiosity Lessons Learned from SQL Profiling DataSets, DataAdapters and O/R Mappers are great tools Can simplify more than 80% - 90% of your generic database access code BUT: Please avoid them in high-load / high-throughput parts of your application
Satisfy Your Technical Curiosity Optimize Your SQL for Transactions “UPDATE” with Foreign Keys “INSERT INTO... SELECT” In the high-load areas of your application. Not everywhere!
Satisfy Your Technical Curiosity Database Locks Minimize duration and number of locks Dynamic SQL (with parameters) vs. Stored Procedures UPDATE only changed rows if possible SELECT only the rows you need, join only tables you need Possibility: changed isolation level (snapshot isolation or NOLOCK) in statistics if you have to report from OLTP data Don‘t use “Sequence-Tables” (better go for Autoincrement/Identity/Guid columns!)
Satisfy Your Technical Curiosity The #1 Reason for Deadlocks TableNameNextValue Customer1234 Employee34 Invoice InvoiceDetail Order OrderDetail SerialNumber Inventory45543
Satisfy Your Technical Curiosity Indexes help a bit... Use: Index (TableName) Not: Index (TableName, NextValue) SQL Server: An index is only locked when one or more of the contained fields are locked! Even snapshot isolation won’t help you here Please note: Oracle sequences behave differently. They always run without transaction locks.
Satisfy Your Technical Curiosity 3 rd - Memory Profiling CLR Profiler 2.0 (free tool) Shows how much memory each method allocates Not leaks, just allocations
Satisfy Your Technical Curiosity Memory Usage Important for multi-user applications Issue: Multiple GC-cycles during one request Generative GC Short-lived objects end up in generation 2 You can quickly check this in PerfMon, too!.NET CLR Memory/Gen #0 Collections, #1, #2 2,5 GB practical maximum for ASP.NET apps on 32 bit systems
Satisfy Your Technical Curiosity In-Process Profiling Often as a last step Reason: In-Proc affects “only” performance Reason 2: After eliminating memory hogs, code will usually be faster anyway Profiler Jetbrains’ DotTrace Redgate ANTS Automated QA AQTime Compuware DevPartner
Satisfy Your Technical Curiosity I code well, so where’s the scary part?
Satisfy Your Technical Curiosity The Scary Facts SqlDataSource Grid A23,926,450 Bytes Grid B17,147,255 Bytes Grid C 3,325,839 Bytes GridView2,583,207 Bytes ObjectDataSource GridView 169,551 Bytes Grid C916,769 Bytes Manual HTML Tables51,237 Bytes w/o ViewState43,897 Bytes
Satisfy Your Technical Curiosity Summary Don‘t assume anything Network – the wire never lies (auth overhead, roundtrips, …) Database – generated SQL Memory – multiple GCs for one request? In-Proc Performance – as the last step (scale up) Don‘t trust anyone It might not be your code, but it could be your job!
Satisfy Your Technical Curiosity
Resources Wireshark/Ethereal: Fiddler: TcpTrace, ProxyTrace: SQL Profiler: out of the box CLR Profiler 2.0: cryptic link, please google
Satisfy Your Technical Curiosity
2006 DSL, WLAN, MBits, … Ping to New York: 800 msec Download of 3,6 GB (Visual Studio): 6 Hours 6 Hours
Satisfy Your Technical Curiosity Early 90s 1200 baud acoustic coupler „Ping“ to New York: 1200 msec Download of 3,6 GB (Visual Studio): 347 Days 347 Days
Satisfy Your Technical Curiosity Early 90s Download 347 Days Walking km 5 km per hour 12 hours per day 333 Days
Satisfy Your Technical Curiosity 2006 Latency (Ping): 33% improvement Bandwidth: % improvement