Diplomitöö: ASP.NET veebirakenduse optimeermine meediaorganisatsiooni näitel

From ICO wiki
Jump to navigationJump to search

Siin lehel kirjutan oma diplomitööd. Alustan 19.märtsil probleemi kirjeldusega.

Olemasoleva olukorra ja probleemi kirjeldus

Järgnevalt antakse lühike ülevaade Eesti Rahvusringhäälingust ja olemasolevast lahendusest

Eesti Rahvusringhääling

Ilus organisatsiooni skeem Eesti Rahvusringhääling(ERR) tekkis Eesti Raadio ja Eesti Televisiooni ühendamisega aastal 2007. Sellest tulenevalt seostub ta väga paljudele eelkõige tele- ja raadioprogrammidega. Televisiooni poolt esindavad ETV ja ETV2 ning raadioid Vikerraadio, Klassikaraadio, Raadio 2, Raadio 4 ja Raadio Tallinn. Viimastel aastatel on neile lisandunud veel mitmeid uudiste- ja teemaportaale , mida praeguseks on kokku juba üle 20ne. Üheks eesmärgiks on jõuda viie esimese ajarkirjanduslikku sisu pakkuva portaali sekka Eestis. 2010. aastal oli TNS Emori andmetele Rahvusringhäälingu portaalide lugejaskond 165 tuhat lugejat nädalas. Väga palju tööd on tehtud ka selleks, et suurendada programmide ja saadete kättesaadavaust internetis nii järelvaatamiseks kui ka reaalajas. ERR oli Eestis esimene, kes hakkas edastama otse pilti ka internetis ja teeb seda ka peagi mobiilides.

Portaalide arendus ERR'is

ERR'is tegeleb portaalide arendusega portaalide arenduse üksus. Ametikult loodi see 1. jaanuar 2010. Praeguse hetkel kuuluvad meeskonda ametlikult 3 arendajat ja veebiarendusjuht. Eelnevalt vastutas arenduse eest üks inimene. Kõik uued portaalid luuakse hetkel ASP.NET 4 platvormil, millega paralleelselt toimub vanema versiooni ASP.NET portaalide üle toomine uuemale versioonile. Lisaks .NET raamistikku kasutavatele portaalidele on kasutusel hetkel veel ka PHP lahendusi, millele ei tehta enam väga suuri juurdearendusi, vaid pigem tegeletakse haldamisega.

PHP tehnoloogial portaalid Eesti Rahvusringhäälingus

PHP portaalide haldusega tegeleb praegu täiskohaga üks inimene. Räägi ka miks ja kuidas need on tekkinud

PHP4 tehnoloogial arendatud portaalid

  • etv.err.ee - ETV kanali portaal, võimalik jälgida tagantjärele saateid ja nende uudiseid.
  • uudised.err.ee - uudiste portaal.
  • ilm.err.ee - ilma portaal.
  • meieoma.ee - lastele mõeldud portaal.

PHP5 tehnoloogial arendatud portaalid

Millal tekkinud, kas arendatatakse edasi, mis on plaanid nendega

  • pood.err.ee - võimalik osta ERR toodangut.
  • Raadioportaalides on võimalik lugeda nendega seonduvaid uudisedeid, kuulata saateid arhiivist ja ka otse.
    • vikerraadio.err.ee
    • r2.err.ee
    • r4.err.ee
    • raadiotallinn.err.ee
    • klassikaraadio.err.ee
  • teadus.err.ee - teadus- ja haridussaadete portaal.
  • raadioteater.err.ee - võimaldab kuulata vikerraadios esitatud kuuldemänge ja järjejutte.

ASP.NET platvormil portaalidde arendus Eesti Rahvusringhäälingus

Miks? Kes?Kus? Kuidas?

ASP.NET 2.0

  • err.ee -Eesti Rahvusringhäälingu keskportaal.
  • om.err.ee - Taliolümpiamänge kajastav portaal.

ASP.NET 4.0

  • news.err.ee - Eestit kajastav ingliskeelne uudiste portaal
  • eestilaul.err.ee - Eesti Laulu ja Eurovisiooni kajastav teemaportaaal
  • otse.err.ee - Portaal, mis võimaldab jälgida ERR'i tele-ja raadiotoodangut reaalajas.
  • valijakompass.err.ee - teemaportaal mis aitas võrrelda inimestel enda seisukohti erakondade omadega.
  • koolifilm.err.ee - koolifilmi konkurssi läbiviimiseks loodud portaal
  • rus.err.ee - Eestit kajastav venekeelne uudisteportaal.
  • retseptid.err.ee - portaal, kuhu lisatakse eetris olnud retsepte.
  • kodanik.err.ee -
  • jalgpall.err.ee - Portaal, mis kajastas jalgpalli MM 2010't
  • ring.err.ee - ERR portaalide registreeritud kasutajate..
  • etv2.err.ee - kajastab ETV2'ga seotud uudiseid/üritusi.

Probleemi kirjeldus

Teise põlvkonna ASP.NET portaalide jaoks loodud lahendus valmis kiirustades, kuna selle valmistamine toimus äärmiselt piiratud ajaraamis ja tööjõudu selle projekti tarvis oli vähe. Seetõttu puudus oodatava süsteemi põhjalik eelanalüüs. Rakenduse loomiseks kasutati töövõtteid, mis kiirendasid küll selle valmimise kiirust, kuid paratamatult kannatas selle all rakenduse kvaliteet (sh jõudlus). Ametlikku kasutuselevõttu eel ei olnud võimalik, tulevenalt ajaraamist, teha süsteemile täielikke jõudlusteste, mis näidanuks selle toimimist suurte koormuste korral. Teise põlvkonna ASP.NET portaalide mootori valmimise hetkel hakati seda lahendust kasutama vaid ühe portaali piires. Hiljem lisandus sellele platvormile täiendavaid portaale ning jõudluse küsimus muutus seepärast aktuaalseks.

Arendusmeeskonda on lisandunud noori programeerijaid, kes ei ole piisavalt teadlikud kuidas tagada korraliku koodikvaliteeti. ASP.NET lahendusi on küll võimalik pealtnäha kiiresti ja kergelt valmistada, kuid kasutades valesid tehnoloogiaid ning töövõtteid ja jättes optimaalse ressursikasutuse jälgimise tagataustale, mõjub see rakenduse jõudlusele hävitavalt.

Poole aasta jooksul on lisandunud uusi .NET portaale, milledest enamus kasutab eelpool mainitud lahendust. Viimasel ajal on esinenud suurte koormuste korral märgatavaid jõudlusprobleeme. Üheks põhjuseks on kindlasti asjaolu, et kõiki .NET portaalide haldamiseks on kasutada ainult üks server. Ehk kui üks portaal hakkab kasutama väga palju ressurssi, siis mõjutab see ka teiste portaalide tööd. See on kindlasti ka üheks turvanõrkuseks - leides ühel leheküljel ressursinõudliku protseduuri, saab seda kasutada kõikide ASP.NET portaalide töö häirimiseks. Halvimal juhul lõpeb see serveri töö seiskumisega. Täiendavad investeeringud riistvarasse on aga välistatud, et kasvatada serveripargi jõudlust. Kuna organisatsioon tegutseb internetimeedia turul ja laieneb sellel pidevalt, siis häired veebirakenduste töös mõjuvad mainele negatiivselt ning on oht kaotada külastajaid.

Lähiajal on lisandumas antud serverile veel kaks täiesti uut portaali. Lisaks peavad hakkama mõned esimese põlvkonna portaalid kasutama hakkama ka "uut mootorit". Kuna juba praegu esineb jõudlusprobleeme, tuleb enne seda parandada olemasoleva lahenduse jõudlust.

Tegemist on tänapäeval väga aktuaalse probleemiga, mis ei puuduta ainult näitena toodud organisatsiooni. Tagades veebirakendused optimaalse ressursikasutuse, võib ära hoida ka täiendavad lisakutulused riistvara soetamiseks, millega loodetakse probleeme lahendada. Viimane aga ei ole tihti lahendus, vaid pigem probleemi peitmine, kuna rakenduse ja ka külastatavuse kasvuga on see peagi tagasi. See osa on selgelt liiga lühike Võimalik viide, et probleemi aktuaalsust üldisena käsitleb autor peeatükis see ja see

Metoodika valik ja võimalikud lahendused

Selles peatükis selgitab autor töös kasutatavat metoodikat ning annab ülevaate käsitletava teema valdkonnast üldiselt....

Metoodika

Lahenduse leidmiseks teostab autor teoreetilise uuring kasutatakse olemasolevate materjalide analüüsi ning seejärel koostab olemasolevate rakenduste optimeerimise kava. Lõputöö käigus tutvutakse parimate praktikatega ja valitakse välja neist sobivaimad. Valiku tegemisel hinnatakse sobivust olemasoleva lahendusega. Kui valik on teostatud mõõdetakse praeguse lahenduse töökiirust. Peale seda võetakse kasutusele leitud optimeerimisvõimalused, mida rakendatakse kõigepealt testserveris, millele järgnevad uuesti mõõtmiseid. Võrreldakse saadud tulemusi ja tehakse järeldus. Eelistatud on Microsofti enda poolt soovitatud lahendused. Miks?

ASP.NET veebirakenduse arhitektuur

Optimeerimisest üldiselt

Tänapäeval on jõudlusprobleemid väga aktuaalsed, kuna üha rohkem kasutatakse erinevate toimingute tegemiseks IT-lahendusi. Selle tõttu sõltub meist peaaegu igaüks mingilmoel konkreetse rakenduse töötamisest. Tihti häirivad loodud lahenduste tööd jõudlusprobleemid. Viimased kerkivad esile, kui süsteemile kasvab koormus, kuna tihti on nende tekkimist raske prognoosida. Sama olukord on ka liikluses: Näiteks kell 4 öösel tööle sõit võtab alati vähem aega, kui seda teha hommikusel tipptunnil. Nii võib väike tähelepanematus rakenduses halvata terve süsteemi töö. Viimane hakkab küll hiljem tööle, kuid kahju on juba selleks ajaks sündinud - pahased kliendid, maine langus, võimalik rahaline kahju.

Kuidas seda vältida? Parem kirjuta vormis: selle vältimiseks saab kasutada... Üheks võimaluseks on alati juurde soetada riistvara, mis annab juurde rohkem jõudlust. See on õigustatud ainult juhul, kui on kindlaks tehtud, et rakendus on juba optimeeritud ja olemasolevate vahenditega pole seda enam võimalik parandada. Vastasel juhul on tegemist probleemi ajutise peitmisega, mitte lahendamisega. Lisaks kulutatakse nii mõttetult finantsvahendeid. Seega tuleks alati alustada olemasoleva lahenduse analüüsiga ja võimaluse korral optimeerimisega.

Lahendust tuleb vaadata alati kui tervikut. Näiteks veebileht ei koosne ainult koodist, mis kirjutab välja ainult vajalikke asju. Seda infot tuleb käia kuskilt pärimas - andmebaasist. Lehe reserveerimise eest vastutab aga server. Ükskõik millise selle osa halvasti töötamine mõjutab teisi. Parandades ühte osa, paraneb enamasti ka üldine jõudlus, kuid maksimaalse kasutegerui saavutamiseks tuleb vaadata rakenduse kõiki osasid. Edukalt probleemide lahendamisel võib nii vältida täiendava riistvara soetamist ja tagada parema süsteemi töökindluse.


Alati tuleb meeles pidada, et enne optimeerima asumist peame vastama küsimusele:"Kui palju me sellest võidame". Kui kulutame 2 päeva optimeerimaks päringut, mida tehakse kord aastas ja võidame paar millisekundit, siis tegelikkuses oleme kaotanud 2 väärtuslikku tundi. Samuti peab jälgima, milliseid muudatusi toob see kaasa olemasolevas lahenduses. Kas muudatus, mis muudab koodi loetamatuks ja selle silumise raskeks, on õigustatud?

Antud lõputöö eesmärgiks on leida kõige lihtsamalt kasutatavaid ja suuremat jõudlusvõitu tagavad võtted ASP.Net veebirakenduse optimeerimiseks ning neid rakendada. Selle saavutamiseks tuuakse välja ka lihtsamad võimalused, kuidas jälgida erinevate rakenduse osade töötamiskiirust, millele tuleks selle juures tähelepanu pöörata ja milliseid muudatusi see endaga kaasa toob. Lisaks luuakse dokument, mida saab kasutada uute loodavate lahenduste optimeerimiseks tulevikuks.

Andmebaasi optimeerimine

Öeldakse, et koodi saab alles siis optimeerida, kui midagi töötavat on juba valmis tehtud. Andmebaaside puhul selline väide aga ei kehti, kuna selle hea jõudluse tagamise üheks tähtsamaks nurgakiviks on korralik disain. Kui andmebaas on halvasti loodud, siis on ka selle optimeerimine keeruline ja sellest pole nii palju kasu. Öeldakse, et päev tööd andmebaasi loomise algusfaasus võrdub hiljem sama tulemuse saavutamiseks kolme kuuga. Andmebaasi jõudluse tagamine ei koosne ainult protseduuride korrigeerimisest ja mõnede seadete muutmitest. Enne selle kallale asumist peab analüüsima üldse seda, mis hetkel toimub - kuidas päringuid täidetakse, kui palju see võtab jõudlust, kas indekseeritud on õiged väljad. Ei saa loota, et suvaline indekseerimine parandab andmebaasijõudlust, vastupidi, selle hoolimatu kasutamine mõjub jõudlusele hoopis negatiivselt. Siiski on mõned põhitõed, mis parandavad andmebaasi jõudlust alates selle loomisest.

Antud lõputöö eesmärgiks on leida kõige lihtsamalt kasutatavaid ja suuremat jõudlusvõitu tagavad võtted ASP.Net veebirakenduse optimeerimiseks ning neid rakendada. Selle saavutamiseks tuuakse välja ka võimalused, kuidas mõõta erinevate rakenduse osade töötamiskiirust, millele tuleks selle juures tähelepanu pöörata ja milliseid muudatusi see endaga kaasa toob. Lisaks luuakse dokument, mida saab kasutada uute loodavate lahenduste varajaseks optimeerimiseks tulevikuks. Ainus eeldus on, et tegemist on .NET 4 raamistikuga ja andmebaasina kasutatakse SQL Server 2008 väljaannet, kuna need on antud töö aluseks.

Andmebaasi loomine

Nagu eelpool mainitud, algab kõik andmebaasiloomisest. Selle protsessi käigus tehtud otsused mõjutavad väga palju andmebaasi edaspidist jõudlust ja ressursikasutust. Alguses valesti tehtud otsused võivad mõjuda halvasti andmebaasi, kui ka seda kasutava rakenduse jõudlusele. Muidugi on kõige tähtsam andmebaasi loogiline ülesehitus, kuid tähelepanu tuleb pöörata ka kindlasti veergude definitsioonidile, mis tuleb määrata korrektselt ja loogiliselt. Ehk kuupäevad peaksid olema kuupäeva tüüpi, mitte nVarchar või char. Teine punkt mida veerutüüpide loomisel tasub alati läbi mõelda on, kui täpseid andmeid meilt nõutakse? Lihtne näide selle kohta on kuupäevad, mida kasutatakse alati väga palju, näiteks registreerimaks uue sissekande loomise kuupäeva. Tihti kasutatakse andmebaasis kuupäeva tüübiks automaatselt DateTime, mis võtab ruumi 8 baiti ja täpsuseks kolm millisekundit. Kuid kui tihti on selline täpsus süsteemides vajalik? Jah, tõesti on kohti kus see on väga kriitiline, kuid kindlasti leidub rohkem situatsioone, kus piisab ka minutitäpsusest.

Näiteks uudisteportaalides on avaldamisajad tihti märgitud ainult kuupäeva ja minutitega. Selle jaoks on ideaalne SmallDateTime, mis on minuti täpsusega ja lisaks võtab poole vähem ruumi(4baiti). Lisaks on andmebaasis olemas nüüd täpselt vajalikus formaadis kuupäev ning me ei pea hakkama seda veebirakenduses andmete väljaküsimusel seda omakorda ümber hakkama vormindama, mis säästab veel rohkem ressurssi.

Kindlasti tuleb säilitada aga ka paindlikus ehk tinyint võtab küll 4 korda vähem ruumi, kui Int, aga see eest saab tabelisse kokku tekitada 256 unikaalset kannet kui tegemist on primaarse võtme väljaga.

Selliseid näiteid leidub kõigi andmetüüpide kohta. Ehk enne tabelite loomist tuleks kindlasti tutvuda konkreetse andmebaasimootori dokumentatsiooniga ja teha selgeks, milliseid võimalusi pakutakse ja mida meil täpselt vaja on. Eelpool mainitiud SmallDateTime on saadaval alates SQL Server 2008 versioonist.

GUID

Huvitav on mainida ka GUIDi kasutamist. Jõudluse poolelt tundub olevate GUID'i kasutamine hullumeelne kui võrrelda seda näiteks INT tüübiga. (Ikkagi 16 baiti vs 4 baiti). Samas GUID'iga kaasneb ka kaks plussi. GUID on alati unikaalne, kui INT on unikaalne ainult ühes tabelis. See tõttu on GUID'i kasutamisega välistatud, et kokku viiakse omavahel tabelite veerud, mis tegelikult ei ole omavahel seotud. Teine pluss on see, et GUID ei saa kunagi otsa.

Üks enim levinud argument, miks mitte GUIDi kasutada primaarse võtmena ja eelistada sellele INTi on asjaolu, et see nullib ära klasteeritud indekseerimisega saavutatava jõudlusevõidu. INT kasvab automaatselt ja seega iga uus sissekanne automaatse primaarse võtme kasvamise puhul on viimane, GUID genereeritakse automaatselt ja see tõttu ei pruugi see viimane olla. Iga uus sissekanne nõuab indeksite uuendamist ja see tõttu põhjustab selle kasutamine lehtede poolitusprobleeme ja indeksite fragmenteerumist. Alates SQL Server 2005 versioonist saab selle vastu kasutada funktsiooni NewsequentialID(), mis tagab, et iga järgmine GUID on eelmisest suurem. Seega ei tule uus sissekanne mitte lehe keskele, vaid läheb alati viimaseks. Samas tuleb tõdeda, et kuna GUID kasutab rohkem mälu, siis tekib juurde indekseerimisel rohkem lehti ja indeksite uuendamine on kulukam kui INT tüübi puhul.

Päringute analüüs

Päringute analüüs. Enne päringute optimeerimist on vajalik teada, millised päringuid üldse andmebaasi tehakse ja kui kaua aega nende täitmine võtab. Kindlasti peab arvestama ka päringute arvu, kuna optimeerides päringut mida kasutatakse kord kuus 100ms võrra kiiremaks, pole nii prioriteetne nagu optimeerida päringut mida tehakse päevas 1000 korda 10ms kiiremaks. Leidmaks päringuid, mida tehakse saab kasutada sellist SQL päringut:

-- alljärgneva päringuga saad lugeda protseduur cache'i sisu
-- saadav tabel sisaldab küllalt infot otsustamaks, millised protseduurid või päringud kulutavad serverit

SELECT sql.text, qs.EXECUTION_COUNT, qs.*, p.* 
FROM sys.dm_exec_query_stats AS qs 
CROSS APPLY sys.dm_exec_sql_text(sql_handle) sql
CROSS APPLY sys.dm_exec_query_plan(plan_handle) p
WHERE text NOT LIKE '%sql.text%'
ORDER BY 

-- vali ise mis järjekorras sa vastust tahad
--qs.total_worker_time desc  -- kulutatud aja järgi
qs.EXECUTION_COUNT DESC  -- täitmiskordade järgi
--qs.max_elapsed_time DESC  -- maksimaalse kestuse järgi

--vajaduse saad protseduur cache'i puhastada
--CHECKPOINT				--writes dirty pages to disk
--DBCC FREEPROCCACHE		--clears entire plan cache

--NB! Viimases veerus saadud tabelis on XML kujul Query Plan
--Salvesta see laiendiga sqlplan ja ava Management Studios - ja imesta :)

(http://www.sarv.ee/ftp/henn/SQL/Proc%20cache%20statistika.sql)

Selle abil saab leida enim tehtavaid SQL päringuid nii kulutautd aja järgi, maksimaalse aja järgi, kui ka täitmiskordade järgi. Kui potensiaalsed päringud, mida võiks optimeerida on leitud, saab nende analüüsimiseks kasutada SQL Serveri Päringu täitmisplaani (Query Execution Plan). See näitab vajalike operatsioone päringu täitmiseks. Seda tuleb lugeda vasakult paremale, alt üles. Nii on võimalik leida ülesse probleemseid kohti, näiteks kui indekseerimine ei tööta.

Päringute optimeerimine

Info saamiseks andmebaasist tehakse päringuid, kus vastavalt seatud tingimustele väljastatakse sobivad tulemused. Nende loomisel ja kirjutamisel tuleb jälgida mõningaid lihtsaid võtteid, et vältida üleliigset ressursi kulutamist.

Infot küsides peab alati kirjeldama, mida me tahame tagasi saada. Ehk näiteks SELECT * päring võib olla päris korralik jõudlusetapja, olukorras kus meil on tabelis 10 välja, kuid tahame saada kätte neist ainult kahte. Sellisel juhul on tegemist ebavajaliku ressursiraiskamisega. Lisaks on sellisel juhul ka tabelite indekseerimisest väga vähe kasu, kuna kõigi veergude kättesaaamiseks tuleb teha lisapäringuid.

Päringuid kirjutades peaks küsima alati seda, mida meil vaja on. Võimalusel tuleks vältida eitusi.

Andmebaasi töö sõltub väga palju selle ülesehitustest ja konkreetsetest päringutest. Selle optimeerimiseks peab analüüsima juba loodud ja loomisel olevaid päringuid, et näha kuidas nad käituvad. Selle jaoks on soovitatv kasutada SQL Serveri Query Editor'i kus on võimalik näha päringu täitmist kasutades Execution plan'i. Nii on võimalik kindlaks teha, näiteks kas loodud indekseid kasutatakse, kuidas täpselt toimub päringu täitmine ning kui palju see aega võtab. Selle alusels saab vajadusel muuta indekseerimist või päringuid.

Protseduurid

Andmebaasi jõudluse tagamisel on hea praktika protseduuride kasutamine. Hästi kirjutatud protseduurid on väga kiired. Lisaks on neid lihtne testida ja hallata võrreldes ad hoc päringutega. Samuti on need turvalisemad, kuna kasutavad parameetreid, mis antakse neile kaasa. Ka rakenduseloojatel on lihtsam kutsuda välja protseduur, mille sisendiks antakse parameetrid, kui kirjutada ad hoc päringut, mis avab võimaluse SQL "injenction" rünnakuteks ja seega on ka üheks turvariskiks. Viimaseid on ka raske hallata ja asuvad reaalsetest andmetest kaugel.

Kasutades protseduure on lihtsam jälgida päringute täitmist ja ajakulu, võrreldes tavalise SQL päringuga, mis tuleb väljaspoolt andmebaasi. Kuna kaasa antakse ainult parameetrid, siis on ka edastatav andmemaht väiksem. Samuti asub see ka andmetele lähem.

Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käsku SET NOCOUNT ON. Viimasega võib sõltuvalt päringu keerukusest võita kuni 17% selle täitmise kiirusest. Vaikimisi on NOCOUNT välja lülitatud ja see tõttu saadab saadab SQL Server kaasa ka alati ridade arvu, mis päringu tulemusena leiti.

Lisaks tuleks vältida kursoreid. Kuigi nad on väga paindlikud ja võimaluste rohked, tuleb nende kasutamisel maksta ränka hinda jõudluses. Kui protseduurides kasutatakse kursoreid, siis nende optimeerimiseks tuleks alustada kursorite eemaldamisest.

Indekseerimine

Indeksid mõjutavad SQL Serveri jõudlust märgatavalt. Indekseerimine on nagu raamatu sisukord. Kui soovime leida vajalikku infot, vaatame sisukorda ning leiame õige koha. Samamoodi käime pidevalt andmebaasist infot otsimas, kus mingi sissekanne asub. Tabel ilma indeksita on nagu raamat sisukorrata - millegi leidmiseks peame lappama läbi terve raamatu, et leida õige koht, mida otsime ja see on kulukas. Kui andmebaasis on tabelid õigesti indekseeritud toimub otsimine nagu raamatu sisukorrast(kiiresti).

Indekseid on kahte tüüpi - klasterdatud ja klasterdamata. Klasterdatud indekseerimiseks on ideaalsed väljad tabelite primaarvõtmed kahel põhjusel: 1) see väli on alati unikaalne 2)infot otsitakse tihti selle võtme järgi. Vaikimisi luuakse primaarvõtme veerule alati klasterdatud indeks. Selle loomiseks käsitsi tuleb kasutades SQL lauset:

CREATE UNIQUE CLUSTERED INDEX index_id ON TABLE (veeru_nimi)

Tabeliveerg millele see luuakse, peab olema alati unikaalne.

Mitte klasterdatud indekseerimise puhul ei pea olema väli unikaalne. Luuakse lausega: CREATE INDEX võti ON tabeli_nimi(veeru_nimi). Sellest on ainult siis kasu, kui me valime ainult konkreetse välja, mis on klasteerimata indeksisse määratud. Kui aga on vajalik lisaks veel välju, tuleks kasutada Coverage-Indexit ning lisada ka need väljad. Selleks tuleb kasutada lauset:

CREATE INDEX võti ON tabeli nimi(veerg) include ( tabeli_veerg1, tabeli_veerg2,..).

Sobib eriti veergudele, kus kasutatakse GROUP BY, COUNT(*) päringuid.

Indekseerimiseks ei sobi väljad, mis on väga mahukad. Näiteks nVarchar(200), mis võtab palju ruumi ja indeksite loomine on mahukas protsess.

Indekseerides tabeli veerge kõhutunde järgi, võib see mõjuda jõudlusele hoopis negatiivselt, kuna õigete ridade leidmiseks peab ikkagi tegema lisapäringuid. Selle vätlimiseks tuleks jälgida päringu täitmise plaani, mis näitab, kuidas päringuid läbi viiakse ja kas indeksite tabelit üldse kasutatakse. Nii võib leida kohti, kus tabel on küll indekseeritud, kuid selleks on kasutatud valesid välju ja see tõttu ei saa kasutada kunagi otsimist indeksi järgi ja päringu täitmine võtab rohkem aega ning ressurssi.

Indeksite loomisel peab arvestama, et indekseerimisega peab maksma natuke hinda ka jõudluses. See tõttu tuleks kaasta indeksitesse minimaalselt välju. Mida rohkem on välju, seda kulukam on indeksite uuesti arvutamine, mis leiab aset iga DDL käsu puhul. Indeksite tabel koosneb lehtedest ja lisades uue sissekande tuleb lehed uuesti luua. Eriti halvasti mõjub see siis, kui uus sissekanne tuleb indeksi lehtede keskele. See eeldab lehtede uuesti loomist ja nende poolitamist. See tõttu tuleb hoolikalt kaaluda, kus kasutada rühmitatud indekseid.

Alates SQL Server 2008 versioonist on võimalik kasutada filtreeritud indekseerimist, mis tähendab, et klasterdamata indeksite loomiseks kasutatakse andmetest ainult mingit osa, mis vastab seatud tingimustele. Selle loomiseks on lause:

CREATE INDEX index_id ON tabeli_nimi(tabeli_veerg) WHERE tingimus 

. Vajadusel saab ka siin kasutada kaetud indekseerimist.

Transaktsioonid

http://msdn.microsoft.com/en-us/library/ff647793.aspx#scalenetchapt14%20_topic9 Valesti kirjutatud transaktsioonid võivad mõjuda andmebaasi tööle halvavalt. Selle vältimiseks on levinud praktikad: tuleks vältiad pikki transaktsioone, kuna nende ajal toimub tabelis lukustamine. Soovitatav on valideerida enne transaktsioone juba rakenduses andmed, et vältida transaktsiooni ajal vigade tekkmist, mis pikedab neid. Lisaks ei tohiks transaktsioone alustada enne, kui kõik vajalikud andmed on olemas, kuna lukustus lõpeb alles siis, kui kõik andmed on saadetud. Halb näide on näiteks see, kui alustada transaktsiooniga, kuid selle edukaks lõppemiseks on vaja veel kasutaja poolt sisendit. Tabel on lukus seni, kuni kasutaja on sisendi andnud.

Deadlockide vältimine(üks transaktsioon ootab teise taga ja võivadki igaveseks ootama jääda) Parallelism tuleks sättida üheks. Transaktsioonid peaksid olema lühikesed, kõik üleliigne tuleks eemaldada. ja veel punkte. Lisaks tuleks sättida lukkudele time-out ühenduses, kuna by default võibki igaveseks ootama jääda. SQL Server Bible 1382.

Sõnaotsing

SQL Server pakub sõnade otsimiseks lahendust, mille nimeks on FullTextSearch. Seda saab kasutada alates Standard versioonist ning töötab indekseerimise põhimõttel. See lahendus pole küll mõeldud otseselt otsingumootoriks, kuid see on väga hea jõudlusega ning täidab igati oma põhiülesannet, hoides samal ajal ressursikasutuse madalana. Kindlasti tuleks seda eelistada algelisele otsingule, kus kasutatae LIKE operaatorit, mis on aeglane.

Andmebaasi konfigureerimine

Parimate praktikate kohaselt soovitatakse jätta palju variante vaikimisi, kuna nii töötab server kõige optimaalselt ning nende muutmisel võib olla effekt jõudlusele hoopis negatiivne

Startup Manager Kui soovida SQL Serverist pigistada välja viimane, siis võib SQL Server Configuration Manager'i all saab lisada Startup Parameters alla parameetri -x, mis võimaldab maksimaalselt jõudlust. Selllel on aga üks väga suur miinus. Nimelt lülitatakse kõik monitoorimisvõimalused selleks välja ja jõudlusprobleemide jälgimine ja otsimine muutub peaaegu võimatuks.

Ühenduste automaatne sulgemine(Auto Close) Ühenduste automaatset sulgemist saab kontrollida graafilisel Management Studiost ja käsuga: ALTER DATABASE <ANDBEMAASINIMI> SET auto_close ON/OFF. Kui Auto Close on lubatud, siis peale kõigi aktiivste ühenduste sulgumist andmebaasiga vabastab SQL server kõik selle andmebaasi ressursid, mis teoreetiliselt peaks andma rohkem ressursse mõnele teisele andmebaasile. Pealtnäha võib see mõjuda jõudlusele hästi, kuid tegelikult on see kindel viis kuidas hävitada SQL Serveri jõudlus, kuna paljud rakendused sulgevad ja avavad ühendusi korduvalt. Uute ühenduste puhul tuleb aga andmebaas uuesti laadida, kompileerida protseduurid ja arvutada päringu läbiviimise plaanid. See tõttu peaks see ühenduste automaatne sulgemine olema keelatud, mis on ka kõigis SQL Serveri versioonides vaikimis, välja arvatud SQL Express.

Ühenduste automaatne sulgemine peaks olema lubatud ainult siis, kui tegemist on andmebaasiga, mis hoiab endas arhiivi ja kasutatakse väga vähe.

Automaatne kahanemine (Auto Shrink) Samuti peaks olema keelatud käsuga ALTER DATABASE <Andmebaasinimi> SET AUTOSHRINK OFF; Kui andmebaasil on üle 25% vaba ruumi, siis see põhjustab andmete ja logifailide kahandamise operatsiooni. Failide kahandamine on väga kulukas protsess.

ASP.NET tehnoloogiast tulenevad optimeerimisvõimalused

Web.config

web.config failis asub informatsioon veebirakenduse seadistuse kohta nagu näiteks andmebaasiga ühenduse loomiseks vajalikud parameetrid või kuidas toimub rakenduse kompileerimine. ASP.NET kasutab selles failis olevat infot, et luua rakenduse ülesehitus. Kui testkonnas testida rakendust, peaks olema kindlasti web.configis olema parameeter "compilation debug" väärtus true. Vigade esinemise korral on sel juhul neid lihtne leida. Veebirakenduse tõstmisel live serverisse tõstmisel peab jälgima, et antud parameeter oleks false. Vastasel juhul kompileeritakse pidevalt veebirakendust iga lehe laadimise ajal uuesti ja see omakorda kasvatab protsessori ja mälu kasutust. Kõige kindlam viis selle vältimiseks on muuta serveris asuvat machine.config faili ja lisada parameeter deployment retail="true". Nii on kindel, et ükski veebiaplikatsioon ei kasuta antud serveris debug mode'i. Ainukeseks miinuseks selle puhul on, et vea ilmnemisel ei kuvata vea täpset asukohta(Rea numbrit ja veakirjeldust).

Lisaks tasub web.config faili lisada ka outputcache'imise erinevad profiilid, millega saab määrata kui kaua lehte serveri mälus hoitakse. Kui lehele on tulemas suur koormus või midagi muud, saab ühest kohast muuta kõikide cahche'ide kehtivuse pikkust, mis kasutavad konkreetset profiili.

Viewstate

Viewstate'i kasutatakse, et hoida väärtusi ASP.NET tööriistade(controls) objektide kohta. Lehe rendendamisel genereerib ASP.NET ühe peidetud välja, mis kannab nime __VIEWSTATE, kus on see info sees. Nii on võimalik antud väärtuseid kasutada ka peale kliendi-serveri vahelist suhtlust, kui selleks kasutatakse postbacki, mille kutsub välja näiteks nupulevajutus. Hoides selles aga suurel hulgal andmeid, kasvab see tõttu ka lehe suurus ning selle laadimise aeg. Arvestama peab ka sellega, et lehe renderdamisel tuleb viewstate'i serialiseerida ja deseriaaliseerida. Lisaks võib see vähendada Garbage Collection'i efektiivsust. Sellepärast tuleb selle kasutamisega olla ettevaatlik ja eemaldada kohtadest, kus seda vaja ei lähe, kuna see mõjub jõudlusele halvasti. Näiteks genereerivad kõige rohkem viewstate'i ASP.net enda tööriistad Listview ja Gridview. Lehel sisalduva viewstate'i hulga analüüsimiseks on hea tööriist ASP.NET ViewState Helper, mis töötab Firefoxi ja Internet Exploreriga. Selle abil on võimalik näha, kui suure osa moodustab kogu lehe suurusest viewstate. Vaikimisi on see ASP.NET'is igal pool sisselülitatud. Soovitatav on see välja lülitada kohtades, kus ei toimu serveri poolseid kontrolle ja ei kasutata postbacke. Seda saab välja lülitada erinevatel tasemetel: serveris(machinge.config), veebirakenduses(web.config), lehel <%@ Page EnableViewState="false" %> kui ka ASP.NET tööriistades endas(EnableViewstate=false).

Postback'i kontrollimine Kui lehel on lubatud viewstate ja toimub postback, tuleb seda kontrollida kasutades IsPostBack() meetodit, mis teeb kindlaks, kas tegemit on postbackiga. Kui on, siis pole mõtet enam uuesti andmeid pärida, vaid kasutada juba olemasolevaid.

ASP.NET enda tööriistad

Enimlevinud tööriistad, mida tihti kasutatakse on GridView, Listview ja Repeater. Neid kõiki on mugav kasutada, erinevate ????? loomiseks. Esimesed kaks neist genereerivad aga suurel hulgal viewstate'i. Kui eesmärgiks on tavalise listi loomine(näiteks uudiste), siis peab kindlasti selle keelama. Nende tööriistade kasutamisels tuleks pöörata tähelepanu ka sellele, kuidas saada väärtuseid allikast kätte. Väga levinud viis on selleks kasutada süntaksi: <%#Eval("fieldname")%>, mis defineerib välja nime, kuskohast väärtust päritakse. Seda on lihtne kasutada, olenemata sellest, kas on tegemist objektide listiga või DataTable'iga. Tegelikult tuleb sellise süntaksi puhul maksta hinda jõudluses, kuna küsitava välja tüüp ei ole tegelikult defineeritud ja selle kindlaks tegemiseks kasutatakse peegeldust.(reflection) Nii tuleb 10 rea väärtustamiseks teha Eval operatsiooni tegelikult 20 korda, kuna esialgu pole teada, millist tüüpi andmetega tegu on. Parem variant on viidata kohe klassile, kust otsitav väli pärit on nagu näiteks:

<%#((MyClass)Container.DataItem).field1%> või DataTable kasutamise puhul <%#((DataRowView)Container.DataItem).field1%>.

Ainuüksi 10 rea lisamisel võib kiirusevahe olla enam kui kümne kordne, viimase variandi kasuks. Selle kasutamisel peame arvestaam, et muutes näiteks klassinime, peame muutma seda ka kohas, kus pärime välja väärtuseid.

ASP.NET genereerib automaatselt html'i kõikidele väljadele ID'd, kui need on ka koodis määratud. Näiteks kui meil on ASP.NET'i pildikomponent parameetritega <asp:Image ID="imgMainItem" runat="server"/>, siis sõltuvalt selle sügavusest lehtede hierarhias võib peale kompileerimist htmli vaadates näha, et antud välja ID'ks on saanud hoopis id="ctl00_leftColumn_ctl00_Vaikekategooria3_imgMainItem". Nagu näha on tegemist üpriski mahuka nimetusega. Kui aga tegelikkuses seda id'd meil vaja ei lähe, siis peaks jätma selle määramata. Mahuka esilehe puhul on sellega võimalik hoida päris palju ruumi kokku. Kui siiski vajame ID'd, võime selle peale kasutamist ära nullida. Eht näiteks: imgMainItem.Src="pilt.jpg"; imgMainItem.ID=null;

Cache

Cache'imine on üks lihtsamaid viise, kuidas muuta veebirakenduse ja ka andmebaasi tööd optimaalsemaks, hoides enimkasutatavaid ressursse mälus. Sellest andmete kättesaamine on lihtsam ja kiirem, kui selle pärimine pidevalt andmebaasist või kuskilt mujalt. ASP.NETis on kasutusel Cache API hoidmaks enimkasutatavat .... ja outputcache, mille korral salvestatakse serveri mällu terve leht. Selle kasutamisel peab arvestama, et vajalike andmete/lehtede hoiustamiseks kasutatake serveri mälu. See tõttu peab läbi mõtlema, mida on vaja cache'ida ja mida mitte, eriti siis kui serveri mälu on vähe. Head kandidaadid cahce'imiseks on lehed/andmed, mida kasutatakse kõige rohkem või mille kätte saamine on väga kulukas protsess. Enamasti on selleks näiteks esileht ja mõned suuremad listid ning otsingutulemused. Cache API'l ja OutPutCache on küll kaks erinevat asja, kuid põhimõte on neil siiski sarnane. Mõlemale on võimalik ette anda aeg, kui kaua aega neid serveri mälus hoitakse. Lisaks saab mõlema puhul kasutada SqlCacheDepencyt, mis võimaldab jälgida, kas andmebaasitabelites on muudatusi toimunud. Cache kustutakse sellel juhul, siis kui jälgitavas tabelis toimub muudatus. Selle toimimiseks peab andmebaasis lubaba tabelitel SqlCacheDependency ja ka web.config failis kajastama seda. On võimalus ka kasutada mitme tabeli jälgmist. Soovitatav on kasutada tabeleid, kus tihti muudatusi ei toimu, vastasel juhul on Cache pidevalt tühi ja andmete saamiseks tuleb siiski päringuid teha. Sellisel juhul tuleks anda ajaline intervall, mille tagant andmeid uuendatakse. http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx. Cache API puhul on võimalik jälgida Cachedependency kasutamisel ka näiteks xml failide muutumist.

OutPutCache

OutPutCache'i puhul salvestatakse terve dünaamiliselt loodav leht serveri mällu. Peale seda kuvatakse lihtsalt mälus olevat lehte. Seda saab kasutada nii terve .aspx lehtede salvestamiseks, kui ka usercontrolide puhul. OutPutCache jaoks tuleb lisada järgnev kood lehe ülaossa: < %@ OutputCache Duration="60" VaryByParam="None" % > Need kaks parameetrit on alati kohustuslikud. Duration näitab kui pikka aega lehte serveri mälus hoitakse. Lisaks on levinumad parameetrid veel: Shared="true/false" - saab kasutada ainult usercontrollide puhul. Kui true, siis cache'itakse see kõikidel lehtedel. VarByParam="parameetrinimi" - arvestatakse querystringidega. CacheProfile="profiilinimi" - web.configis asuv outputcache'i profiil. SqlDependency ="adnmebaasi/tabeli paar" - defineeritakse andmebaasi /tabeli paarid, mille muutumise korral leht serveri mälust kustutakse. http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx Lisaks on üks huvitav parameeter veel VaryByCustom, mille kasutamiseks tuleb Global.asax'is override'ida GetVarByCstomString meetod: Näiteks: public override string GetyVarByCustomString(HttpContext context, string custom){ if(custom=="weekday"){ return .... }else{ return bas.GetVarbyCustomString(context, custom) } } ASP.NET ei hooli stringi tegelikust sisust, vaid kontrollib seda, kas vastav stringi väärtusega leht on juba serveri mällu salvestatud. Kui on, siis serveeritakse leht serveri mälust, vastasel juhul lisatakse uus lehe koopia mällu. Olen seda saab kasutanud näiteks feedi cache'imiseks, mille loomine oli väga kulukas ja mida tohivad näha ainult teatud IP aadressitega kliendid. Tavalise OutPutCache'i lisamine on välistatud, kuna kui võõra IP'ga klient tuleb, näeb ta ikkagi feedi sisu, leht on serveri mälus ja outputcache'i puhul lehe eventeid ei käivtata. Teine halb asi, mis võib juhtuda on kui võõra IP'ga klient tuleb siis kui lehte pole veel serveri mälus.Sellel juhul aga läheb terve feed katki, kuna serveri mälllu salvestatakse leht, mis on tühi, kuna sel hetkl käis lehel keelatud IP'ga klient. Lahenduseks oli override'ida GetVarByCustomString meetod ja cache'ida leht IP põhiselt.

Cache API

Cache API puhul ei hoita serveri mälus mitte tervet lehte, vaid soovitud väärtusi, mis lisatakse sinna koodifailis. Näiteks: Cache.Insert("võti", "väärtus"). Tihti on selleks list objektidest, DataTable või midagi muud sarnast. Lisamiseks kasutatakse võti/väärtus paari, millele saab lisaks kaasa anda aegumise intervall või sõltuvus andmebaasitabeli muudatustest(SqlCacheDependency). Nii saab vähendada väärtuste loomiseks tehtavaid operatsioone. Enne Cache'ist väärtuste väljaküsimist tuleb alati kontrollida, kas vastava võtmega on seal üldse midagi olemas, kuna vahepeal kustutakse serverimälus hoiustatud väärtusi, kui serveril on vähe mälu, objekt aegub või dependency muutb. sest need kustutakse vahepeal serveri mälust. (Kas tuleks panna ka mingid koodinäited? http://msdn.microsoft.com/en-us/library/ms178597.aspx

.NET raamistiku vahenditest tulenevad optimeerimisvõimalused

Koodi optimeerimine ei puuduta ainult koodi kirjutamist, vaid kuidas seda teha. Juba lihtsamate praktikate jälgimine võib anda olulist võitu. Tuleks vältida kordusi, kuna see genereerib liiasusut ja võtab ilmaasjata mälu. Objektid tuleks initsialiseerida võimalikult hilja:alles siis kui neid kasutatakse. Nende loomine võtab küll vähe aega, kuid nad allutavad endale seniks mälu kuni neid enam ei vajata. See tõttu tuleks teha objektidega toimetamised võimalikud lühikesed ja siis nad deinitsialiseerida(anda väärtuseks null). Siis teab GC, et võib objekti "heap"ist ära kustuta. Kui objekt initsialiseerida varakult ja seda pikalt kasutada, siis võib ta tõusta GC kõrgemale tasemele ja jääda nii kustutamata, kasutades ilmaasjata mälu.


Stringide liitmine.

Kui teha stringide mahukaid liitmisoperatsioone, on soovitatav kasutada StringBuilderi append meetodit. Kui tegemist on vähem kui seitsme stringi liitmisega, siis tuleks kasutada + operaatorit. Kui ühekorraga liita suurem kogus stringe, on mõistlik kasutada samuti + operaatorit, kuna ainult stringi lõpptulemus luuakse.

Võrdlused

Erinevate objektide võrdlemiseks tuleks kasutada Compare meetodit nii stringide kui ka kuupäevade puhul, kuna see on kiirem. Eriti on see kasulik stringide puhul, kui tegemist on tõusutundmatute võrdlustega.

Veahaldus

Veahaldus on kulukas protsess ja selle valesti kasutamine võib maksta väga valusalt kätte jõudluses. Toome näite. Olgu meil stringide list ja me peame kontrollima kas neid on võimalik Guidides parsida. Selleks on kaks võimalust: kasutada tavalist try-catch veahaldust või meetodit TryParse(). TryParse proovib sisendiks antud parameetrit parsida ja kui see õnnestub, siis tagastab väärtuse true ja parsitud väärtuse. Kui parsimine on edukas, töötavad mõlemad variandid sama kiiresti. Kui aga parsimine ei õnnestu, on TryParse tunduvalt kiirem.

Koodinäide lk 74:

for(int i=0; i<1000; i++){
		int targetInt=0;
		try{
			targetInt = Int32.Parse("xyz");
		}catch{
		}
	}
	
	for(int i=0; i<1000; i++){
		int targetInt=0;
		if(!Int32.TryParse("xyz", out targetInt)){
		}
	}

Tulemus: Esimese variandi jaoks kulus 1052207 ticksi, TryParse jaoks 1522 ticksi. Vahe on märgatav ning võib järeldada, et try-catchi kasutamist tuleb vältida igal pool kus seda võimalik. See on siiski loodud ainult vigade töötlemiseks nagu näiteks andmebaasiühenduseavamine, kus ei saa seda tõesti muudmoodi kontrollida. Kindlasti ei tohiks kasutada seda programmis tingimuste täitmise kontrolliks.

Tsüklid Kasutades foreachi on küll mugav koodi kirjutada, kuid arvestades jõudlust ei ole see kõige parem variant, kuna listi läbikäimiseks kasutatakse enumeratorit ja see tõttu on see ka kulukas. Sellele tuleks eelistada for tsüklit, mis on optimaalsem. Lisaks tuleks viimast kasutades hoiustada listi pikkus muutujas, et iga iteratsiooni ajal ei peaks seda uuesti arvutama, mis on küll väike, aga siiski ressursi raiskav operatsioon. Samuti ei tohiks küsida välja iga iteratsiooni ajal välja väärtusi, mis on kõik aeg konstantsed, vaid defineerida need enne tsüklit näiteks objektide puhul. Lk80

Strukt ja klass Võimalusels tuleks eelistada struktide kasutamist, kuna need annavad juurde jõudlust. Põhjuseks on nende erinevus mälukasutuses. Struktid paiknevad alati pinus(stack), peale meetodi täitmist kustutab kohe ära need. Mäluhaldus on väga lihtne. Klasside puhul on tegemist reference tüüpi, mille jaoks läheb lisaks vaja veel aadressi(tüüpobjektpointerit), sünkroniseerimisblokki(alati olemas), GC vajalikud väljad(bitid), alles siis hakkavad väärtused. Ehk üks integer võtab 3 integeri ruumi. Struct aga ainult ühe. Ka nende meetodite väljakutsumine on erinev, kuna value tüüpi, siis teab alati mis tüüpi välja kutsuda. Objekti meetodi väljakutsumisel viitab see tüübi tabelile... Staatilisi meetodeid tuleks kasutada, kuna tema puhul saab translaator panna õige aadressi. Struktidel on ka piirangud, kus neid kasutada ei saa. Nende puhul ei ole pärilust(inheritance) nagu klassidel. Teda ei saa olemasolevast klassist ega struktist tuletada, küll aga saab implementeerida interface'ist. http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx + hennu loeng. 00:43 H.Sarv. Võimaluse korral tuleks staatilisi meetoodeid kasutada, kuna translaator saab... 00:44 on koodinäide.

Listid Kollektsioonide kasutamist tuleks alati võimalusel vältida, neile tuleks eelistada massiive, mis on kõige kiiremad. Kui see pole aga võimalik, on soovitatav kasutada Genereerikuid nagu näiteks List või Dictionary. Viimane on eriti kiire kui listist on vaja otsida konkreetseid väärtuseid, kuna tegemist on võti-väärtus paariga. Lisaks saab võtme välja abil välistada duplikaatide esinemist, kuna see peab olema unikaalne. Listi loomisel tuleks anda ette ka selle suurus. Kui seda mitte teha, siis peale seda kui listis saab kohtade arv täis, korrutatakse olemasolev list kahega ja pannakse see selle uueks pikkuseks. Sorted lisit asemel List.Sort

http://msdn.microsoft.com/en-us/library/ms172181%28v=vs.80%29.aspx + hennu loeng. Samas soovitab üldse massiividele üle minna.

Mäluhaldus http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 Kui luuakse uus objekt, siis peale new väljakutsumist eraldatakse sellele mälu. Objekti kasutatakse ja ta "sureb" peale seda kui tema väärtus sätitakse nulliks või "else going out of scope". Peale seda vabastatakse see osa mälust ja seda saavad kasutada teised objektid. Need tuleb luua nii hilja kui võimalik, sest see säästab mälu kasutust ja nii ei teki ohtu, et see säilib kaua. Peale seda kui objektiga on toimetused tehtud, pole meil seda enam vaja ning see tuleks "ära visata" ehk väärtus võrtsustada nulliga. Nii teab Garbage Collector, et seda objekti enam ei vajata ning saab selle varakult ära koristada. Mälu puhastatakse siis kui vaja ja korjatakse ära see, mida ei kasutata. Kogu mälu jagatakse neljaks generatsiooniks. Kõik värsked objektid saavad mälu 0 generatsioonis, kui see saab täis, siis tuleb GC neid koristama. Kõik need objektid, mis sellele ajal ei osutu prügiks, tõstetakse esimesse generatsiooni, kuna on vajalikud. Kui 0 generatsioonis ei ole midagi kustutada, liigutakse esimesele tasemele. Finalizerite loomine objektidele on väga ebasoovitatav, kuna nad jäävad GC töö käigus ellu. Nad tõstetakse Finalizer qeuesse. Allas järgmisel prügikoristamisel jõutakse neile. Jäävad ette alles siis kui, hakatakse puhastama järgmisesse. GC.SupressFinalizer(kas on nii põhjalikult vaja). IDisposable on eelistatav. Eelistatav konstruktsioon on "using", mis hoolitseb selle eest, et selle sees tehtud objekt kustutakse peale selle lõppu. Tee pikaajalised objektid kõige pealt. Generatsioon 2's. http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5

Leitud võimaluste rakendamine

Leitud võimaluste rakendamine Töö praktilises osas tegelen leitud optimeerimisvõimaluste rakendamisega ja tulemuste analüüsimisega. Läbiviidavad muudatused puudutavad eelkõige ERR'i teise põlvkonna .Net portaale. ASP.Net optimeerimisvõimalusi kasutan lehtedele news.err.ee ja rus.err.ee. News'i valiku põhjuseks on asjaolu, et selle baasil on loodud ka mitmeid teisi portaale ehk leitud võimalusi saab lihtsalt neile üle kanda. Rus pidid algselt olema väike uudisteportaal, millest on praeguseks välja kasvanud meie üks suurima sisuga ERR .NET lehti. Lisaks on varem esinenud suurte koormuste puhul sellel portaalil märgatavaid jõudlusprobleeme. Prioriteediks on mõlema portaali puhul tegeleda esilehega, kuna need on võrreldes muude alamlehtedega sisuga kõige mahukamad. Lisaks korduvad mitmed esilehe komponendid alamlehtedel.

Kõigepealt on plaanis uurida, milliseid päringuid on andmebaasis seni täidetud kõige rohkem ja kui kaua aega need võtavad. See info võetakse live'i andmebaasist. Esialgseks analüüsiks kasutatakse kasutusel oleva andmebaasi koopiat. Mahukamate päringute puhul analüüsin nende läbiviimist, proovin leida "pudelikaela" ja rakendada mõnda leitud optimeerimisvõimalustest. See võib endaga kaasa tuua muudatusi andmebaasis või koodi poolel, sõltuvalt sellest, kus see päring asub.

ASP.Net optimeerisvõimalustest proovitakse esmasjärjekorras Cache'imist, kuna sellega on võimalik vähendada pöörumisi andmebaasi poole ja seega parandada ka selle jõudlust. See eeldab enne komponentide prioriteetide analüüsi, mille alusel saab otusta, mida saab Cache'ida ja kui kauaks. Lisaks proovitakse vähendada lehel viewstate'i suurust, mis on aktuaalne kui lahendust luuakse näiteks mobiilse saidi jaoks, kuna mobiilistandardite järgi ei tohiks lehed väga suured olla. Samuti tuleb kontrollida, et lehtedel kasutataks ASP.NET enda tööriistu kõige optimaalselt.

Kõige viimasena proovitakse rakendada .NET raamistiku vahenditest tulenevaid optimeerimisvõimalusi, kuna need ei pruugi anda alati nii suurt võitu võrrledes eelnevatega. Need mõjutavad ainult rakendusekihti, kui eelnevad aga mõlemat. Kontrollitakse veahaldust ja võrdlusi. Lisaks for ja foreachi, kuna tihti soovitatakse kasutada küll for'i, kuid .NET4 versioonis on juba foreach väga optimeeritud ja võib käituda isegi kiiremini. Kuna mõlemal testitaval veebirakendusel on puudulik andmekiht, siis structi ja klassi erinevusi ei saa testida.