Archive for August, 2008

Aug 30 2008

Objekt-orienteerituse lõks SharePointis

Published by Targo under Hea kood, Jõudlus, SharePoint

sharepoint.gif

Tavaliselt ma kirjutan üldistel “filosoofilistel” teemadel, aga viimase kuu jooksul on mul pistmist olnud mitme sarnase juhtumiga SharePointi customiseeritud arenduse teemal, sestap tänane erand.

Läbivateks sümptomiteks on siin:

  • Inimesed kirjutavad SharePointi objektimudeli peale igasuguseid huvitavaid algoritme
  • Arendaja masinal töötab kõik ilusasti ja enamvähem mõistliku kiirusega
  • Tegelikul paigaldusel või siis koormustesti all aga hakkavad operatsioonid arusaamatul viisil blokeeruma
  • Esmane uurimine näitab tavaliselt, et SQL Serveri CPU/mälu on punases

Nende sümptomite puhul on üsna tavaline, et arendajad on astunud objekt-orienteerituse lõksu. Objekt-orienteerituse lõksuks nimetan ma olukorda, kus arendaja kasutab objektiklasse, mis näevad üldiselt väga süütud ja ohutud välja, teadmata, milliseid tagajärgi nende kasutamine tegelikult kaasa toob.

Klassikaliseks ülesandeks äritarkvaras on andmebaaside peale mitmesuguste frameworkide ehitamine, mida arendajal hea ja lihtne kasutada oleks. Kirjutad aga koodi, sulle genereeritakse automaatselt õiged päringud ja anna muudkui tuld, eks? Tegelikult pole ükski päringugeneraator nii taiplik kui päris inimene ja genereerib andmebaasi jaoks enamasti rohkem tööd kui hädapärast vaja oleks.

SharePointi andmemudel on erijuhtum sellisest andmebaasile ehitatud vahekihist ja pole samuti nimetatud puudustest vaba, samas tulevad siin sisse veel mõned eripärad, millega arvestada. Nagu alguses toodud diagrammilt näha, on SharePointi perekonna toodete põhjaks Windows SharePoint Services (WSS), mille peale erinevad tiimid nagu Portal, CMS, Search, Excel Server, Project Server jne juba omaenda produkte loovad, ehk siis tegelevad SharePointi custom arendusega, just nagu mõni minu lahketest lugejatestki.

Peamine probleem on siin selles, et WSS teeb asju veidi erinevatel viisidel olenevalt sellest, kas tegemist on WSSi enda kuvatavate andmetega või läbi objektimudeli päritavate asjadega. See, mida WSS listides ise kuvab, pannakse juba väga madalal tasemel tervikuna kokku, peaaegu, et SQList otse HTMLi transleerides ja see protsess on väga efektiivne.
Objektimudeli puhul tehakse hulk .Net objekte, mis on enamasti suhteliselt õhukesed. Kui mingit alamobjekti või välja vaja läheb, tehakse selleks tavaliselt eraldi SQL päring. Samas pole arendajal 99% juhtudest aimugi

  • milline see SQL tegelikult täpselt välja näeb
  • kas mitmete sarnaste päringute tegemine on üldse mõistlik või küsitakse enamasti samu andmeid

Tulemuseks oli, et iga kord, kui mõni uus arendaja SharePointiga seotud toodetes koodi hakkas kirjutama, sai see kood enamasti ebaefektiivne ja tekitas palju andmebaasipäringuid. Kui aga palju kasutajaid teeb korraga palju päringuid, ei jõua SQL Server neid kõiki korraga teenindada ja osad asjad jäävad lihtsalt toppama. Lahenduseks sai, et päringute arvust sai mingis mõttes püha lehm, iga kord, kui keegi tahtis oma koodi mingit uut päringut lisada, tuli “päringupolitsei” ehk vastava arhitektiga konsulteerida.

Tegelesin ise jõudlusküsimustega SPS 2003 projektis ning seal saime asjad lõpuks nii kaugele, et näiteks portaali avalehe kui kõige populaarsema lehe kuvamiseks tehti lõpuks ainult 2 SQL päringut, üks WSSi listide ja web partide kõigi andmete korraga laadimiseks ja teine kontrollimaks, kas Portali areate ja navigatsioonistruktuuris on midagi muutunud (enamasti ei ole ja siis pole vaja midagi enamat teha, kui on muutunud, siis tuleb struktuur uuesti laadida, aga seda juhtub harva). Võrdluseks: tihti leiab SharePointile peale arendatud lahendusi, kus ühe lehekülje laadimisel sooritatakse näiteks 30 või 50 päringut. Aga päringute arv on selles mõttes otseses vastandseoses saidi jõudlusega.

Kuidas päringuid vähendada? Peamine rohi siinjuures on hoolikalt mõelda:

  • kas on tõenäoline, et need andmed on eelmisest kasutuskorrast saadik tegelikult muutunud?
  • Kui ei, siis luua mingi lihtne cache, mis neid andmeid meeles hoiab.
  • Kui andmed siiski aeg-ajalt muutuvad, aga see muutmine meie kontrolli all on, saab sellegipoolest cache’i kasutada ja andmete muutumise korral vastavad kirjed lihtsalt invalideerida.

Enamikul WSSi peale ehitatud SharePointi toodetel on peaaegu igal kasutajaliidese komponendil kas oma või jagatud cache, kus hoitakse harva muutuvaid andmeid. Cache’i invalideerimiseks saab rakendada juba väga mitmesuguseid strateegiaid, olgu siis aja- või mahupiiranguna või lihtsalt iga kord triviaalse päringuga kontrollides, kas midagi on muutunud.

Enamasti on täiesti piisav kasutada ASP.Neti Cache objekti (System.Web.Caching.Cache), see on ise väga kergekaaluline objekt ja ei tekita üldiselt mingeid probleeme.

Ehk siis selle asemel, et teha

SPListItem listItem = DoSomeStuffWithSPQuery(userInput);
string userDisplayText = listItem.Title;

saab kirjutada näiteks

string userDisplayText;
if(Cache[userInput] != null)
{
userDisplayText = (string)Cache[userInput];
}
else
{
SPListItem listItem = DoSomeStuffWithSPQuery(userInput);
string userDisplayText = listItem.Title;
Cache[userInput] = userDisplayText;
}

Põhimõtteliselt triviaalne, aga kui inimesed seda alati õigel kohal kasutaks, käiks enamik SharePointi installatsioone mitu korda kiiremini :)

Cache’imise puhul tuleb muidugi eelnevalt hinnata nende andmete mahtu, mida me cache’i paneme, et ei satuks sinna kogemata sadade kaupa megabaidiseid objekte, aga 95% juhtudest on inimestel tegemist lihtsate andmetega.

Kõigi päringute ülevaatamine ja vajaduse korral cache’imine on küllaltki loominguline ja aeganõudev tegevus, aga tasub end üldjuhul kindlasti ära, eriti kui seda teha juba varakult arendusprotsessi käigus, enne kui hakata ränka vaeva nägema koormustestide tulemuste analüüsiga.

Üks oluline aspekt, mida silmas pidada: SharePointi objektid ise (SPList, SPFolder, SPListItem jne) ei eksisteeri üldjuhul asjadena iseeneses, vaid on seotud mingi konkreetse web requestiga (SPRequest), mis omakorda laeb mällu hulga C++ objekte. Tavaliselt koristatakse nad requesti lõpus kenasti ära, aga cache’i pannes jäävad nad kuni cache’i tühjendamiseni alles, nii et nende alalhoidmine võib osutuda mälu mõttes ootamatult kulukaks. Sellepärast on alati kasulikum cache’ida nende objektide elementaartüüpidest väljade väärtusi, mitte objekte endid.

7 responses so far

Aug 08 2008

Kadunud poja tagasitulek

Published by Targo under Isiklik

Kuna seda on piisavalt palju kordi küsitud, panen oma Eestisse siirdumise detailid siia ka kirja:

Maandun Tallinnas 15. augustil. Elama hakkan Tartus, aga sebin ilmselt alatasa ka igal pool mujal ringi. Alates 25. augustist hakkan peamiselt olema Webmedia Tartu kontoris, kus tegutsen isehakanud guruna, samuti ka Microsofti ja Webmedia Tallinna kontorites ning Tartu Ülikoolis.

Loodan igatahes kõigi oma vanade ja uute sõprade ning tuttavatega peatselt juba päriselus suhelda :)

One response so far