SlideShare uma empresa Scribd logo
1 de 82
Optymalizacja
aplikacji ASP
.NET
 Skalowalność – ilu użytkowników może pracować jednocześnie?
 Aplikacja może obsługiwać tysiące użytkowników, ale być wolna
 Zmiany w sprzęcie, infrastrukturze sieciowej, itp. (istotna architektura!)
 Wydajność – jak szybko ładują się strony?
 Zasada 8 sekund
 Liczy się odczuwalna wydajność (np. reklamy dopiero na końcu)
 To także:
 Szybkość wprowadzania poprawek i zmian
 Łatwość wdrażania aplikacji
 Proces wytwórczy
 …
 Architektura Bing vs strony domowej (można przesadzić)
Skalowalność i wydajność
 Lokalny cache przeglądarki
 DNS – cache / zapytanie
 Proxy – visible / transparent
 Cache serwera
 System - http.sys
 IIS
 ASP
.NET (dane w ram / z dysku)
 Cache SQL Server
 Dyski – SSD / zwykłe / cache…
Komponenty wpływające na wydajność
 Odczuwalna wydajność
 Kolejność ładowania, AJAX
 Mniej żądań do serwera
 Walidacja po stronie klienta, bundling, itp.
 Cache na wszystkich warstwach
 Minimalizacja blokujących wywołań
 Synchroniczne operacje zapisu do bazy, zewnętrzne usługi, itp.
 Optymalizacja I/O (dyski, itp.)
 Także partycjonowanie / sharding, itp.
Najważniejsze zasady przy optymalizacji
Wydajność po stronie klienta
 Maximum Transfer Unit (MTU) - rozmiar okna odpowiedzi
 Od 500 do 1500 bajtów
 Dużo komunikatów SYN-ACK
 TCP Slow Start (RFC 5681)
 Bardzo kosztowne nawiązywanie połączenia
 Długi okres między pierwszym pakietem a kolejnym
 Zapobiega przeciążeniu sieci
 Jak najmniej nowych połączeń (np. żądania plików)
 HTTP Keep-Alives – domyślnie w IIS 120 sekund
 Np. przy długich formularzach można zwiększyć (ostrożnie)
Protokół TCP
TCP Slow Start - przykład
 IE Developer tools (F12)
 Żółte – slow start + pierwszy pakiet odpowiedzi
 Niebieski – reszta odpowiedzi
 Jeśli <img> było w pierwszym pakiecie
 <head>
 Przeglądarka nie wyświetli nic przed pobraniem całego nagłówka
 „Lookahead” – ograniczenia
 Jak najwięcej w <body>
 Nawet <link> i <style> (niezgodne ze specyfikacją, ale działa)
 Kolejność
 Np. duży baner reklamowy na górze strony – w kodzie lepiej niżej
Struktura strony
 Ustawiać width i height dla <img>!
Późne ładowanie - placeholder
<img id="myimg" width="50" height="50" />
<!-- Klasycznie -->
<script type="text/javascript">
document.getElementById("myimg").src = "myimage.jpg";
</script>
<img id="Img1" width="50" height="50" />
<!-- w jQuery -->
<script type="text/javascript">
$("#myimg").attr("src", "myimage.jpg");
</script>
Późne ładowanie – preloading
<!-- Preloading - na górze strony lub w onload (jeśli może być później) -->
<script type="text/javascript">
var myimg = new Image();
myimg.src = "myimage.jpg";
</script>
<!-- Niżej na stronie, będzie załadowane z cache (dla rolloverów) -->
<img src="myimage.jpg" width="50" height="50" />
 Wielkość liter
 W Unix – system plików case sensitive
 Niektóre serwery cache’ują oddzielnie
 Może spowodować wysłanie dwóch żądań
 Można dołączyć moduł http, który to poprawia
 Referencje do tej samej domeny
 Przekierowanie z domena.com/gfx.jpg na www.domena.com/gfx.jpg
Cache i URL
<img src="myimage.jpg" width="50" height="50" />
<img src="myimage.JPG" width="50" height="50" />
 Przeglądarki mają do 6 równoległych połączeń dla domeny
 Przed IE8 – tylko 2!
 Można podzielić pliki na kilka domen
 img.mojadomena.com, css.mojadomena.com, itp.
 Aliasy lub inne usługi cookieless (np. Azure Blob)
Przetwarzanie żądań
<img src="q1.gif" height="16" width="16" />
<img src="q2.gif" height="16" width="16" />
<img src="q3.gif" height="16" width="16" />
<img src="q4.gif" height="16" width="16" />
<img src="q5.gif" height="16" width="16" />
<img src="q6.gif" height="16" width="16" />
<img src="q7.gif" height="16" width="16" />
<img src="q8.gif" height="16" width="16" />
<img src="q9.gif" height="16" width="16" />
<img src="q10.gif" height="16" width="16" />
 ok. 30% zwiększenie szybkości wczytywania
Podział plików na kilka domen
<img src="q1.gif" height="16" width="16" />
<img src="q2.gif" height="16" width="16" />
<img src="q3.gif" height="16" width="16" />
<img src="q4.gif" height="16" width="16" />
<img src="q5.gif" height="16" width="16" />
<img src="http://mojadomena.net/samples/ch02/q6.gif" height="16" width="16" />
<img src="http://mojadomena.net/samples/ch02/q7.gif" height="16" width="16" />
<img src="http://mojadomena.net/samples/ch02/q8.gif" height="16" width="16" />
<img src="http://mojadomena.net/samples/ch02/q9.gif" height="16" width="16" />
<img src="http://mojadomena.net/samples/ch02/q10.gif" height="16" width="16" />
 Jeśli kilka aliasów – mechanizm generowania powtarzalnych url
 Plik grafika.jpg zawsze z s1.domena.com, grafika3.jpg z
s2.domena.com, itp.
 Wewnątrz własnej kontrolki
 Control adapter dla Image
(dalej)
ASP
.NET i podział na kilka domen
private string _src;
private static string[] subdomains = {
"http://s1.12titans.net",
"http://s2.12titans.net",
"http://s3.12titans.net"
};
public string src
{
get
{
HttpContext ctx = HttpContext.Current;
if (ctx.Request.Url.Host != "localhost")
{
if (!String.IsNullOrEmpty(this._src) && !this._src.StartsWith("http") &&
!this._src.StartsWith("data:"))
{
int n = Math.Abs(this._src.GetHashCode()) % subdomains.Length;
return subdomains[n] + this._src;
}
}
return this._src;
}
set
{
this._src = ResolveUrl(value).ToLowerInvariant();
}
}
 Skrypty inline mogą opóźniać renderowanie strony
 Renderowanie dopiero po zakończeniu działania skryptów
 OnLoad / DOMReady – wtedy po wyrenderowaniu
 Umieszczać na końcu pliku
 Jeśli skrypty zmieniają HTML
 Zamiast document.write() – innerHTML (możliwe wywołania później)
 Ukryty div z document.write() + odkrywanie go później
 <script defer> i <script async> (HTML 5)
 Nie wstrzymuje parsera, pobiera skrypt i wykonuje kod (np. podpina do onload)
 Async – nie gwarantuje kolejności (wywołuje po pobraniu)
 Defer – gwarantuje kolejność wywołań
 Dołączać z CDN (m.in. ASP
.NET AJAX, jQuery) - http://www.asp.net/ajaxlibrary/cdn.ashx
Skrypty
 Tylko lower case w miarę możliwości – kompresja
 <img> zamiast <IMG>, itp.
 Image sprites dla wielu mniejszych grafik
 background-position: 0 -120px
 Grafika - rozważyć data URI scheme (IE 8+)
 Narzędzia lub online – np. dataurl.net
 Do niewielkich grafik (base64, więc 40% większe)
 Zwłaszcza w CSS, kiedy może być dodatkowo cache’owane
Zmniejszanie liczby żądań
#hdr{border:1px solid #000;height:40px;
background:url(data:image/gif;base64,R0lGODlhAQAoANUAAAAAAP///wFUzgNV0ANVzwVX0QZY0gdY0gha
0wpb1Qxd1g1e1w9g2BFh2RJj2xVk3BZm3Rho3hpp4Bxr4h5t4x9u5CFw5SRx5yVz6Cd16Sl26it47C157S987jF97
zOA8jJ+8TWB8zaD9DiE9TqF9zqG9zyH+D2I+D6J+T+K+v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACoALAAAAAABACgAAAYlwBTqZCqRRqLQB+TpcDa
aDOZiqVAmkgjk4WgwFooE4mAoDAiCIAA7)
 Javascript
 Walidacja po stronie klienta
 Wyłączanie submit po kliknięciu
 Generowanie długich list (np. select i wiele elementów <option>)
 Unikać obiekt.inny.jeszczeinny.zmienna (pomocnicza zmienna)
 Wielokrotny document.write zamiast sklejania stringów
 textContent szybszy od innerHTML (jeśli element zawiera tekst)
 ASP
.NET 4.5 – unobtrusive validation
Zmniejszenie liczby żądań – c.d.
<code><add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms"/></code>
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms;
 Favicon.ico – lepiej żeby był (cache vs 404 za każdym razem)
 CSS – inline przy pierwszym wyświetleniu
 Mniej żądań przy pierwszym wejściu
 Skrypt ładowany inline – jeśli nie ustawione ciasteczko
 W Onload – pobierany dynamicznie (cache dla kolejnych żądań)
 Nie zamiast – plik potrzebny (cache)
Zmniejszenie liczby żądań – c.d.
<script type="text/javascript">
function getcss() {
var h = document.getElementsByTagName('head');
var l = document.createElement('link');
l.type = 'text/css';
l.rel = 'stylesheet';
l.href = 'css/file19.css';
h[0].appendChild(l);
}
</script>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Set-Cookie"
value="C=A;expires=Sat, 01-Jan-2050 00:00:00 GMT;path=/demo/css/" />
</customHeaders>
</httpProtocol>
</system.webServer>
 Określić <!DOCTYPE>
 Parser lookahead nie musi restartować
 Width i Height przy grafikach
 Rozmiary kolumn – tabele
 Charset (dla statycznych stron)
Szybkość renderowania strony
 Kiedy wiemy jaka będzie kolejna strona (np. „wizard”)
 W pageLoad (nie document ready)
Precaching - grafiki
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(window).load(function() {
var pre = new Image(0,0);
pre.src = "http://s1.domena.net/static/next1.jpg";
var prx = new Image(0, 0);
prx.src = "http://s2.domena.net/static/next2.jpg";
});
</script>
 <img>- dla innych formatów nie zadziała (MIME type)
 AJAX – można, ale tylko ta sama domena
 Dynamicznie element <script>
 Nie musi być dodawany do DOM
 Uwaga – parsowane i wywoływane
 Dynamicznie <link>
 Musi być w DOM
 Wczytywany (może być konflikt selektorów)
Precaching – CSS, JS
<script type="text/javascript">
function preload() {
var req = getreq();
if (req != null) {
req.open("GET", "/static/next.js", true);
req.send(null);
}
var rex = getreq();
if (rex != null) {
rex.open("GET", "/static/next.css", true);
rex.send(null);
}
}
</script>
<script type="text/javascript">
function preload() {
var scr = document.createElement("script");
scr.src = "http://s1.domena.net/ch02/next.js";
}
</script>
<script type="text/javascript">
function preload() {
var lnk = document.createElement("link");
lnk.rel = "stylesheet";
lnk.type = "text/css";
lnk.href = "http://s1.domena.net/next.css";
document.getElementsByTagName('head')[0].appendChild(lnk);
}
</script>
Caching
 Każdy ma nieco inną rolę (np. ASP
.NET vs http.sys vs SQL)
Wiele rodzajów cache
 Cache-Control: max-age lub Expires (dawniej)
 Jeśli nie ustawione oblicza
 Aktualny czas +10% różnicy między Last-Modified a aktualnym
 Po tym czasie – nadal na dysku, ale nie używane
 Conditional Get (If-Modified-Since)
 HTTP 304 – not modified
Statyczne pliki
GET /check.png HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
If-Modified-Since: Sat, 10 Jan 2012 10:52:45 GMT
If-None-Match: "80fc52fa8bb2c81:0"
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;
WOW64; Trident/5.0)
Host: www.domena.net
Connection: Keep-Alive
<system.webServer>
. . .
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
</staticContent>
</system.webServer>
 Cache-Control: no-cache
 Przeglądarka musi sprawdzić, ale może korzystać z cache (back/fwd)
 Cache-Control: no-store
 Całkowite wyłączenie (także back/forward)
Cache statyczny - wyłączanie
<location path="image.jpg">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
</system.webServer>
 Output cache
 VaryByParam, VaryByHeader – np. Accept-Language (dla różnych języków)
 VaryByControl (np. „src”, jeśli taką właściwość ma nasza User Control)
 Dla User Controls – ustawiać to samo ID na różnych stronach i Shared=true
 Jeśli shared=false to do porównywania ID brana także nazwa Page
Dynamiczna zawartość
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="dyn-client.aspx.cs" Inherits="dyn_client" %>
<%@ OutputCache Duration="86400" Location="Client" VaryByParam="None" %>
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache1Day" duration="86400"
location="Client" varyByParam="none" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
<%@ OutputCache CacheProfile="Cache1Day" %>
 Najprościej – VaryByCustom = „browser”
 Po swojemu - global.asax
 Jeśli chcemy np. jedną wersję dla wszystkich IE i jedną dla Webkit
Cache dla różnych przeglądarek
public override string GetVaryByCustomString(HttpContext context, string custom)
{
switch (custom.ToLower())
{
case "iemozilla":
switch (context.Request.Browser.Browser.ToLower())
{
case "ie":
case "blazer 3.0":
return "ie";
case "mozilla":
case "firebird":
case "firefox":
case "applemac-safari":
return "mozilla";
default:
return "default";
}
default:
return base.GetVaryByCustomString(context, custom);
}
}
Dynamiczna zawartość - wyłączanie
this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
this.Response.Cache.SetAllowResponseInBrowserHistory(true); // Aby nie było Expires (niepotrzebne)
this.Response.AppendHeader("Cache-Control", "no-store"); // Dla no-store
<%@ OutputCache Location=„None" %>
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
 Czasem chcemy mieć pewność, że dane aktualne
 Aspx, kod lub profil w web.config
 Domyślnie ASP
.NET ustawia Cache-Control: private
 Nie będzie cache’owane przez proxy
 Możliwe nadpisanie (Cache-Control: public)
 <%@ OutputCache Location=„Any” %>
 Location Downstream – tylko w przeglądarkach
Dynamiczna zawartość – c.d.
this.Response.Cache.SetMaxAge(age);
this.Response.Cache.SetExpires(DateTime.UtcNow + age);
this.Response.Cache.SetLastModified(DateTime.UtcNow);
this.Response.Cache.SetCacheability(HttpCacheability.Public);
this.Response.Cache.SetNoServerCaching();
Rozszerzalność
<caching>
<outputCache defaultProvider="AspNetInternalProvider">
<providers>
<add name="DiskCache"
type="Test.OutputCacheEx.DiskOutputCacheProvider, DiskCacheProvider"/>
</providers>
</outputCache>
</caching>
 ASP
.NET 4.0+ – możliwe np. zapisywanie na dysku
 Możliwa dynamiczna podmiana
 Np. top 10 w pamięci, reszta na dysku
 Stan tymczasowy strony, stan kontrolek serwerowych
 Często lepsze od sesji (baza przy farmie)
 LosFormatter – szybki dla typów string, hashtable, arraylist, pair, triple, int, boolean
 Dla pozostałych – BinaryFormatter (wolny), ale można napisać własny TypeConverter
 Lepiej – kolekcja prostych typów niż własny obiekt (bez TypeConvertera)
 Obecność elementu wykorzystywana m.in. do rozpoznania Page.IsPostback
 ViewStateMac – zabezpieczenie przed modyfikacjami
 Zabezpieczenie przez CSRF
 W Page_init – ViewState[userkey] = this.User.Identy.Name;
ViewState
 Ma tendencje do rozrastania się
 Może być prościej wysłać zapytanie niż uploadować dużo większy formularz
 Możliwość wyłączenia
 Od ASP
.NET 4 – nie tylko dla całej strony (EnableViewState), ale pojedynczych kontrolek
 ViewStateMode – enabled, disabled, inherit (domyślnie)
 Warto domyślnie wyłączyć (w web.config) i włączać tam, gdzie potrzeba
 ControlState – część, której nie można wyłączyć
ViewState - problemy
 Tag Transform, aby wyłączyć Control State
 Jeśli nie korzystamy z zaawansowanych funkcji kontrolki
ViewState – wyłączanie
public class ListViewNoCS : ListView
{
protected override object SaveControlState()
{
return null;
}
}
<pages>
. . .
<tagMapping>
<add tagType="System.Web.UI.WebControls.ListView"
mappedTagType="Samples.ListViewNoCS" />
</tagMapping>
</pages>
 Dla wolnych połączeń (np. klienci mobile) można przechowywać po
stronie serwera
 Można uzależnić to od typu połączenia lub rozmiaru ViewState
ViewState – wolne połączenia
protected override void SavePageStateToPersistenceMedium(object state)
{
string key = Guid.NewGuid().ToString();
this.ClientScript.RegisterHiddenField(ViewKeyName, key);
this.Cache[key] = state;
}
protected override object LoadPageStateFromPersistenceMedium()
{
string key = this.Request[ViewKeyName];
if (key == null)
throw new InvalidOperationException("Invalid ViewState Key");
object state = this.Cache[key];
if (state == null)
throw new InvalidOperationException("ViewState too old");
return state;
}
 Dla domeny - max 50, 10 KB / cookie
 Session lub persistent
 Domyślna wartość path - „/”
 Dołączane także do zawartości statycznej wszystkich plików!
 Ustawiać zawsze cookie.Path = „/katalog/”
 Bez ustawienia Domain
 IE – także wszystkie subdomeny
 Inne przeglądarki – tylko aktualna domena
 Lepiej ustawić cookie.Domain (unikanie błędów)
 Cookie.HttpOnly = true
 Cookie niewidoczne dla JS (mniej możliwości ataku)
 Powinno się ustawiać domyślnie dla wszystkich
 Cookie.Secure = true – wysyłane tylko przez SSL
 Jeśli nie możemy SSL – konwersja do Base64 (Convert.ToBase64String) i szyfrowanie symetryczne
Cookies
 IE8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+
 10 MB – IE, 5 MB - pozostałe
 2 typy
 Per-session (do zamkniecia okna)
 Per-domain
 Tylko string, ale można serializować do JSON
 Tylko klient – nie przesyłane do serwera
 Można dodać np. jako parametr wywołania usługi WCF
HTML 5 Web Storage
<script type="text/javascript">
sessionStorage.setItem('mykey', 'this is my value');
var item = sessionStorage.getItem('mykey')
</script>
 Kernel-mode driver - http.sys
 Znacznie szybszy (bez context switching, itd.)
 Domyślnie włączony dla zawartości statycznej
 Dla dynamicznej – OutputCache, ustawienie IIS
lub applicationHost.config
 Kiedy nie działa (najczęstsze)
 Zawartość z querystring
 Domyślny dokument (d.com zamiast d.com/default.htm)
 Włączona kompresja
 Domyślnie sliding, 120 sekund
 HKLMSystemCurrentControlSetServicesHttpParametersUriScavengerPeriod
 Warto zmienić w razie potrzeby (np. kilkanaście godzin) - ostrożnie
Windows Kernel Cache
 Domyślnie włączony – jeśli ustawione OutputCache
 Także dla żądań z querystring
 Dla własnych HttpHandlerów – włączyć User Mode Caching
 http://d.com/katalog/ zamiast http://d.com/katalog
 W przeciwnym wypadku HTTP 302
 Zapobiega cache’owaniu 3 różnych wersji
IIS Cache
 Podobnie jak IIS, ale VaryByParam może być custom
 Np. kontekst użytkownika
 Fragment Cache – OutputCache w User Control
 Substitution Cache
 Cała strona cache’owana, oprócz <asp:Substitution>
Cache ASP
.NET
<body>
Cached time: <%= DateTime.Now.ToString() %>
<br />Page time:
<asp:Substitution ID="sub" runat="server" MethodName="SubTime" />
</body>
public static string SubTime(HttpContext context)
{
return DateTime.Now.ToString();
}
 Plik
 Baza danych
 Konieczne włączenie Service Broker
Cache Dependency
CacheDependency depend = new CacheDependency(this.MapPath("~/depend.txt"));
this.CachePolicy.Dependency = depend;
using (SqlConnection conn = new SqlConnection(cs))
{
string sql = "dbo.GetInfo";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlCacheDependency dep = new SqlCacheDependency(cmd);
mygrid.DataSource = cmd.ExecuteReader();
mygrid.DataBind();
this.Response.AddCacheDependency(dep);
}
}
// SqlDependency.Start() w web.config
 Np. AppFabric
Cache Provider
public class MemoryCacheProvider : OutputCacheProvider
{
public override object Add(string key, object entry, DateTime utcExpiry)
{
object result = HttpRuntime.Cache[key];
if (result == null)
{
this.Set(key, entry, utcExpiry);
result = entry;
}
return result;
}
public override object Get(string key)
{
return HttpRuntime.Cache[key];
}
public override void Remove(string key)
{
HttpRuntime.Cache.Remove(key);
}
public override void Set(string key, object entry, DateTime utcExpiry)
{
HttpRuntime.Cache.Insert(key, entry, null, utcExpiry,
Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
}
<system.web>
<caching>
<outputCache>
<providers>
<add name="MemoryCacheProvider" type="Samples.MemoryCacheProvider" />
</providers>
</outputCache>
</caching>
</system.web>
 Kiedy chcemy jak najwięcej, jak najdłużej (na ile pamięć pozwoli)
 Omijamy logikę Cache Policy - szybkość
 Nie dla web farm
 WeakReference i GC
Statyczne pola – uproszczony cache
public static class Weak
{
public static WeakReference MyItem { get; set; }
public static readonly Object lockObject = new Object();
public static DataSet WeakData()
{
DataSet ds = null;
lock (lockObject)
{
if (MyItem != null)
ds = MyItem.Target as DataSet;
if (ds == null)
{
ds = new DataSet();
MyItem = new WeakReference(ds);
}
}
return ds;
}
}
IIS
 Domyślnie – jeden proces w3wp.exe
 AppPool - kilka procesów dla kolekcji aplikacji (Web
Garden)
 Maximum Worker Processes
 AppPool Recycling
 Tracimy cache, inproc session, static, …
 Domyślnie 29h
 Warto zmienić na określoną godzinę lub liczbę
obsłużonych requestów (NLB)
App Pool
 Wiele AppPools
 Dzielenie aplikacji na kilka puli
 Błąd w jednej puli nie ma wpływu na działanie drugiej
 Np. obsługa magazynu i aplikacja dla konsumentów
 Web Garden
 Ochrona przed błędami procesu w3wp – kilka procesów
 Uwaga - context-switching między wątkami szybszy niż między procesami!
 Konieczna duplikacja w pamięci danych takich jak cache czy pola static
 Zalecane max 1-2 worker procesy / CPU core
 Tylko, kiedy najistotniejsza ciągłość pracy
Kiedy najważniejsze jest działanie
 ASP
.NET – ISAPI Extension
 Duplikacja funkcjonalności
 2 odrębne pipeline’y
 Np. Logowanie, auth -> IIS, później ASP
.NET
 Trudniejsza konfiguracja
IIS6 + ASP
.NET (Classic mode)
Authentication
Basic NTLM Anon
...
Determine
Handler
...
SendResponse
HTTP
Request
HTTP
CGI
Static
File
ISAPI
Compre
ssion
Log
aspnet_isapi.dll
Authentication
Map
Handler
Forms Windows
...
ASPX
Trace
...
...
 Wyodrębnione komponenty z w3core.dll
 Niezależne dodawanie / usuwanie
funkcjonalności
 Np. auth – możemy dać własne zamiast
basic / LDAP
, itp..
 Lekki core
Architektura IIS 7
Authentication
...
ExecuteHandler
...
SendResponse
HTTP
Request
HTTP
Response
Authorization
UpdateCache
ResolveCache
Authentication
...
Determine
Handler
...
SendResponse
HTTP
Request
HTTP
Response
Basic
NTLM Anon
CGI
Static
File
ISAPI
Log Compre
ssion
Url
Authz
Output
Cache
Forward
er
Basic
40+
 Handler HTTP
 Mapowany dla rozszerzeń (np. aspx)
 Migracja z html do dynamic ->
można dodać mapowanie htm na
ASP
.NET
 Moduły HTTP
 ASP
.NET bezpośrednio w IIS Pipeline
 Np. sesja, uwierzytelnianie
dla zawartości statycznej, php, itp.
 Rozszerzalność przez .NET,
a nie ISAPI (C++)
 Usuwać niepotrzebne moduły
 Kolejność typów dokumentów w IIS
IIS 7 + ASP
.NET - Integrated Pipeline
ISAPI
Authentication
...
ExecuteHandler
...
SendResponse
Authorization
UpdateCache
ResolveCache
HTTP
Request
Anon
aspnet_isapi.dll
Authentication
Map
Handler
...
...
Forms Windows
ASPX
Trace
...
Basic
Compre
ssion
Log
Static
File
 Nowe w Windows Server 2008
 Rezerwacja minimalnej ilości pamięci lub CPU dla procesów
Windows System Resource Manager
 Bezpieczeństwo i mniej pobieranych danych
 X-Powered-By – IIS
 Nagłówek Server – tylko z kodu
 Etag – przy web farm można wyłączyć (często jest różny dla node’ów)
 X-Aspnet-Version - <httpRuntime enableVersionHeader="false"/>
Usuwanie nagłówków
public class HttpHeaderCleanup : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += OnPreSendRequestHeaders;
}
void OnPreSendRequestHeaders(object sender, EventArgs e)
{
HttpResponse response = HttpContext.Current.Response;
response.Headers.Remove("Server");
response.Headers.Remove("ETag");
}
public void Dispose()
{
}
}
 3-5% więcej CPU, ale generalnie warto
 Gzip (domyślny) lub deflate (mniejszy nagłówek)
Kompresja
<httpCompression directory="%SystemDrive%inetpubtempIIS Temporary Compressed Files" dynamicCompressionDisableCpuUsage="100">
<scheme name="gzip" dll="%Windir%system32inetsrvgzip.dll" staticCompressionLevel="9" dynamicCompressionLevel="5" />
<scheme name="deflate" dll="%Windir%system32inetsrvgzip.dll" staticCompressionLevel="9" dynamicCompressionLevel="5" />
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
</httpCompression>
 Lepsze dla SEO
 http.sys nawet przy querystringach
 Krótsze URLe w odpowiedziach
 Ukrywa technologię aplikacyjną
 IIS (URL Rewrite) lub ASP
.NET
URL Rewriting
 Pamiętać o botach (robots.txt,
sitemap.xml)
 Bandwidth Throttling
 Moduł BitRateThrottling do IIS
 Głównie dla mediów, ale również można
do innych typów danych
 Np. wolniej dla botów lub kawałek
dużego zdjęcia szybko
Szybkość transferu
public class Throttle : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostRequestHandlerExecute += OnPostRequestHandlerExecute;
}
void OnPostRequestHandlerExecute(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
HttpResponse response = context.Response;
if (response.ContentType == "application/x-zip-compressed")
{
HttpRequest request = context.Request;
if (!String.IsNullOrEmpty(request.ServerVariables["SERVER_SOFTWARE"]))
{
request.ServerVariables["ResponseThrottler-InitialSendSize"] = "20";
request.ServerVariables["ResponseThrottler-Rate"] = "10";
}
}
}
public void Dispose()
{
}
}
ASP
.NET
Tradycyjne przetwarzanie żądań
“thread-per-request” a.k.a. “post office”
Thread pool
Żądania
Busy
Busy Busy Busy
Przy load testach –
zużycie CPU
niewielkie, ale długi
czas odpowiedzi
Przetwarzanie asynchroniczne
a.k.a. “restaurant”
Żądania
Thread pool
 Domyślnie 12 / CPU
 Czasem zwiększenie liczby pomaga
 Wiąże się z tym koszt (start, pamięć, context switch)
 Ważniejsza optymalizacja istniejących
 Blokujące wywołania – baza, zewnętrzne usługi, I/O
 Przy obliczeniach (CPU) nie pomoże!
Worker Threads
 Domyślnie przetwarzanie
synchroniczne (1 wątek
całe lifecycle)
 Async point
Synchronicznie i asynchronicznie
Asynchronicznie – web forms (APM)
<%@ Page Async="true„ AsyncTimeout=„30” Language="C#" AutoEventWireup="true" CodeFile="sql-async.aspx.cs" Inherits="sql_async" %>
public const string ConnString = "Data Source=.;Integrated Security=True;Async=True";
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask pat = new PageAsyncTask(BeginAsync, EndAsync, null, null, true);
this.RegisterAsyncTask(pat);
}
private IAsyncResult BeginAsync(object sender, EventArgs e, AsyncCallback cb, object state)
{
SqlConnection conn = new SqlConnection(ConnString);
conn.Open();
SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:01'", conn);
IAsyncResult ar = cmd.BeginExecuteNonQuery(cb, cmd);
return ar;
}
private void EndAsync(IAsyncResult ar)
{
using (SqlCommand cmd = (SqlCommand)ar.AsyncState)
{
using (cmd.Connection)
{
int rows = cmd.EndExecuteNonQuery(ar);
}
}
}
 Task – zaczyna od razu
 APM – kolejkuje do async point
Asynchronicznie – web forms (Task)
public const string ConnString = "Data Source=.;Integrated Security=True;Async=True";
protected async void Page_PreRender(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(ConnString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:01'", conn))
{
await Task.Factory.FromAsync<int>(cmd.BeginExecuteNonQuery,
cmd.EndExecuteNonQuery, null);
}
}
}
 Najlepiej agregować (np. kilka zapytań w procedurze skł.)
 Wywoływane równolegle lub jedno po drugim
Asynchroniczne strony – wiele zadań
protected void Page_Load(object sender, EventArgs e)
{
// Dwa pierwsze – równolegle. Następnie BeginAsync3 (ostatni parametr PageAsyncTask)
PageAsyncTask pat = new PageAsyncTask(BeginAsync1, EndAsync1, null, null, true);
this.RegisterAsyncTask(pat);
pat = new PageAsyncTask(BeginAsync2, EndAsync2, null, null, true);
this.RegisterAsyncTask(pat);
pat = new PageAsyncTask(BeginAsync3, EndAsync3, null, null, false);
this.RegisterAsyncTask(pat);
}
 Czasem potrzeba zarejestrowania zadania po zakończeniu poprzedniego
 Np. drugie wywołanie usługi po zakończeniu poprzedniego
 Konieczne wywołanie ExecuteRegeisteredAsyncTasks()
 Można także wywołać, aby wymusić wywołanie przed async point
 Dla Task – zwyczajnie jeden po drugim z await
Późniejsza rejestracja
private void EndAsync(IAsyncResult ar)
{
using (SqlCommand cmd = (SqlCommand)ar.AsyncState)
{
using (cmd.Connection)
{
int rows = cmd.EndExecuteNonQuery(ar);
}
}
PageAsyncTask pat = new PageAsyncTask(BeginAsync2, EndAsync2, null, null, true);
this.RegisterAsyncTask(pat);
this.ExecuteRegisteredAsyncTasks();
}
 Usługi  Pliki
Inne operacje
protected async void Page_Load(object sender, EventArgs e)
{
var terra = new TerraServiceSoapClient();
Place place = new Place()
{
City = "Seattle",
State = "WA",
Country = "US"
};
var result = await terra.GetPlaceFactsAsync(place);
PlaceFacts facts = result.Body.GetPlaceFactsResult;
this.LA.Text = String.Format("Latitude: {0:0.##}", facts.Center.Lat);
this.LO.Text = String.Format("Longitude: {0:0.##}", facts.Center.Lon);
}
// Dla web requestów:
// var r = WebRequest.Create(„http://…”);
// var res = await r.GetResponseAsync();
private IAsyncResult BeginAsync(object s, EventArgs e, AsyncCallback cb, object s)
{
FileStream fs = new FileStream(this.Server.MapPath("csg.png"),
FileMode.Open, FileAccess.Read, FileShare.Read, 4096,
FileOptions.Asynchronous | FileOptions.SequentialScan);
this.Data = new byte[64 * 1024];
IAsyncResult ar = fs.BeginRead(this.Data, 0, this.Data.Length, cb, fs);
return ar;
// dla podejścia Task:
// int size = await fs.ReadAsync(this.Data, 0, this.Data.Length);
}
Async controller – przed MVC 4
public class WeatherAsyncController : AsyncController
{
private string _forecastUrl = "http://weather.yahooapis.com/forecastjson?w=523920&u=c";
public void IndexAsync()
{
var webClient = new WebClient();
AsyncManager.OutstandingOperations.Increment();
webClient.DownloadStringCompleted += (sender, evt) =>
{
// capture result when web service completes
AsyncManager.Parameters["json"] = evt.Result;
AsyncManager.OutstandingOperations.Decrement();
// Exception handling - challenge...
};
// async call
webClient.DownloadStringAsync(new Uri(_forecastUrl));
}
public ActionResult IndexCompleted(string json)
{
WeatherData weather = new JavaScriptSerializer().Deserialize<WeatherData>(json);
return View("Weather", weather);
}
}
Async controller – MVC 4
public class WeatherTaskAsyncController : AsyncController
{
private string _forecastUrl = "http://weather.yahooapis.com/forecastjson?w=523920&u=c";
public async Task<ActionResult> Index()
{
string json = await new WebClient().DownloadStringTaskAsync(_forecastUrl);
WeatherData weather = new JavaScriptSerializer().Deserialize<WeatherData>(json);
return View("Weather", weather);
}
}
 Możliwość wywołania kodu równolegle
 Po wyrenderowaniu strony lub w trakcie
 ThreadPool.QueueUserWorkItem()
 Zużywa wątki z AppPool
 1 wątek w tle + kolejka
 Typowy consumer - producer
 Np. logowanie (nie wymagane 100% działanie)
 Bardziej krytyczne zadania – np. Service Broker lub Azure Worker + kolejka
 Przy wielu wątkach – warto ReaderWriterLockSlim
 EnterReadLock / EnterWriteLock (mniejsze ryzyko zakleszczenia)
 Przykład
Background Worker Thread
 InProc
 Najszybsza, ale load balancer tylko sticky
 Nie odporna na awarie sprzętu
 StateServer
 Web farm – ok, ale single point of failure
 SQL (+SQL Agent do usuwania)
 Możliwe przyspieszenie przez <sessionState compressionEnabled=„true” />
 <%@ Page EnableSessionState=„false” @> - ale i tak update (timeout)
 <%@ Page EnablesessionState=„ReadOnly” @> - mniej locków; ta sama SP
, która odczytuje
 Przyspieszyć zapis do logu (podział na dyski, SSD, itp.)
 PartitionResolver (wybór conn str na podst id sesji) i SessionIDManager (id sesji z nr maszyny)
 Mimo wszystko niezbyt skalowalne – patrz: AppFabric session provider
Sesja
Control ID
 Możliwość kontroli identyfikatorów (klienckich) kontrolek serwerowych
 Control.ClientIdMode
 Legacy
 Static
 Predictable
 Inherit (domyślne dla kontrolek)
 Kolekcje – ClientIDRowSuffix
 Dla całej strony lub kontrolki
 Ostrożnie – duplikacja, długość
 Możliwość zmiany markupu kontrolki serwerowej
 Np. GridView nie z tabelkami, ale na floatach
Control Adapter
// Zamiana URL w Image na małe litery
public class ImageControlAdapter : WebControlAdapter
{
public ImageControlAdapter()
{
}
protected override void BeginRender(System.Web.UI.HtmlTextWriter writer)
{
Image image = Control as Image;
if ((image != null) && !String.IsNullOrEmpty(image.ImageUrl))
{
if (!image.ImageUrl.StartsWith("http") && !image.ImageUrl.StartsWith("data:"))
{
image.ImageUrl = this.Page.ResolveUrl(image.ImageUrl).ToLower();
}
}
base.BeginRender(writer);
}
}
// adapter.browser
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Image"
adapterType="Samples.ImageControlAdapter" />
<adapter controlType="System.Web.UI.WebControls.Panel"
adapterType="Samples.NoIdControlAdapter" />
<adapter controlType="System.Web.UI.WebControls.Label"
adapterType="Samples.NoIdControlAdapter" />
<adapter controlType="System.Web.UI.WebControls.HyperLink"
adapterType="Samples.NoIdControlAdapter" />
</controlAdapters>
</browser>
</browsers>
 Np. wyłączenie
domyślnego
generowania ID
Control Adapter c.d. – usuwanie ID
public class NoIdControlAdapter : WebControlAdapter
{
protected override void Render(HtmlTextWriter writer)
{
PageBase page = this.Page as PageBase;
if ((page != null) && page.RemoveIds &&
(this.Control.ClientIDMode != ClientIDMode.Static))
{
HtmlTextWriter noIdwriter = new NoIdHtmlWriter(writer);
base.RenderBeginTag(noIdwriter);
base.RenderContents(writer);
base.RenderEndTag(noIdwriter);
}
else
{
base.Render(writer);
}
}
}
public class NoIdHtmlWriter : HtmlTextWriter
{
public NoIdHtmlWriter(TextWriter writer)
: base(writer)
{
}
public override void AddAttribute(HtmlTextWriterAttribute key, string value)
{
if (key != HtmlTextWriterAttribute.Id)
base.AddAttribute(key, value);
}
}
public class PageBase : Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.RemoveIds = true;
}
public bool RemoveIds { get; set; }
}
 Np. do zwracania zapisanego w bazie HTML
 Bez cyklu życia ASP
.NET – szybciej
 Asynchronicznie – uczestniczy w każdym żądaniu!
 IsReusable – czy jedna instancja może być dla wielu żądań
HTTP Handler w .NET
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Data;
using System.Web;
using System.Data.SqlClient;
public class Handler : IHttpAsyncHandler {
public const string ConnString =
"Data Source=.;Initial Catalog=Sample;Integrated Security=True;Async=True";
HttpContext Context { get; set; }
public void ProcessRequest(HttpContext context)
{
}
public IAsyncResult BeginProcessRequest(HttpContext context,
AsyncCallback cb, object extraData)
{
this.Context = context;
int fileid = 0;
string id = context.Request.QueryString["id"];
if (!String.IsNullOrEmpty(id))
 Krótsze adresy w kodzie
 http.sys caching
 Łączenie np. z ASP
.NET MVC (MapRoute / MapPageRoute)
Routing
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add("Category", new Route("{category}", new PageRouteHandler("~/1.3 Routing.aspx")));
RouteTable.Routes.Add("CategoryAndPage", new Route("{category}/{page}", new PageRouteHandler("~/1.3 Routing.aspx")));
}
protected void Page_Load(object sender, EventArgs e)
{
lblCategory.Text = RouteData.Values["category"] as string;
lblPage.Text = RouteData.Values["page"] as string;
}
 Klasyczne
 this.Response.Redirect("~/pages/error.aspx", true);
True – czy zakończyć request
 this.Response.RedirectPermanent
 this.Response.RedirectToRoute
 Server.Transfer(„~/pages/error.aspx”, false)
 False – czy przekazać parametry z obecnej strony
 True – dla ViewState wyrzuci exception; tylko dla querystring
 Cross-page postback
Przekierowania
<asp:Button runat="server" PostBackUrl="~/pages/otherpage.aspx" Text="Submit" />
 Zawartość z Render() buforowana i zwracana na koniec
 Dla długotrwałych zadań może wymagać czasu
 Najlepiej – z Ajax
 Response.Flush() – wysłanie odpowiedzi z bufora
 Przed Render() nic w nim nie ma!
Wczesny flush odpowiedzi
 W OnPreRender
 Ręczny zapis odpowiedzi
 Wyrenderowanie wybranych kontrolek serwerowych
 Usunięcie wyrenderowanych kontrolek (aby nie było duplikacji po Render)
 Długotrwałe zadanie w OnPreRender (async) lub synchronicznie po
PreRender (po async point)
Wczesny flush – c.d.
<html>
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="test" Text="testing" />
</div>
</form>
</body>
</html>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.Response.Write("<!DOCTYPE html PUBLIC " +
""-//W3C//DTD XHTML 1.0 Transitional//EN" " +
""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">n");
this.Response.Write("<html xmlns="http://www.w3.org/1999/xhtml">n");
HtmlTextWriter writer = this.CreateHtmlTextWriter(this.Response.Output);
this.Header.RenderControl(writer);
writer.Flush();
this.Response.Flush();
this.Controls.Remove(this.Header);
Thread.Sleep(2000);
}
Wczesny flush - odpowiedź
HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 03 Feb 2012 12:16:11 GMT
161
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1">
<link href="App_Themes/mkt/common.css" type="text/css" rel="stylesheet" />
<title>
Testing
</title>
<script type="text/javascript" src="test.js"></script>
</head>
146
<body>
<form name="form1" method="post" action="flush1.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwULLTE0NDMxNDM0MTlkZA0loE+taD1AMKhxDNDZZLZADwxZqGnPPbIF8Mylq4PV" />
</div>
<div>
<span id="test">testing</span>
</div>
</form>
</body>
</html>
0
Minification dla dynamicznych
public class MinifyStream : Stream
{
private StreamWriter Writer { get; set; }
private Decoder Utf8Decoder { get; set; }
public MinifyStream(Stream stream)
{
this.Writer = new StreamWriter(stream, Encoding.UTF8);
this.Utf8Decoder = Encoding.UTF8.GetDecoder();
}
public override void Write(byte[] buffer, int offset, int count)
{
int characterCount = this.Utf8Decoder.GetCharCount(buffer, offset, count);
char[] result = new char[characterCount];
int decodedCount = this.Utf8Decoder.GetChars(buffer, offset, count, result, 0);
if (decodedCount <= 0)
return;
// ... wyfiltrowanie zbędnych znaków i zapis do this.Writer
}
public override void Close()
{
this.Writer.Flush();
this.Writer.Close();
base.Close();
}
public override void Flush()
{
this.Writer.Flush();
}
// ...
}
// W module HttpModule
private void Sample_PostRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpResponse response = application.Context.Response;
if(response.ContentType == "text/html")
response.Filter = new MinifyStream(response.Filter);
}
 Page.IsPostBack
 Rozpoznawanie odświeżenia strony
Unikanie niepotrzebnej pracy
protected virtual bool IsRefresh
{
get
{
return this.Request.Headers["Pragma"] == "no-cache" ||
this.Request.Headers["Cache-Control"] == "max-age=0";
}
}
 Response.IsClientConnected
 Czy przeglądarka jeszcze czeka na odpowiedź, czy została zamknięta?
 Warto sprawdzić przed długotrwałą operacją na bazie
 <compilation batch=true />
 True – niewiele pakietów
 False – każda strona w osobnym assembly (wolniej, ale łatwiej zmiany)
 Wyłączyć debug mode!
 Można wymusić w machine.config
Inne
<system.web>
<deployment retail="true" />
</system.web>
Auto-start aplikacji
//applicationHost.config
<serviceAutoStartProviders>
<add name="PrewarmMyCache"
type="MyNamespace.CustomInitialization, MyLibrary" />
</serviceAutoStartProviders>
public class CustomInitialization : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
// Nasza inicjalizacja.
}
}
 Dawniej – Global.asax i Application_Load
 IIS 7.5 i Windows Server 2008 R2
 Książka Ultra-Fast ASP
.NET 4.5
 Książka Ultra-Fast ASP
.NET
 MSDN – ASP
.NET Performance
Zasoby
© 2012 Microsoft Corporation. Wszelkie prawa zastrzeżone.
Microsoft, Windows oraz inne nazwy produktów są lub mogą być znakami towarowymi lub zastrzeżonymi znakami towarowymi firmy Microsoft
w Stanach Zjednoczonych i innych krajach. Zamieszczone informacje mają charakter wyłącznie informacyjny. FIRMA MICROSOFT NIE UDZIELA
ŻADNYCH GWARANCJI (WYRAŻONYCH WPROST LUB DOMYŚLNIE), W TYM TAKŻE USTAWOWEJ RĘKOJMI ZA WADY FIZYCZNE I PRAWNE, CO DO
INFORMACJI ZAWARTYCH W TEJ PREZENTACJI.

Mais conteúdo relacionado

Mais procurados

"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbaćBartosz Ratajczyk
 
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Bartlomiej Zass
 
Tomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureTomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureWebhosting.pl
 
Bohater UI bez front end developera ?
Bohater UI bez front end developera ?Bohater UI bez front end developera ?
Bohater UI bez front end developera ?Quick-Solution
 
[PLCUG] Power shell (PL)
[PLCUG] Power shell (PL)[PLCUG] Power shell (PL)
[PLCUG] Power shell (PL)Jaroslaw Sobel
 
Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?tkryskiewicz
 
Jak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńJak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńPaweł Kondraciuk
 
Wprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPWprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPPHPCon Poland
 
Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Tomasz Dziuda
 
Testowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackTestowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackThe Software House
 
Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaWojciech Lichota
 
Seam framework in_action
Seam framework in_actionSeam framework in_action
Seam framework in_actionMichał Orman
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxDawid Rusnak
 
Angular 4 pragmatycznie
Angular 4 pragmatycznieAngular 4 pragmatycznie
Angular 4 pragmatycznieSages
 
DynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychDynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychThe Software House
 

Mais procurados (19)

"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
 
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)
 
Tomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureTomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows Azure
 
Bohater UI bez front end developera ?
Bohater UI bez front end developera ?Bohater UI bez front end developera ?
Bohater UI bez front end developera ?
 
[PLCUG] Power shell (PL)
[PLCUG] Power shell (PL)[PLCUG] Power shell (PL)
[PLCUG] Power shell (PL)
 
AJAX - wdw1
AJAX - wdw1AJAX - wdw1
AJAX - wdw1
 
Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?
 
Jak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńJak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzień
 
Wprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPWprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHP
 
Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014
 
Testowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackTestowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStack
 
Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użycia
 
Seam framework in_action
Seam framework in_actionSeam framework in_action
Seam framework in_action
 
Behat
BehatBehat
Behat
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/Redux
 
Silverlight i PHP
Silverlight i PHPSilverlight i PHP
Silverlight i PHP
 
Angular 4 pragmatycznie
Angular 4 pragmatycznieAngular 4 pragmatycznie
Angular 4 pragmatycznie
 
DynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychDynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornych
 

Destaque

150527 cuestionario evaluación club de internet i
150527 cuestionario evaluación club de internet i150527 cuestionario evaluación club de internet i
150527 cuestionario evaluación club de internet iRoberto GARCÍA ARRIBAS
 
Carta de España Nº 674 Septiembre 2011
Carta de España Nº 674 Septiembre 2011Carta de España Nº 674 Septiembre 2011
Carta de España Nº 674 Septiembre 2011Cext
 
Comte de Rius, Química
Comte de Rius, QuímicaComte de Rius, Química
Comte de Rius, Químicaclara87
 
Helpedia 2.0
Helpedia 2.0Helpedia 2.0
Helpedia 2.0Helpedia
 
Ferreteria gutierrez 1
Ferreteria gutierrez 1Ferreteria gutierrez 1
Ferreteria gutierrez 1carmitagarcia
 
Implementasi kartu jakarta sehat
Implementasi kartu jakarta sehatImplementasi kartu jakarta sehat
Implementasi kartu jakarta sehatJoan Mahulae
 
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...PrensaDMB
 
En torno a la cultura escrita – margaret meek- Leidy Melo
En torno a la cultura escrita – margaret meek- Leidy MeloEn torno a la cultura escrita – margaret meek- Leidy Melo
En torno a la cultura escrita – margaret meek- Leidy MeloLeidy Melo
 
Cómo hacer sal de colores.
Cómo hacer sal de colores.Cómo hacer sal de colores.
Cómo hacer sal de colores.Ritamv91
 
Caracteristicas de los modulos fotovoltaicos
Caracteristicas de los modulos fotovoltaicosCaracteristicas de los modulos fotovoltaicos
Caracteristicas de los modulos fotovoltaicosKarolayn Farfan Cruz
 
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAPVirtual Forge
 
Paso a paso: Como hacer una pagina en Jimdo
Paso a paso: Como hacer una pagina en JimdoPaso a paso: Como hacer una pagina en Jimdo
Paso a paso: Como hacer una pagina en JimdoGabriel Tibaquira
 
Manual del-equipo-para-kendo
Manual del-equipo-para-kendoManual del-equipo-para-kendo
Manual del-equipo-para-kendoclubkendovigo
 
Training Needs Analysis Modified
Training Needs Analysis ModifiedTraining Needs Analysis Modified
Training Needs Analysis ModifiedPhil Mayor
 
Catalog LEICA Silverline | Optics Trade | 2014
Catalog LEICA Silverline | Optics Trade | 2014Catalog LEICA Silverline | Optics Trade | 2014
Catalog LEICA Silverline | Optics Trade | 2014Optics-Trade
 
Seminar Social Media Marketing WS11/12
Seminar Social Media Marketing WS11/12Seminar Social Media Marketing WS11/12
Seminar Social Media Marketing WS11/12Marco Jakob
 

Destaque (20)

Proyecto de verano delicias
Proyecto de verano deliciasProyecto de verano delicias
Proyecto de verano delicias
 
150527 cuestionario evaluación club de internet i
150527 cuestionario evaluación club de internet i150527 cuestionario evaluación club de internet i
150527 cuestionario evaluación club de internet i
 
Carta de España Nº 674 Septiembre 2011
Carta de España Nº 674 Septiembre 2011Carta de España Nº 674 Septiembre 2011
Carta de España Nº 674 Septiembre 2011
 
Elvens kall
Elvens kallElvens kall
Elvens kall
 
Phone android jelly bean
Phone   android jelly beanPhone   android jelly bean
Phone android jelly bean
 
Comte de Rius, Química
Comte de Rius, QuímicaComte de Rius, Química
Comte de Rius, Química
 
Helpedia 2.0
Helpedia 2.0Helpedia 2.0
Helpedia 2.0
 
Ferreteria gutierrez 1
Ferreteria gutierrez 1Ferreteria gutierrez 1
Ferreteria gutierrez 1
 
Implementasi kartu jakarta sehat
Implementasi kartu jakarta sehatImplementasi kartu jakarta sehat
Implementasi kartu jakarta sehat
 
Nbolmnf
NbolmnfNbolmnf
Nbolmnf
 
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...
Equipo de trabajo de Hospital Pirovano - Jornada "Convivencia Escolar para un...
 
En torno a la cultura escrita – margaret meek- Leidy Melo
En torno a la cultura escrita – margaret meek- Leidy MeloEn torno a la cultura escrita – margaret meek- Leidy Melo
En torno a la cultura escrita – margaret meek- Leidy Melo
 
Cómo hacer sal de colores.
Cómo hacer sal de colores.Cómo hacer sal de colores.
Cómo hacer sal de colores.
 
Caracteristicas de los modulos fotovoltaicos
Caracteristicas de los modulos fotovoltaicosCaracteristicas de los modulos fotovoltaicos
Caracteristicas de los modulos fotovoltaicos
 
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP
10 GOLDEN RULES FOR CODING AUTHORIZATION CHECKS IN ABAP
 
Paso a paso: Como hacer una pagina en Jimdo
Paso a paso: Como hacer una pagina en JimdoPaso a paso: Como hacer una pagina en Jimdo
Paso a paso: Como hacer una pagina en Jimdo
 
Manual del-equipo-para-kendo
Manual del-equipo-para-kendoManual del-equipo-para-kendo
Manual del-equipo-para-kendo
 
Training Needs Analysis Modified
Training Needs Analysis ModifiedTraining Needs Analysis Modified
Training Needs Analysis Modified
 
Catalog LEICA Silverline | Optics Trade | 2014
Catalog LEICA Silverline | Optics Trade | 2014Catalog LEICA Silverline | Optics Trade | 2014
Catalog LEICA Silverline | Optics Trade | 2014
 
Seminar Social Media Marketing WS11/12
Seminar Social Media Marketing WS11/12Seminar Social Media Marketing WS11/12
Seminar Social Media Marketing WS11/12
 

Semelhante a Optymalizacja aplikacji ASP.NET

W3 Total Cache - skuteczne przyśpieszanie WordPressa
W3 Total Cache - skuteczne przyśpieszanie WordPressaW3 Total Cache - skuteczne przyśpieszanie WordPressa
W3 Total Cache - skuteczne przyśpieszanie WordPressaBartosz Romanowski
 
Zhakuj swojego Wordpressa, WordUP Trojmiasto
Zhakuj swojego Wordpressa, WordUP TrojmiastoZhakuj swojego Wordpressa, WordUP Trojmiasto
Zhakuj swojego Wordpressa, WordUP Trojmiastosecman_pl
 
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótka
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótkaWebpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótka
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótkaMarcin Gajda
 
Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!The Software House
 
WebView security on iOS (PL)
WebView security on iOS (PL)WebView security on iOS (PL)
WebView security on iOS (PL)lpilorz
 
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaThymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaMaciej Ziarko
 
Piątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTPPiątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTPXSolve
 
HTML5 - now or later
HTML5 - now or laterHTML5 - now or later
HTML5 - now or laterKasia Drzyzga
 
WebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowWebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowMarcin Dembowski
 
Pocałunek śmierci
Pocałunek śmierciPocałunek śmierci
Pocałunek śmierciDivante
 
Websites vs Cloud Services - OLMUG
Websites vs Cloud Services - OLMUGWebsites vs Cloud Services - OLMUG
Websites vs Cloud Services - OLMUGBart Zaremba
 
Laravelowe paczki do uwierzytelniania
Laravelowe paczki do uwierzytelnianiaLaravelowe paczki do uwierzytelniania
Laravelowe paczki do uwierzytelnianiaLaravel Poland MeetUp
 
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiProjektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiAntoni Orfin
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawyApptension
 

Semelhante a Optymalizacja aplikacji ASP.NET (20)

W3 Total Cache - skuteczne przyśpieszanie WordPressa
W3 Total Cache - skuteczne przyśpieszanie WordPressaW3 Total Cache - skuteczne przyśpieszanie WordPressa
W3 Total Cache - skuteczne przyśpieszanie WordPressa
 
Zhakuj swojego Wordpressa, WordUP Trojmiasto
Zhakuj swojego Wordpressa, WordUP TrojmiastoZhakuj swojego Wordpressa, WordUP Trojmiasto
Zhakuj swojego Wordpressa, WordUP Trojmiasto
 
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótka
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótkaWebpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótka
Webpack - Czym jest webpack i dlaczego chcesz go używać? - wersja krótka
 
W 3 sekundy do setki
W 3 sekundy do setkiW 3 sekundy do setki
W 3 sekundy do setki
 
Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!
 
WebView security on iOS (PL)
WebView security on iOS (PL)WebView security on iOS (PL)
WebView security on iOS (PL)
 
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaThymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
 
Piątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTPPiątek z XSolve - Bezpieczne nagłówki HTTP
Piątek z XSolve - Bezpieczne nagłówki HTTP
 
Wydajny frontend 2023
Wydajny frontend 2023Wydajny frontend 2023
Wydajny frontend 2023
 
Android i REST
Android i RESTAndroid i REST
Android i REST
 
HTML5 - now or later
HTML5 - now or laterHTML5 - now or later
HTML5 - now or later
 
TGT#20 - Ataki XSS - Robert Charewicz
TGT#20 - Ataki XSS - Robert CharewiczTGT#20 - Ataki XSS - Robert Charewicz
TGT#20 - Ataki XSS - Robert Charewicz
 
WebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowWebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, Tomorrow
 
Pocałunek śmierci
Pocałunek śmierciPocałunek śmierci
Pocałunek śmierci
 
HTML5: Atak i obrona
HTML5: Atak i obronaHTML5: Atak i obrona
HTML5: Atak i obrona
 
Web Cache
Web CacheWeb Cache
Web Cache
 
Websites vs Cloud Services - OLMUG
Websites vs Cloud Services - OLMUGWebsites vs Cloud Services - OLMUG
Websites vs Cloud Services - OLMUG
 
Laravelowe paczki do uwierzytelniania
Laravelowe paczki do uwierzytelnianiaLaravelowe paczki do uwierzytelniania
Laravelowe paczki do uwierzytelniania
 
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiProjektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawy
 

Optymalizacja aplikacji ASP.NET

  • 2.  Skalowalność – ilu użytkowników może pracować jednocześnie?  Aplikacja może obsługiwać tysiące użytkowników, ale być wolna  Zmiany w sprzęcie, infrastrukturze sieciowej, itp. (istotna architektura!)  Wydajność – jak szybko ładują się strony?  Zasada 8 sekund  Liczy się odczuwalna wydajność (np. reklamy dopiero na końcu)  To także:  Szybkość wprowadzania poprawek i zmian  Łatwość wdrażania aplikacji  Proces wytwórczy  …  Architektura Bing vs strony domowej (można przesadzić) Skalowalność i wydajność
  • 3.  Lokalny cache przeglądarki  DNS – cache / zapytanie  Proxy – visible / transparent  Cache serwera  System - http.sys  IIS  ASP .NET (dane w ram / z dysku)  Cache SQL Server  Dyski – SSD / zwykłe / cache… Komponenty wpływające na wydajność
  • 4.  Odczuwalna wydajność  Kolejność ładowania, AJAX  Mniej żądań do serwera  Walidacja po stronie klienta, bundling, itp.  Cache na wszystkich warstwach  Minimalizacja blokujących wywołań  Synchroniczne operacje zapisu do bazy, zewnętrzne usługi, itp.  Optymalizacja I/O (dyski, itp.)  Także partycjonowanie / sharding, itp. Najważniejsze zasady przy optymalizacji
  • 6.  Maximum Transfer Unit (MTU) - rozmiar okna odpowiedzi  Od 500 do 1500 bajtów  Dużo komunikatów SYN-ACK  TCP Slow Start (RFC 5681)  Bardzo kosztowne nawiązywanie połączenia  Długi okres między pierwszym pakietem a kolejnym  Zapobiega przeciążeniu sieci  Jak najmniej nowych połączeń (np. żądania plików)  HTTP Keep-Alives – domyślnie w IIS 120 sekund  Np. przy długich formularzach można zwiększyć (ostrożnie) Protokół TCP
  • 7. TCP Slow Start - przykład  IE Developer tools (F12)  Żółte – slow start + pierwszy pakiet odpowiedzi  Niebieski – reszta odpowiedzi  Jeśli <img> było w pierwszym pakiecie
  • 8.  <head>  Przeglądarka nie wyświetli nic przed pobraniem całego nagłówka  „Lookahead” – ograniczenia  Jak najwięcej w <body>  Nawet <link> i <style> (niezgodne ze specyfikacją, ale działa)  Kolejność  Np. duży baner reklamowy na górze strony – w kodzie lepiej niżej Struktura strony
  • 9.  Ustawiać width i height dla <img>! Późne ładowanie - placeholder <img id="myimg" width="50" height="50" /> <!-- Klasycznie --> <script type="text/javascript"> document.getElementById("myimg").src = "myimage.jpg"; </script> <img id="Img1" width="50" height="50" /> <!-- w jQuery --> <script type="text/javascript"> $("#myimg").attr("src", "myimage.jpg"); </script>
  • 10. Późne ładowanie – preloading <!-- Preloading - na górze strony lub w onload (jeśli może być później) --> <script type="text/javascript"> var myimg = new Image(); myimg.src = "myimage.jpg"; </script> <!-- Niżej na stronie, będzie załadowane z cache (dla rolloverów) --> <img src="myimage.jpg" width="50" height="50" />
  • 11.  Wielkość liter  W Unix – system plików case sensitive  Niektóre serwery cache’ują oddzielnie  Może spowodować wysłanie dwóch żądań  Można dołączyć moduł http, który to poprawia  Referencje do tej samej domeny  Przekierowanie z domena.com/gfx.jpg na www.domena.com/gfx.jpg Cache i URL <img src="myimage.jpg" width="50" height="50" /> <img src="myimage.JPG" width="50" height="50" />
  • 12.  Przeglądarki mają do 6 równoległych połączeń dla domeny  Przed IE8 – tylko 2!  Można podzielić pliki na kilka domen  img.mojadomena.com, css.mojadomena.com, itp.  Aliasy lub inne usługi cookieless (np. Azure Blob) Przetwarzanie żądań <img src="q1.gif" height="16" width="16" /> <img src="q2.gif" height="16" width="16" /> <img src="q3.gif" height="16" width="16" /> <img src="q4.gif" height="16" width="16" /> <img src="q5.gif" height="16" width="16" /> <img src="q6.gif" height="16" width="16" /> <img src="q7.gif" height="16" width="16" /> <img src="q8.gif" height="16" width="16" /> <img src="q9.gif" height="16" width="16" /> <img src="q10.gif" height="16" width="16" />
  • 13.  ok. 30% zwiększenie szybkości wczytywania Podział plików na kilka domen <img src="q1.gif" height="16" width="16" /> <img src="q2.gif" height="16" width="16" /> <img src="q3.gif" height="16" width="16" /> <img src="q4.gif" height="16" width="16" /> <img src="q5.gif" height="16" width="16" /> <img src="http://mojadomena.net/samples/ch02/q6.gif" height="16" width="16" /> <img src="http://mojadomena.net/samples/ch02/q7.gif" height="16" width="16" /> <img src="http://mojadomena.net/samples/ch02/q8.gif" height="16" width="16" /> <img src="http://mojadomena.net/samples/ch02/q9.gif" height="16" width="16" /> <img src="http://mojadomena.net/samples/ch02/q10.gif" height="16" width="16" />
  • 14.  Jeśli kilka aliasów – mechanizm generowania powtarzalnych url  Plik grafika.jpg zawsze z s1.domena.com, grafika3.jpg z s2.domena.com, itp.  Wewnątrz własnej kontrolki  Control adapter dla Image (dalej) ASP .NET i podział na kilka domen private string _src; private static string[] subdomains = { "http://s1.12titans.net", "http://s2.12titans.net", "http://s3.12titans.net" }; public string src { get { HttpContext ctx = HttpContext.Current; if (ctx.Request.Url.Host != "localhost") { if (!String.IsNullOrEmpty(this._src) && !this._src.StartsWith("http") && !this._src.StartsWith("data:")) { int n = Math.Abs(this._src.GetHashCode()) % subdomains.Length; return subdomains[n] + this._src; } } return this._src; } set { this._src = ResolveUrl(value).ToLowerInvariant(); } }
  • 15.  Skrypty inline mogą opóźniać renderowanie strony  Renderowanie dopiero po zakończeniu działania skryptów  OnLoad / DOMReady – wtedy po wyrenderowaniu  Umieszczać na końcu pliku  Jeśli skrypty zmieniają HTML  Zamiast document.write() – innerHTML (możliwe wywołania później)  Ukryty div z document.write() + odkrywanie go później  <script defer> i <script async> (HTML 5)  Nie wstrzymuje parsera, pobiera skrypt i wykonuje kod (np. podpina do onload)  Async – nie gwarantuje kolejności (wywołuje po pobraniu)  Defer – gwarantuje kolejność wywołań  Dołączać z CDN (m.in. ASP .NET AJAX, jQuery) - http://www.asp.net/ajaxlibrary/cdn.ashx Skrypty
  • 16.  Tylko lower case w miarę możliwości – kompresja  <img> zamiast <IMG>, itp.  Image sprites dla wielu mniejszych grafik  background-position: 0 -120px  Grafika - rozważyć data URI scheme (IE 8+)  Narzędzia lub online – np. dataurl.net  Do niewielkich grafik (base64, więc 40% większe)  Zwłaszcza w CSS, kiedy może być dodatkowo cache’owane Zmniejszanie liczby żądań #hdr{border:1px solid #000;height:40px; background:url(data:image/gif;base64,R0lGODlhAQAoANUAAAAAAP///wFUzgNV0ANVzwVX0QZY0gdY0gha 0wpb1Qxd1g1e1w9g2BFh2RJj2xVk3BZm3Rho3hpp4Bxr4h5t4x9u5CFw5SRx5yVz6Cd16Sl26it47C157S987jF97 zOA8jJ+8TWB8zaD9DiE9TqF9zqG9zyH+D2I+D6J+T+K+v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACoALAAAAAABACgAAAYlwBTqZCqRRqLQB+TpcDa aDOZiqVAmkgjk4WgwFooE4mAoDAiCIAA7)
  • 17.  Javascript  Walidacja po stronie klienta  Wyłączanie submit po kliknięciu  Generowanie długich list (np. select i wiele elementów <option>)  Unikać obiekt.inny.jeszczeinny.zmienna (pomocnicza zmienna)  Wielokrotny document.write zamiast sklejania stringów  textContent szybszy od innerHTML (jeśli element zawiera tekst)  ASP .NET 4.5 – unobtrusive validation Zmniejszenie liczby żądań – c.d. <code><add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms"/></code> ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms;
  • 18.  Favicon.ico – lepiej żeby był (cache vs 404 za każdym razem)  CSS – inline przy pierwszym wyświetleniu  Mniej żądań przy pierwszym wejściu  Skrypt ładowany inline – jeśli nie ustawione ciasteczko  W Onload – pobierany dynamicznie (cache dla kolejnych żądań)  Nie zamiast – plik potrzebny (cache) Zmniejszenie liczby żądań – c.d. <script type="text/javascript"> function getcss() { var h = document.getElementsByTagName('head'); var l = document.createElement('link'); l.type = 'text/css'; l.rel = 'stylesheet'; l.href = 'css/file19.css'; h[0].appendChild(l); } </script> <system.webServer> <httpProtocol> <customHeaders> <add name="Set-Cookie" value="C=A;expires=Sat, 01-Jan-2050 00:00:00 GMT;path=/demo/css/" /> </customHeaders> </httpProtocol> </system.webServer>
  • 19.  Określić <!DOCTYPE>  Parser lookahead nie musi restartować  Width i Height przy grafikach  Rozmiary kolumn – tabele  Charset (dla statycznych stron) Szybkość renderowania strony
  • 20.  Kiedy wiemy jaka będzie kolejna strona (np. „wizard”)  W pageLoad (nie document ready) Precaching - grafiki <script type="text/javascript" src="jquery-1.7.1.min.js"></script> <script type="text/javascript"> $(window).load(function() { var pre = new Image(0,0); pre.src = "http://s1.domena.net/static/next1.jpg"; var prx = new Image(0, 0); prx.src = "http://s2.domena.net/static/next2.jpg"; }); </script>
  • 21.  <img>- dla innych formatów nie zadziała (MIME type)  AJAX – można, ale tylko ta sama domena  Dynamicznie element <script>  Nie musi być dodawany do DOM  Uwaga – parsowane i wywoływane  Dynamicznie <link>  Musi być w DOM  Wczytywany (może być konflikt selektorów) Precaching – CSS, JS <script type="text/javascript"> function preload() { var req = getreq(); if (req != null) { req.open("GET", "/static/next.js", true); req.send(null); } var rex = getreq(); if (rex != null) { rex.open("GET", "/static/next.css", true); rex.send(null); } } </script> <script type="text/javascript"> function preload() { var scr = document.createElement("script"); scr.src = "http://s1.domena.net/ch02/next.js"; } </script> <script type="text/javascript"> function preload() { var lnk = document.createElement("link"); lnk.rel = "stylesheet"; lnk.type = "text/css"; lnk.href = "http://s1.domena.net/next.css"; document.getElementsByTagName('head')[0].appendChild(lnk); } </script>
  • 23.  Każdy ma nieco inną rolę (np. ASP .NET vs http.sys vs SQL) Wiele rodzajów cache
  • 24.  Cache-Control: max-age lub Expires (dawniej)  Jeśli nie ustawione oblicza  Aktualny czas +10% różnicy między Last-Modified a aktualnym  Po tym czasie – nadal na dysku, ale nie używane  Conditional Get (If-Modified-Since)  HTTP 304 – not modified Statyczne pliki GET /check.png HTTP/1.1 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate If-Modified-Since: Sat, 10 Jan 2012 10:52:45 GMT If-None-Match: "80fc52fa8bb2c81:0" User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Host: www.domena.net Connection: Keep-Alive <system.webServer> . . . <staticContent> <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" /> </staticContent> </system.webServer>
  • 25.  Cache-Control: no-cache  Przeglądarka musi sprawdzić, ale może korzystać z cache (back/fwd)  Cache-Control: no-store  Całkowite wyłączenie (także back/forward) Cache statyczny - wyłączanie <location path="image.jpg"> <system.webServer> <staticContent> <clientCache cacheControlMode="DisableCache" /> </staticContent> </system.webServer>
  • 26.  Output cache  VaryByParam, VaryByHeader – np. Accept-Language (dla różnych języków)  VaryByControl (np. „src”, jeśli taką właściwość ma nasza User Control)  Dla User Controls – ustawiać to samo ID na różnych stronach i Shared=true  Jeśli shared=false to do porównywania ID brana także nazwa Page Dynamiczna zawartość <%@ Page Language="C#" AutoEventWireup="true" CodeFile="dyn-client.aspx.cs" Inherits="dyn_client" %> <%@ OutputCache Duration="86400" Location="Client" VaryByParam="None" %> <system.web> <caching> <outputCacheSettings> <outputCacheProfiles> <add name="Cache1Day" duration="86400" location="Client" varyByParam="none" /> </outputCacheProfiles> </outputCacheSettings> </caching> </system.web> <%@ OutputCache CacheProfile="Cache1Day" %>
  • 27.  Najprościej – VaryByCustom = „browser”  Po swojemu - global.asax  Jeśli chcemy np. jedną wersję dla wszystkich IE i jedną dla Webkit Cache dla różnych przeglądarek public override string GetVaryByCustomString(HttpContext context, string custom) { switch (custom.ToLower()) { case "iemozilla": switch (context.Request.Browser.Browser.ToLower()) { case "ie": case "blazer 3.0": return "ie"; case "mozilla": case "firebird": case "firefox": case "applemac-safari": return "mozilla"; default: return "default"; } default: return base.GetVaryByCustomString(context, custom); } }
  • 28. Dynamiczna zawartość - wyłączanie this.Response.Cache.SetCacheability(HttpCacheability.NoCache); this.Response.Cache.SetAllowResponseInBrowserHistory(true); // Aby nie było Expires (niepotrzebne) this.Response.AppendHeader("Cache-Control", "no-store"); // Dla no-store <%@ OutputCache Location=„None" %> Cache-Control: no-cache Pragma: no-cache Expires: -1  Czasem chcemy mieć pewność, że dane aktualne  Aspx, kod lub profil w web.config
  • 29.  Domyślnie ASP .NET ustawia Cache-Control: private  Nie będzie cache’owane przez proxy  Możliwe nadpisanie (Cache-Control: public)  <%@ OutputCache Location=„Any” %>  Location Downstream – tylko w przeglądarkach Dynamiczna zawartość – c.d. this.Response.Cache.SetMaxAge(age); this.Response.Cache.SetExpires(DateTime.UtcNow + age); this.Response.Cache.SetLastModified(DateTime.UtcNow); this.Response.Cache.SetCacheability(HttpCacheability.Public); this.Response.Cache.SetNoServerCaching();
  • 30. Rozszerzalność <caching> <outputCache defaultProvider="AspNetInternalProvider"> <providers> <add name="DiskCache" type="Test.OutputCacheEx.DiskOutputCacheProvider, DiskCacheProvider"/> </providers> </outputCache> </caching>  ASP .NET 4.0+ – możliwe np. zapisywanie na dysku  Możliwa dynamiczna podmiana  Np. top 10 w pamięci, reszta na dysku
  • 31.  Stan tymczasowy strony, stan kontrolek serwerowych  Często lepsze od sesji (baza przy farmie)  LosFormatter – szybki dla typów string, hashtable, arraylist, pair, triple, int, boolean  Dla pozostałych – BinaryFormatter (wolny), ale można napisać własny TypeConverter  Lepiej – kolekcja prostych typów niż własny obiekt (bez TypeConvertera)  Obecność elementu wykorzystywana m.in. do rozpoznania Page.IsPostback  ViewStateMac – zabezpieczenie przed modyfikacjami  Zabezpieczenie przez CSRF  W Page_init – ViewState[userkey] = this.User.Identy.Name; ViewState
  • 32.  Ma tendencje do rozrastania się  Może być prościej wysłać zapytanie niż uploadować dużo większy formularz  Możliwość wyłączenia  Od ASP .NET 4 – nie tylko dla całej strony (EnableViewState), ale pojedynczych kontrolek  ViewStateMode – enabled, disabled, inherit (domyślnie)  Warto domyślnie wyłączyć (w web.config) i włączać tam, gdzie potrzeba  ControlState – część, której nie można wyłączyć ViewState - problemy
  • 33.  Tag Transform, aby wyłączyć Control State  Jeśli nie korzystamy z zaawansowanych funkcji kontrolki ViewState – wyłączanie public class ListViewNoCS : ListView { protected override object SaveControlState() { return null; } } <pages> . . . <tagMapping> <add tagType="System.Web.UI.WebControls.ListView" mappedTagType="Samples.ListViewNoCS" /> </tagMapping> </pages>
  • 34.  Dla wolnych połączeń (np. klienci mobile) można przechowywać po stronie serwera  Można uzależnić to od typu połączenia lub rozmiaru ViewState ViewState – wolne połączenia protected override void SavePageStateToPersistenceMedium(object state) { string key = Guid.NewGuid().ToString(); this.ClientScript.RegisterHiddenField(ViewKeyName, key); this.Cache[key] = state; } protected override object LoadPageStateFromPersistenceMedium() { string key = this.Request[ViewKeyName]; if (key == null) throw new InvalidOperationException("Invalid ViewState Key"); object state = this.Cache[key]; if (state == null) throw new InvalidOperationException("ViewState too old"); return state; }
  • 35.  Dla domeny - max 50, 10 KB / cookie  Session lub persistent  Domyślna wartość path - „/”  Dołączane także do zawartości statycznej wszystkich plików!  Ustawiać zawsze cookie.Path = „/katalog/”  Bez ustawienia Domain  IE – także wszystkie subdomeny  Inne przeglądarki – tylko aktualna domena  Lepiej ustawić cookie.Domain (unikanie błędów)  Cookie.HttpOnly = true  Cookie niewidoczne dla JS (mniej możliwości ataku)  Powinno się ustawiać domyślnie dla wszystkich  Cookie.Secure = true – wysyłane tylko przez SSL  Jeśli nie możemy SSL – konwersja do Base64 (Convert.ToBase64String) i szyfrowanie symetryczne Cookies
  • 36.  IE8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+  10 MB – IE, 5 MB - pozostałe  2 typy  Per-session (do zamkniecia okna)  Per-domain  Tylko string, ale można serializować do JSON  Tylko klient – nie przesyłane do serwera  Można dodać np. jako parametr wywołania usługi WCF HTML 5 Web Storage <script type="text/javascript"> sessionStorage.setItem('mykey', 'this is my value'); var item = sessionStorage.getItem('mykey') </script>
  • 37.  Kernel-mode driver - http.sys  Znacznie szybszy (bez context switching, itd.)  Domyślnie włączony dla zawartości statycznej  Dla dynamicznej – OutputCache, ustawienie IIS lub applicationHost.config  Kiedy nie działa (najczęstsze)  Zawartość z querystring  Domyślny dokument (d.com zamiast d.com/default.htm)  Włączona kompresja  Domyślnie sliding, 120 sekund  HKLMSystemCurrentControlSetServicesHttpParametersUriScavengerPeriod  Warto zmienić w razie potrzeby (np. kilkanaście godzin) - ostrożnie Windows Kernel Cache
  • 38.  Domyślnie włączony – jeśli ustawione OutputCache  Także dla żądań z querystring  Dla własnych HttpHandlerów – włączyć User Mode Caching  http://d.com/katalog/ zamiast http://d.com/katalog  W przeciwnym wypadku HTTP 302  Zapobiega cache’owaniu 3 różnych wersji IIS Cache
  • 39.  Podobnie jak IIS, ale VaryByParam może być custom  Np. kontekst użytkownika  Fragment Cache – OutputCache w User Control  Substitution Cache  Cała strona cache’owana, oprócz <asp:Substitution> Cache ASP .NET <body> Cached time: <%= DateTime.Now.ToString() %> <br />Page time: <asp:Substitution ID="sub" runat="server" MethodName="SubTime" /> </body> public static string SubTime(HttpContext context) { return DateTime.Now.ToString(); }
  • 40.  Plik  Baza danych  Konieczne włączenie Service Broker Cache Dependency CacheDependency depend = new CacheDependency(this.MapPath("~/depend.txt")); this.CachePolicy.Dependency = depend; using (SqlConnection conn = new SqlConnection(cs)) { string sql = "dbo.GetInfo"; using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.CommandType = CommandType.StoredProcedure; conn.Open(); SqlCacheDependency dep = new SqlCacheDependency(cmd); mygrid.DataSource = cmd.ExecuteReader(); mygrid.DataBind(); this.Response.AddCacheDependency(dep); } } // SqlDependency.Start() w web.config
  • 41.  Np. AppFabric Cache Provider public class MemoryCacheProvider : OutputCacheProvider { public override object Add(string key, object entry, DateTime utcExpiry) { object result = HttpRuntime.Cache[key]; if (result == null) { this.Set(key, entry, utcExpiry); result = entry; } return result; } public override object Get(string key) { return HttpRuntime.Cache[key]; } public override void Remove(string key) { HttpRuntime.Cache.Remove(key); } public override void Set(string key, object entry, DateTime utcExpiry) { HttpRuntime.Cache.Insert(key, entry, null, utcExpiry, Cache.NoSlidingExpiration, CacheItemPriority.High, null); } } <system.web> <caching> <outputCache> <providers> <add name="MemoryCacheProvider" type="Samples.MemoryCacheProvider" /> </providers> </outputCache> </caching> </system.web>
  • 42.  Kiedy chcemy jak najwięcej, jak najdłużej (na ile pamięć pozwoli)  Omijamy logikę Cache Policy - szybkość  Nie dla web farm  WeakReference i GC Statyczne pola – uproszczony cache public static class Weak { public static WeakReference MyItem { get; set; } public static readonly Object lockObject = new Object(); public static DataSet WeakData() { DataSet ds = null; lock (lockObject) { if (MyItem != null) ds = MyItem.Target as DataSet; if (ds == null) { ds = new DataSet(); MyItem = new WeakReference(ds); } } return ds; } }
  • 43. IIS
  • 44.  Domyślnie – jeden proces w3wp.exe  AppPool - kilka procesów dla kolekcji aplikacji (Web Garden)  Maximum Worker Processes  AppPool Recycling  Tracimy cache, inproc session, static, …  Domyślnie 29h  Warto zmienić na określoną godzinę lub liczbę obsłużonych requestów (NLB) App Pool
  • 45.  Wiele AppPools  Dzielenie aplikacji na kilka puli  Błąd w jednej puli nie ma wpływu na działanie drugiej  Np. obsługa magazynu i aplikacja dla konsumentów  Web Garden  Ochrona przed błędami procesu w3wp – kilka procesów  Uwaga - context-switching między wątkami szybszy niż między procesami!  Konieczna duplikacja w pamięci danych takich jak cache czy pola static  Zalecane max 1-2 worker procesy / CPU core  Tylko, kiedy najistotniejsza ciągłość pracy Kiedy najważniejsze jest działanie
  • 46.  ASP .NET – ISAPI Extension  Duplikacja funkcjonalności  2 odrębne pipeline’y  Np. Logowanie, auth -> IIS, później ASP .NET  Trudniejsza konfiguracja IIS6 + ASP .NET (Classic mode) Authentication Basic NTLM Anon ... Determine Handler ... SendResponse HTTP Request HTTP CGI Static File ISAPI Compre ssion Log aspnet_isapi.dll Authentication Map Handler Forms Windows ... ASPX Trace ... ...
  • 47.  Wyodrębnione komponenty z w3core.dll  Niezależne dodawanie / usuwanie funkcjonalności  Np. auth – możemy dać własne zamiast basic / LDAP , itp..  Lekki core Architektura IIS 7 Authentication ... ExecuteHandler ... SendResponse HTTP Request HTTP Response Authorization UpdateCache ResolveCache Authentication ... Determine Handler ... SendResponse HTTP Request HTTP Response Basic NTLM Anon CGI Static File ISAPI Log Compre ssion Url Authz Output Cache Forward er Basic 40+
  • 48.  Handler HTTP  Mapowany dla rozszerzeń (np. aspx)  Migracja z html do dynamic -> można dodać mapowanie htm na ASP .NET  Moduły HTTP  ASP .NET bezpośrednio w IIS Pipeline  Np. sesja, uwierzytelnianie dla zawartości statycznej, php, itp.  Rozszerzalność przez .NET, a nie ISAPI (C++)  Usuwać niepotrzebne moduły  Kolejność typów dokumentów w IIS IIS 7 + ASP .NET - Integrated Pipeline ISAPI Authentication ... ExecuteHandler ... SendResponse Authorization UpdateCache ResolveCache HTTP Request Anon aspnet_isapi.dll Authentication Map Handler ... ... Forms Windows ASPX Trace ... Basic Compre ssion Log Static File
  • 49.  Nowe w Windows Server 2008  Rezerwacja minimalnej ilości pamięci lub CPU dla procesów Windows System Resource Manager
  • 50.  Bezpieczeństwo i mniej pobieranych danych  X-Powered-By – IIS  Nagłówek Server – tylko z kodu  Etag – przy web farm można wyłączyć (często jest różny dla node’ów)  X-Aspnet-Version - <httpRuntime enableVersionHeader="false"/> Usuwanie nagłówków public class HttpHeaderCleanup : IHttpModule { public void Init(HttpApplication context) { context.PreSendRequestHeaders += OnPreSendRequestHeaders; } void OnPreSendRequestHeaders(object sender, EventArgs e) { HttpResponse response = HttpContext.Current.Response; response.Headers.Remove("Server"); response.Headers.Remove("ETag"); } public void Dispose() { } }
  • 51.  3-5% więcej CPU, ale generalnie warto  Gzip (domyślny) lub deflate (mniejszy nagłówek) Kompresja <httpCompression directory="%SystemDrive%inetpubtempIIS Temporary Compressed Files" dynamicCompressionDisableCpuUsage="100"> <scheme name="gzip" dll="%Windir%system32inetsrvgzip.dll" staticCompressionLevel="9" dynamicCompressionLevel="5" /> <scheme name="deflate" dll="%Windir%system32inetsrvgzip.dll" staticCompressionLevel="9" dynamicCompressionLevel="5" /> <staticTypes> <add mimeType="text/*" enabled="true" /> <add mimeType="message/*" enabled="true" /> <add mimeType="application/x-javascript" enabled="true" /> <add mimeType="*/*" enabled="false" /> </staticTypes> <dynamicTypes> <add mimeType="text/*" enabled="true" /> <add mimeType="message/*" enabled="true" /> <add mimeType="application/x-javascript" enabled="true" /> <add mimeType="*/*" enabled="false" /> </dynamicTypes> </httpCompression>
  • 52.  Lepsze dla SEO  http.sys nawet przy querystringach  Krótsze URLe w odpowiedziach  Ukrywa technologię aplikacyjną  IIS (URL Rewrite) lub ASP .NET URL Rewriting
  • 53.  Pamiętać o botach (robots.txt, sitemap.xml)  Bandwidth Throttling  Moduł BitRateThrottling do IIS  Głównie dla mediów, ale również można do innych typów danych  Np. wolniej dla botów lub kawałek dużego zdjęcia szybko Szybkość transferu public class Throttle : IHttpModule { public void Init(HttpApplication context) { context.PostRequestHandlerExecute += OnPostRequestHandlerExecute; } void OnPostRequestHandlerExecute(object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; HttpResponse response = context.Response; if (response.ContentType == "application/x-zip-compressed") { HttpRequest request = context.Request; if (!String.IsNullOrEmpty(request.ServerVariables["SERVER_SOFTWARE"])) { request.ServerVariables["ResponseThrottler-InitialSendSize"] = "20"; request.ServerVariables["ResponseThrottler-Rate"] = "10"; } } } public void Dispose() { } }
  • 55. Tradycyjne przetwarzanie żądań “thread-per-request” a.k.a. “post office” Thread pool Żądania Busy Busy Busy Busy Przy load testach – zużycie CPU niewielkie, ale długi czas odpowiedzi
  • 57.  Domyślnie 12 / CPU  Czasem zwiększenie liczby pomaga  Wiąże się z tym koszt (start, pamięć, context switch)  Ważniejsza optymalizacja istniejących  Blokujące wywołania – baza, zewnętrzne usługi, I/O  Przy obliczeniach (CPU) nie pomoże! Worker Threads
  • 58.  Domyślnie przetwarzanie synchroniczne (1 wątek całe lifecycle)  Async point Synchronicznie i asynchronicznie
  • 59. Asynchronicznie – web forms (APM) <%@ Page Async="true„ AsyncTimeout=„30” Language="C#" AutoEventWireup="true" CodeFile="sql-async.aspx.cs" Inherits="sql_async" %> public const string ConnString = "Data Source=.;Integrated Security=True;Async=True"; protected void Page_Load(object sender, EventArgs e) { PageAsyncTask pat = new PageAsyncTask(BeginAsync, EndAsync, null, null, true); this.RegisterAsyncTask(pat); } private IAsyncResult BeginAsync(object sender, EventArgs e, AsyncCallback cb, object state) { SqlConnection conn = new SqlConnection(ConnString); conn.Open(); SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:01'", conn); IAsyncResult ar = cmd.BeginExecuteNonQuery(cb, cmd); return ar; } private void EndAsync(IAsyncResult ar) { using (SqlCommand cmd = (SqlCommand)ar.AsyncState) { using (cmd.Connection) { int rows = cmd.EndExecuteNonQuery(ar); } } }
  • 60.  Task – zaczyna od razu  APM – kolejkuje do async point Asynchronicznie – web forms (Task) public const string ConnString = "Data Source=.;Integrated Security=True;Async=True"; protected async void Page_PreRender(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection(ConnString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:01'", conn)) { await Task.Factory.FromAsync<int>(cmd.BeginExecuteNonQuery, cmd.EndExecuteNonQuery, null); } } }
  • 61.  Najlepiej agregować (np. kilka zapytań w procedurze skł.)  Wywoływane równolegle lub jedno po drugim Asynchroniczne strony – wiele zadań protected void Page_Load(object sender, EventArgs e) { // Dwa pierwsze – równolegle. Następnie BeginAsync3 (ostatni parametr PageAsyncTask) PageAsyncTask pat = new PageAsyncTask(BeginAsync1, EndAsync1, null, null, true); this.RegisterAsyncTask(pat); pat = new PageAsyncTask(BeginAsync2, EndAsync2, null, null, true); this.RegisterAsyncTask(pat); pat = new PageAsyncTask(BeginAsync3, EndAsync3, null, null, false); this.RegisterAsyncTask(pat); }
  • 62.  Czasem potrzeba zarejestrowania zadania po zakończeniu poprzedniego  Np. drugie wywołanie usługi po zakończeniu poprzedniego  Konieczne wywołanie ExecuteRegeisteredAsyncTasks()  Można także wywołać, aby wymusić wywołanie przed async point  Dla Task – zwyczajnie jeden po drugim z await Późniejsza rejestracja private void EndAsync(IAsyncResult ar) { using (SqlCommand cmd = (SqlCommand)ar.AsyncState) { using (cmd.Connection) { int rows = cmd.EndExecuteNonQuery(ar); } } PageAsyncTask pat = new PageAsyncTask(BeginAsync2, EndAsync2, null, null, true); this.RegisterAsyncTask(pat); this.ExecuteRegisteredAsyncTasks(); }
  • 63.  Usługi  Pliki Inne operacje protected async void Page_Load(object sender, EventArgs e) { var terra = new TerraServiceSoapClient(); Place place = new Place() { City = "Seattle", State = "WA", Country = "US" }; var result = await terra.GetPlaceFactsAsync(place); PlaceFacts facts = result.Body.GetPlaceFactsResult; this.LA.Text = String.Format("Latitude: {0:0.##}", facts.Center.Lat); this.LO.Text = String.Format("Longitude: {0:0.##}", facts.Center.Lon); } // Dla web requestów: // var r = WebRequest.Create(„http://…”); // var res = await r.GetResponseAsync(); private IAsyncResult BeginAsync(object s, EventArgs e, AsyncCallback cb, object s) { FileStream fs = new FileStream(this.Server.MapPath("csg.png"), FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan); this.Data = new byte[64 * 1024]; IAsyncResult ar = fs.BeginRead(this.Data, 0, this.Data.Length, cb, fs); return ar; // dla podejścia Task: // int size = await fs.ReadAsync(this.Data, 0, this.Data.Length); }
  • 64. Async controller – przed MVC 4 public class WeatherAsyncController : AsyncController { private string _forecastUrl = "http://weather.yahooapis.com/forecastjson?w=523920&u=c"; public void IndexAsync() { var webClient = new WebClient(); AsyncManager.OutstandingOperations.Increment(); webClient.DownloadStringCompleted += (sender, evt) => { // capture result when web service completes AsyncManager.Parameters["json"] = evt.Result; AsyncManager.OutstandingOperations.Decrement(); // Exception handling - challenge... }; // async call webClient.DownloadStringAsync(new Uri(_forecastUrl)); } public ActionResult IndexCompleted(string json) { WeatherData weather = new JavaScriptSerializer().Deserialize<WeatherData>(json); return View("Weather", weather); } }
  • 65. Async controller – MVC 4 public class WeatherTaskAsyncController : AsyncController { private string _forecastUrl = "http://weather.yahooapis.com/forecastjson?w=523920&u=c"; public async Task<ActionResult> Index() { string json = await new WebClient().DownloadStringTaskAsync(_forecastUrl); WeatherData weather = new JavaScriptSerializer().Deserialize<WeatherData>(json); return View("Weather", weather); } }
  • 66.  Możliwość wywołania kodu równolegle  Po wyrenderowaniu strony lub w trakcie  ThreadPool.QueueUserWorkItem()  Zużywa wątki z AppPool  1 wątek w tle + kolejka  Typowy consumer - producer  Np. logowanie (nie wymagane 100% działanie)  Bardziej krytyczne zadania – np. Service Broker lub Azure Worker + kolejka  Przy wielu wątkach – warto ReaderWriterLockSlim  EnterReadLock / EnterWriteLock (mniejsze ryzyko zakleszczenia)  Przykład Background Worker Thread
  • 67.  InProc  Najszybsza, ale load balancer tylko sticky  Nie odporna na awarie sprzętu  StateServer  Web farm – ok, ale single point of failure  SQL (+SQL Agent do usuwania)  Możliwe przyspieszenie przez <sessionState compressionEnabled=„true” />  <%@ Page EnableSessionState=„false” @> - ale i tak update (timeout)  <%@ Page EnablesessionState=„ReadOnly” @> - mniej locków; ta sama SP , która odczytuje  Przyspieszyć zapis do logu (podział na dyski, SSD, itp.)  PartitionResolver (wybór conn str na podst id sesji) i SessionIDManager (id sesji z nr maszyny)  Mimo wszystko niezbyt skalowalne – patrz: AppFabric session provider Sesja
  • 68. Control ID  Możliwość kontroli identyfikatorów (klienckich) kontrolek serwerowych  Control.ClientIdMode  Legacy  Static  Predictable  Inherit (domyślne dla kontrolek)  Kolekcje – ClientIDRowSuffix  Dla całej strony lub kontrolki  Ostrożnie – duplikacja, długość
  • 69.  Możliwość zmiany markupu kontrolki serwerowej  Np. GridView nie z tabelkami, ale na floatach Control Adapter // Zamiana URL w Image na małe litery public class ImageControlAdapter : WebControlAdapter { public ImageControlAdapter() { } protected override void BeginRender(System.Web.UI.HtmlTextWriter writer) { Image image = Control as Image; if ((image != null) && !String.IsNullOrEmpty(image.ImageUrl)) { if (!image.ImageUrl.StartsWith("http") && !image.ImageUrl.StartsWith("data:")) { image.ImageUrl = this.Page.ResolveUrl(image.ImageUrl).ToLower(); } } base.BeginRender(writer); } } // adapter.browser <browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.WebControls.Image" adapterType="Samples.ImageControlAdapter" /> <adapter controlType="System.Web.UI.WebControls.Panel" adapterType="Samples.NoIdControlAdapter" /> <adapter controlType="System.Web.UI.WebControls.Label" adapterType="Samples.NoIdControlAdapter" /> <adapter controlType="System.Web.UI.WebControls.HyperLink" adapterType="Samples.NoIdControlAdapter" /> </controlAdapters> </browser> </browsers>
  • 70.  Np. wyłączenie domyślnego generowania ID Control Adapter c.d. – usuwanie ID public class NoIdControlAdapter : WebControlAdapter { protected override void Render(HtmlTextWriter writer) { PageBase page = this.Page as PageBase; if ((page != null) && page.RemoveIds && (this.Control.ClientIDMode != ClientIDMode.Static)) { HtmlTextWriter noIdwriter = new NoIdHtmlWriter(writer); base.RenderBeginTag(noIdwriter); base.RenderContents(writer); base.RenderEndTag(noIdwriter); } else { base.Render(writer); } } } public class NoIdHtmlWriter : HtmlTextWriter { public NoIdHtmlWriter(TextWriter writer) : base(writer) { } public override void AddAttribute(HtmlTextWriterAttribute key, string value) { if (key != HtmlTextWriterAttribute.Id) base.AddAttribute(key, value); } } public class PageBase : Page { protected override void OnInit(EventArgs e) { base.OnInit(e); this.RemoveIds = true; } public bool RemoveIds { get; set; } }
  • 71.  Np. do zwracania zapisanego w bazie HTML  Bez cyklu życia ASP .NET – szybciej  Asynchronicznie – uczestniczy w każdym żądaniu!  IsReusable – czy jedna instancja może być dla wielu żądań HTTP Handler w .NET <%@ WebHandler Language="C#" Class="Handler" %> using System; using System.Data; using System.Web; using System.Data.SqlClient; public class Handler : IHttpAsyncHandler { public const string ConnString = "Data Source=.;Initial Catalog=Sample;Integrated Security=True;Async=True"; HttpContext Context { get; set; } public void ProcessRequest(HttpContext context) { } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { this.Context = context; int fileid = 0; string id = context.Request.QueryString["id"]; if (!String.IsNullOrEmpty(id))
  • 72.  Krótsze adresy w kodzie  http.sys caching  Łączenie np. z ASP .NET MVC (MapRoute / MapPageRoute) Routing protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.Add("Category", new Route("{category}", new PageRouteHandler("~/1.3 Routing.aspx"))); RouteTable.Routes.Add("CategoryAndPage", new Route("{category}/{page}", new PageRouteHandler("~/1.3 Routing.aspx"))); } protected void Page_Load(object sender, EventArgs e) { lblCategory.Text = RouteData.Values["category"] as string; lblPage.Text = RouteData.Values["page"] as string; }
  • 73.  Klasyczne  this.Response.Redirect("~/pages/error.aspx", true); True – czy zakończyć request  this.Response.RedirectPermanent  this.Response.RedirectToRoute  Server.Transfer(„~/pages/error.aspx”, false)  False – czy przekazać parametry z obecnej strony  True – dla ViewState wyrzuci exception; tylko dla querystring  Cross-page postback Przekierowania <asp:Button runat="server" PostBackUrl="~/pages/otherpage.aspx" Text="Submit" />
  • 74.  Zawartość z Render() buforowana i zwracana na koniec  Dla długotrwałych zadań może wymagać czasu  Najlepiej – z Ajax  Response.Flush() – wysłanie odpowiedzi z bufora  Przed Render() nic w nim nie ma! Wczesny flush odpowiedzi
  • 75.  W OnPreRender  Ręczny zapis odpowiedzi  Wyrenderowanie wybranych kontrolek serwerowych  Usunięcie wyrenderowanych kontrolek (aby nie było duplikacji po Render)  Długotrwałe zadanie w OnPreRender (async) lub synchronicznie po PreRender (po async point) Wczesny flush – c.d. <html> <head id="Head1" runat="server"> <title></title> <script type="text/javascript" src="test.js"></script> </head> <body> <form id="form1" runat="server"> <div> <asp:Label runat="server" ID="test" Text="testing" /> </div> </form> </body> </html> protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); this.Response.Write("<!DOCTYPE html PUBLIC " + ""-//W3C//DTD XHTML 1.0 Transitional//EN" " + ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">n"); this.Response.Write("<html xmlns="http://www.w3.org/1999/xhtml">n"); HtmlTextWriter writer = this.CreateHtmlTextWriter(this.Response.Output); this.Header.RenderControl(writer); writer.Flush(); this.Response.Flush(); this.Controls.Remove(this.Header); Thread.Sleep(2000); }
  • 76. Wczesny flush - odpowiedź HTTP/1.1 200 OK Cache-Control: private Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.5 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Fri, 03 Feb 2012 12:16:11 GMT 161 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"> <link href="App_Themes/mkt/common.css" type="text/css" rel="stylesheet" /> <title> Testing </title> <script type="text/javascript" src="test.js"></script> </head> 146 <body> <form name="form1" method="post" action="flush1.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE0NDMxNDM0MTlkZA0loE+taD1AMKhxDNDZZLZADwxZqGnPPbIF8Mylq4PV" /> </div> <div> <span id="test">testing</span> </div> </form> </body> </html> 0
  • 77. Minification dla dynamicznych public class MinifyStream : Stream { private StreamWriter Writer { get; set; } private Decoder Utf8Decoder { get; set; } public MinifyStream(Stream stream) { this.Writer = new StreamWriter(stream, Encoding.UTF8); this.Utf8Decoder = Encoding.UTF8.GetDecoder(); } public override void Write(byte[] buffer, int offset, int count) { int characterCount = this.Utf8Decoder.GetCharCount(buffer, offset, count); char[] result = new char[characterCount]; int decodedCount = this.Utf8Decoder.GetChars(buffer, offset, count, result, 0); if (decodedCount <= 0) return; // ... wyfiltrowanie zbędnych znaków i zapis do this.Writer } public override void Close() { this.Writer.Flush(); this.Writer.Close(); base.Close(); } public override void Flush() { this.Writer.Flush(); } // ... } // W module HttpModule private void Sample_PostRequestHandlerExecute(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpResponse response = application.Context.Response; if(response.ContentType == "text/html") response.Filter = new MinifyStream(response.Filter); }
  • 78.  Page.IsPostBack  Rozpoznawanie odświeżenia strony Unikanie niepotrzebnej pracy protected virtual bool IsRefresh { get { return this.Request.Headers["Pragma"] == "no-cache" || this.Request.Headers["Cache-Control"] == "max-age=0"; } }
  • 79.  Response.IsClientConnected  Czy przeglądarka jeszcze czeka na odpowiedź, czy została zamknięta?  Warto sprawdzić przed długotrwałą operacją na bazie  <compilation batch=true />  True – niewiele pakietów  False – każda strona w osobnym assembly (wolniej, ale łatwiej zmiany)  Wyłączyć debug mode!  Można wymusić w machine.config Inne <system.web> <deployment retail="true" /> </system.web>
  • 80. Auto-start aplikacji //applicationHost.config <serviceAutoStartProviders> <add name="PrewarmMyCache" type="MyNamespace.CustomInitialization, MyLibrary" /> </serviceAutoStartProviders> public class CustomInitialization : System.Web.Hosting.IProcessHostPreloadClient { public void Preload(string[] parameters) { // Nasza inicjalizacja. } }  Dawniej – Global.asax i Application_Load  IIS 7.5 i Windows Server 2008 R2
  • 81.  Książka Ultra-Fast ASP .NET 4.5  Książka Ultra-Fast ASP .NET  MSDN – ASP .NET Performance Zasoby
  • 82. © 2012 Microsoft Corporation. Wszelkie prawa zastrzeżone. Microsoft, Windows oraz inne nazwy produktów są lub mogą być znakami towarowymi lub zastrzeżonymi znakami towarowymi firmy Microsoft w Stanach Zjednoczonych i innych krajach. Zamieszczone informacje mają charakter wyłącznie informacyjny. FIRMA MICROSOFT NIE UDZIELA ŻADNYCH GWARANCJI (WYRAŻONYCH WPROST LUB DOMYŚLNIE), W TYM TAKŻE USTAWOWEJ RĘKOJMI ZA WADY FIZYCZNE I PRAWNE, CO DO INFORMACJI ZAWARTYCH W TEJ PREZENTACJI.