Archive for the 'Hea kood' Category

Mar 15 2011

Kuidas liigutada Fuji mäge

Published by Targo under Hea kood, Jõudlus

Viimase paari nädala üks kõige poleemilisemaid IT-teemasid Eestis on kahtlemata valimistulemuste (mitte)näitamine, mida, kuidas ja kui palju on võimalik ning praktiline testida jt seonduvad küsimused. PostgreSQL leidis leidis endale ootamatult koha mainstream meedia sõnavaras ja igaühel on oma arvamus või ka mitu.

Vaidlejad kipuvad jagunema kahte leeri:

Ühel pool on need, kes väidavad, et sellise probleemi tekkimine oli üldse absurdne, oleks pidanud palju rohkem ja põhjalikumalt testima, stsenaariume läbi mängima jne. Nende iseloomulik tsitaat on: “kui mina midagi sellist teeksin, siis ma teeks küll palju paremini”.

Teisel pool on inimesed, kes on ilmselt ka ise sarnaselt põletada saanud ning võtavad tagasihoidlikuma positsiooni. Nendelt kuuleb väiteid stiilis: “teatud klientidega ongi väga raske”, “kõik konfiguratsioonid polegi saavutatavad” või “muidugi tahaks me ka paremini teha, aga elu seab omad piirangud” jne (tegemist pole muuseas üldse valimiste või Helmesega seotud rahvaga).

Minu meelest ei taba kumbki pool probleemi tegelikku iva. See, et tarkvaras esineb probleeme, on teatud määral paratamatu. Iga projekt on mingis mõttes uus, igal tarkvaratükil on müriaad sõltuvusi, igas konfiguratsioonis on nendest sõltuvustest erinev kombinatsioon jne. Me võime asju testida kuitahes palju, alati on garanteeritud mingid ootamatused, vähemalt ma ise pole osalenud veel üheski projektis, kus pärast asja valmimist poleks olnud põhjust käega otsaette lüüa ning mõne detaili tähelepanuta jätmise pärast oma taipamatust kiruda.

Lahendus ei peitu mitte selles, et kivist vett välja pigistada ja testmaatrikseid tuhandekordistada, vaid selles, kuidas tekkivatest probleemidest võimalikult valutult üle saada. Miks valimistulemused nähtavale ei tulnud, seda mina ei tea. Võibolla oli tõesti tegemist kriminaalse lohakuse ja puuduliku testimisega, aga võibolla siiski mingi konfiguratsiooni iseärasusega, mida polnud varem võimalik isoleerida.

Aga kui probleem ilmnes, oleks kindlasti olnud võimalik leida parem lahendus, kui järjekindlalt lubadusi anda, et “15 minuti pärast saab korda” ja samas uuesti ning uuesti sama reha otsa kukkuda. Kuna algandmed olid vähemalt laias laastus teada, oleks saanud üles visata kasvõi Exceliga tehtud staatilise pildi, mida iga paari minuti tagant värskendada ning keegi poleks probleemi tähelegi pannud. Suurim ebaõnnestumine oli siin võimetus outside the box mõelda ning eristada probleemi kriitilist osa (telekas ei muutu peamised numbrid) vähemtähtsast (andmebaas ei vasta päringutele piisavalt hästi).

Enamik IT-ettevõtteid annavad inimestele värbamisel suhteliselt otseseid ja igavaid katseülesandeid: progeda selline veebikomponent, disainida taoline andmebaasimudel jne. Selle tulemusel saame inimesed, kes suudavad lahendada tüüp-probleeme, aga ootamatuse ees tõstavad käed püsti. Samas, nagu ülal postuleeritud, on ootamatused ainus asi, mida kindlasti oodata võib.

Selline intervjueerimise viis testib faktide mäletamist, aga mitte mõtlemist.

Samas Microsoft ja ka mitmed teised ettevõtted on tuntud oma värbamiskultuuri poolest, kus rõhutakse eelkõige inimeste taiplikkusele ja probleemide lahendamise oskusele, vt kasvõi raamatut How Would You Move Mount Fuji. Küsimus seisneb siis selles, et kuidas Fuji mägi teise kohta nihutada. Sarnased pealtnäha programmeerimisega mitteseotud küsimused on nt “hinnata, mitu bensiinijaama on USA-s”, vt lähemalt nt Joeli asjakohasest artiklist.

Oluline on rõhutada, et Fuji mäe küsimuse puhul pole tegemist mingi tõmbekaga, vaid täiesti tõsise probleemipüstitusega, mis testib kandidaati oskust asjaoludesse süüvida, täpsustavat infot hankida (Miks on vaja nihutada? Kui palju on vaja nihutada? Millised ressursid meil kasutada on?) ning rasketele probleemidele loomingulisi lahendusi (tehnoloogia, tööjõud, poliitilised probleemid, jne jne) leida.

Kuna ma ise olin juba koolis suur ülesandelahendaja, on see lähenemine mulle  muidugi imponeerinud. Siiski võin kätt südamele pannes öelda, et harjumus katsuda ka kõige keerulisemates või absurdsemates situatsioonides lahendusi leida on mind karjääris aidanud rohkem kui ükski tehniline fakt või oskus.

PS Kirjutasin need näited enne maavärinat, mis terve Jaapani koos Fuji mäega kaks ja pool meetrit paigast nihutas. Oh well.

10 responses so far

Jun 22 2010

Teenusearendus vs tootearendus 3

Published by Targo under Hea kood, Raha

Eelnevalt alustatud teema kokkuvõtteks vastuseid mõnedele küsimustele, mida mult vahel Microsofti ja muu tootearenduse kohta on küsitud.

Kui Office’i ajagraafik on sellisel määral fikseeritud (vt teema 2.osa), kuidas jääb vigade parandamisega?

Vigade puhul kehtib sama põhimõte, mis feature’de puhulgi. Vigade parandamiseks on planeeritud teatud aeg ning kui tähtaeg lähemale jõuab, tõuseb järk-järgult latt, millise tõsidusega vigu veel parandatakse ja milliseid mitte. Peamiseks põhjuseks on siin kusjuures ära hoida, et ühe tuntud vea parandamine ei tekitaks uusi tundmatuid vigu. Kui release’ini on jäänud loetud päevad, parandatakse vaid tõsiseid turvavigu ning kui mõni selline leitakse, lükkub release tõesti edasi, et täiendavaks testimiseks aega anda. Iga selline edasilükkamine on aga kulla hinnaga, sest ka kõik seonduvad ja planeeritud tegevused alates CD-de trükkimisest kuni SteveB kõneni mõnel asjakohasel üritusel lükkuvad edasi.

Vead, mida ei jõutud parandada, jäävad (vastavalt tõsidusele) kas service pack‘i või järgmisse versiooni. Kuna tarkvara poodidesse jõudmine võtab aga mõnevõrra aega, saamegi situatsiooni, kus vahel on poest ostmise ajaks juba ka esimene service pack downloaditav.

Milline võiks olla tootearenduse versioonihaldus?

Eristaks siin kõigepealt kaht äärmust:

“Rätsepatöö” tarkvara oluliseks eripäraks on, et kliendile tehakse pidevalt mingeid väikesi kohendusi ja mugandusi. Niipea kui klient midagi tahab ja selle eest on nõus maksma, tehakse ka vastav asi ära.

Teises servas on tarkvara nagu MS Windows, mis elab oma elu, ja kui sa pole just Citigroup või US Department of Defence, on sul üsna vähe võimalust seda kuidagi suunata.

Samas on hulk tarkvarasid, mis on alguse saanud rätsepatööst, aga sealt edasi on neid veel (esialgu) käputäiele klientidele müüdud. Kuna arendusmeeskond on harjunud kliendi erisoovidele orienteeruma, tehakse ka siin mõnda aega samamoodi edasi. Tulemuseks on, et lisaks ilusale ja elegantsele põhifunktsionaalsusele kasvab tootele veel igasuguseid erikujulisi kombitsaid ja konfiguratsioone, mida läheb vaja vaid ühel või teisel meie klientidest. Ja kui me igaühele natuke erineva asja paigaldame, on versioonihalduse seisukohalt tulemuseks tohutu peavalu, sest selles situatsioonis muutub kasvõi regressioonitestimine kiiresti võimatuks.

Minu isiklik arvamus on, et sellist koodibaasi fragmenteerumist tuleks iga hinna eest vältida ja erinevad kliendid peavad saama võimalikult standardseid ja ühetaolisi tükke, nii on pikas perspektiivis ka nende enda elu lihtsam ja vigu vähem. See lähenemine aitab vältida ka “dll hell’i”. Tootearenduse puhul on meil igasuguseid versioone niigi palju (vanad versioonid, viimased versioonid, uued beetad jne), nii et peame oma konfiguratsiooni võimalikult lihtsana hoidma.

Suurte toodete näitena võib siin jälle tuua MS Office’i, mis koosneb praeguseks juba kümnetest erinevatest üksiktoodetest, aga selle asemel, et lasta kasutajail sealt suvalisi kombinatsioone valida, müüb Microsoft ikkagi ainult näputäit standardkonfiguratsioone. Sellegipoolest on Office’i arenduses terve tiim, mis tegeleb täiskohaga ainult versioonide ning build scriptide haldamisega.

Kui palju meil dokumentatsiooni vaja läheb?

Tootearenduse puhul tuletame meelde esimeses osas sissetoodud suurust ϰ, mis muuhulgas mõjutab otseselt ka aega, mis programmeerijatel tuleb kulutada toote hilisemalt toetamisele. Seetõttu on ka dokumentatsioon palju olulisem kui teenusena loodud tarkvara puhul, et toetusprotsess efektiivsem oleks. Konkreetselt Microsofti standardiks on see, et koodile tekib neli erinevat dokumentatsiooni: spetsifikatsioon, arendaja loodud tehniline disain, testija kirjutatud testplaan ja technical writeri tehtud kasutajajuhend.

Selle üle, kas viimase jaoks peaks eraldi inimene olema, võib muidugi vaielda. Me kõik oleme lugenud dokumentatsioone, mis on kirjutatud inimese poolt, kellel pole ilmselgelt olnud piisavalt võimalust asjast aru saada, vt kasvõi LRF-1914 näidet Joeli artiklis.

No responses yet

May 12 2010

Teenusearendus vs tootearendus

Published by Targo under Hea kood, Raha

mass_production

Olen praeguseks oma professionaalses elus sattunud osalema mitmesugustes projektides alates super-spetsiifilistest ühele kliendile optimiseeritud süsteemidest kuni super-üldistatud masstoodeteni.

Mis neil tegelikult vahet on?

Tarkvaraprojekti iseloomustavad kõige põhilisemad põhiparameetrid on:

  • Kasutajate arv K
  • Programmeerijate arv P

Toon lihtsuse mõttes sisse tähise ϰ = K/P (kreeka täht KAPA = Kasutajate Arv jagatud Programmeerijate Arvuga)

Finantsiliselt kehtib üldjuhul reegel, et suur ϰ => suur $, vaadake kasvõi Bill Gatesi. Sellepärast ongi peaaegu iga teenusearendaja kinnisideeks teha oma rätsepatööst “toode” ning liikuda tagumiktundide müügilt tiražeerimisele.

Samas tähendab suurem ϰ ka suuremat vigade parandamise kulu, iga täiendus või parandus tuleb viia palju suurema hulga inimesteni, kellel see omakorda mingeid probleeme või destabiliseerimist võib esile kutsuda.

Seega, mida suurem ϰ, seda kõrgem peab olema toote kvaliteet:

  • Läheb vaja paremaid programmeerijaid ja analüütikuid

Nt Microsofti tootearendusdivisjonid võtavad tööle ehk 2% inimestest, kes sinna oma CV-sid saadavad. Sellepärast on neil ka vaja piisavalt häid inimesi nagu tolmuimejaga mujalt maailmast kokku tõmmata. Vt ka staaride teemat.

  • Läheb vaja rohkem testimist

teenusearendus_rollid

ms_tootearendus_rollid

Diagrammid illustreerivad arendustsükli jooksul kulutatavaid inimtunde – kui projekt on “valmis”, lisandub sellele muidugi ka väline testimine.

Teema jätkub edaspidi…

No responses yet

Nov 16 2008

Tech-Ed’i märkmed I

Published by Targo under Hea kood, Maad ja rahvad, SharePoint

Saabusin just tagasi Barcelonast Tech-Ed EMEA Developers konverentsilt, mis nägi välja umbes nagu ülaltoodud pilt. Barcelona kohta võib öelda nii palju, et homseks saadakse ka selle hotelli internetiühendus ilmselt korda, kus ma peatusin (lubati ju!), ja et mis iganes härra Gaudit mõjutas, oli tegemist millegi väga potentsega.

Aga nüüd teemast. Mitmetes ettekannetes oli muidugi ka asju, mida ennegi siit-sealt nähtud ja kuuldud, aga organiseeritud kujul info edastamine on alati abiks.

Järgnevalt minu memory dump sellest, mis mulle päev hiljem veel meelde jäänud:

Arendusprotsess

Stephanie Saad, kes on muidu ka überlahe tädi, rääkis agile developmentist Visual Studio kontekstis. Me kõik teame üht-teist agile developmentist ja Visual Studio uutest võimalustest, aga paljud neist on omavahel üksüheses vastavuses, ehk VS featured on ehitatud spetsiifiliselt agile metoodikate toetamiseks.

Siin pildil on peamiste agile põhimõtete ülevaade:

VS toetab neid näiteks järgmiselt:

Andmebaasid

Noppeid SQL 2008 uute võimaluste teemal:

  • Intellisense ja parem debugimise support.
  • MERGE käsk, mis töötab vastavalt vajadusele nagu INSERT, UPDATE või DELETE
  • Tabelitüüpi parameetrid
  • Change tracking – tabelitel ja ridadel oleks nüüd nagu versiooninumbrid
  • Suurema täpsusega date/time andmetüübid
  • HierarchyId andmetüüp hierarhiliste andmete hoidmiseks
  • Andmetüübid geograafiliste ja geomeetriliste andmete hoidmiseks (spatial data)

SharePoint

MOSS 2007 SP2 tuleb välja 2009 kevadeks. Minu jaoks üks olulisemaid parandusi on automaatne SQLi indeksite rebuildimine, mis aita ära hoida SP saitide “hapuks minekut”, kus kestva töö järel SP päringute jõudlus degradeeruma kipub. Olen seda situatsiooni ise ka mitme kliendi juures täheldanud. Täpsemat infot siit: http://blogs.msdn.com/sharepoint/archive/2008/10/24/prepare-for-the-upcoming-office-sharepoint-server-2007-and-windows-sharepoint-services-3-0-service-pack-2.aspx

Juba praegu on olemas Visual Studio extensions for SharePoint (http://www.microsoft.com/downloads/details.aspx?FamilyID=3E1DCCCD-1CCA-433A-BB4D-97B96BF7AB63&displaylang=en). Järgmises Visual Studios (VS 2010) on juba sisse ehitatud vahendid SharePointi serveritega töötamiseks – samamoodi nagu praegu on VSil sisseehitatud vahnedid SQL Serveriga integratsiooniks.

Põhiliseks tulevikusuunaks on siiski SharePoint online, mis toetab pea kõiki võimalusi, mis kohapeal paigaldatud SharePoint: http://www.microsoft.com/online/sharepoint-online.mspx 

Muuseas, abiks ressurss nii algajale kui ka kogenud SP arendajale on http://www.microsoft.com/click/SharePointDeveloper/

Jätkub…

No responses yet

Sep 12 2008

Application Performance and The Trap of Object-Orientedness

Pidasin neil päevil Webmedias ettekande antud teemal. Põhimõtteliselt olen sel teemal siin ka varem juttu teinud, aga arendasin teemat natuke edasi.

Originaalslaidid saab leida siit, aga edasi juba sisu ise, koos minu märkmetega, mis on ehk hajusamad/kaootilisemad, kui minu tekst tavaliselt :)

trap_1.JPG

trap_2.JPG

trap_3.JPG

The basic tenets of OOP are abstractions, encapsulation, inheritance and polymorphism: Hopefully all of us know about them, and know when and how to use them. The main idea is that we don’t have to know what’s inside a component, we can swap them in and out, and do a bunch of other cool things.

Make no mistake about it, I think OOP is good, it makes us more productive, and it makes our code much more flexible, maintainable and extensible.However, it also has some inherent dangers: we see an API, it looks very safe and simple. We add 1 line of code that is using this API and introduce who knows what. Perhaps it adds 5 extra SQL queries? Or does some processing that doesn’t scale to our data?

It is extremely easy to misuse some technology that you don’t completely understand.For example, say, you have a very modern, grandma who loves all kinds of gadgets, and she has a brand new digital camera. She also has seven cats, and she takes a video of her cats, then uses the wizard in Windows XP to save to her desktop. For her, all the technologies that she uses are just pretty icons and pictures on the screen, she has no idea of what’s actually happening. All the real details are well hidden and encapsulated. So then she wants to email it to you, and drags&drops the icon of the video to her email. And BOOM, she has just sent you a 500 MB email. Oops. Now the applications are actually quite forgiving to such an operation, and might even survive it. However, all components will be thoroughly stressed: disk, memory, network, everything.
You might laugh at how silly grandma was, but in fact programmers perform the equivalents of sending 500MB files via email every single day.

 

trap_4.JPG

Let’s look at a civil engineering analogy.

In civil engineering, there are whole courses and thick handbooks about the properties of different materials. Various grades of steel, stone, wood and so on. Engineers have to know their strength, density, elasticity, how much they expand and contract in heat, all kinds of things

Now imagine using “encapsulated” building blocks. You see the blocks, they are nice and shiny, and the salesman tells you they are super good and strong. But you have no idea what’s inside them, how they are made, how they behave in different kinds of weather or stress. The engineers would rightfully ask: are you crazy or what?

Unfortunately, software engineers are just like that. Application programmers don’t know what’s happening in their class libraries. Class library writers don’t know what’s happening in the operating system. Systems programmers don’t know what’s happening in the hardware. So you have all these layers of software that were created by people who don’t quite know how the other layers behave. It’s kind of a miracle that software ever works at all.

trap_5.JPG

Let’s look at a classic problem. We have a database with a bunch of stuff. It’s very nicely in 3rd normal form.

In the application layer, we want to handle rather different kinds of data, we have the Rich Domain Model, lots of OO classes, objects, subclasses, methods, properties etc.

Many different frameworks have been invented that perform object-relational mapping between the database and the object-oriented classes. For example, here in Webmedia we use Nhibernate and other similar technologies. So you can do things like “give me all the orders of this customer” by writing “foreach Order in Customer.Orders”. The framework will perform the query for you, and life is good, right?

In reality, things are never simple. The generated queries are often more complex and data-heavy than we absolutely need. Also, it becomes super easy to introduce a bunch of extra queries and create humongous loads on the database.

trap_6.JPG

Let’s look at a case study. This is the default homepage of SharePoint Portal 2003. There’s also SharePoint Portal 2007, which looks a little fancier, but this was the project where I personally worked on performance, that’s why it’s included.
Everything you see here is dynamic, the vertical navigation bars, actions on the left, stuff in the lists etc., people can add and edit the elements in all of these.

The data in the various lists, navigation structure etc is all stored in a SQL database.

trap_7.JPG

This diagram is from more recent times, showing the architecture of MOSS 2007

The main point I want to illustrate here is that there’s the base product, Windows SharePoint Services, and lots of other product teams build their stuff on top of it, essentially doing custom SharePoint development, just like many independent SharePoint solution builders all over the world.

trap_8.JPG

-SharePoint can be thought of as a special kind of object-relation mapper.

It stores everything in a database

Also exposes an object model that lets people query and manipulate different kinds of data (sites, lists, web parts, documents). The object model generates SQL calls, which perform the actual operations.

In order to perform any sort of interesting operation, say copy some documents from one list to another, people often have to call a bunch of small, simple APIs, but all of them tend to generate one sort of query or another

Throughout times, I’ve had to diagnose and profile various SharePoint installations, and there’s a common theme: The developer says, hey, everything works OK on my machine, and all I have is these simple operations, how can they be slow?

Under stress, application behaves erratically, oftentimes pages load very slowly

When looking at SQL, it’s common to see very high CPU/memory usage, and some individual queries look super slow in SQL profiler, but it’s inconsistent. Another thing that we see is tons and tons of queries bombarding SQL server many times per second. What really happens is that when SQL server gets a bunch of requests, it cannot service them all at once, relevant data will be locked more often, and other queries have to wait etc.

This situation is what I call the “Estonian Customs” (“Eesti Toll”) application model.

trap_9.JPG

- Let me tell you a story about Estonian Customs

- As you might know, I recently moved from the United States to Estonia, and had to bring all my household stuff to the country. And I had to take some papers to Eesti Toll in order to prove that I had been living abroad and was now moving to Estonia and all this stuff is my stuff.

I’m using a moving company, and had a guy from the moving company to advise me on what paperwork to bring with me. He has been doing it for 20 years, and he has no idea of what kind of papers might be asked at any time.

So we go in with a big stack of all kinds of documents, the official goes through it, and then asks: but why don’t you have a paper that shows that your car was insured in the US? Um… Because I had no idea it was required? So I call my US insurance company and ask for the appropriate paper to be faxed over and send it to the customs. But then they ask for another paper. And a few days later they ask for another paper, which causes me to context switch all the time and stresses out myself and the whole system.

Now software applications that just keep querying for data are just like that as well. Whenever a new feature or a new step in some algorithm is added, we add some code that calls an API method, which usually translates into a query.

This results in a lot of chattiness, every web page load generates tens of queries against SQL, which can add up to a lot of stress in multiuser scenarios.

Also, it usually results in a lot of redundancy, as multiple API calls can often return overlapping data, or even exactly the same data.

Overall, we end up with a death by a thousand cuts – no single query is too bad, but at some point we will add the straw that breaks the camel’s back

Now sometimes this approach is OK. If we are simply prototyping, or we know that this particular piece of functionality will never ever have a high load on it, it will be fine. However, it’s also highly dangerous because as soon as someone changes the conditions by adding more users or lifting this functionality to a different area, things will fall apart very quickly.

trap_10.JPG

-Now let’s come back to our SharePoint story – what did the SharePoint org decide to do?

Realizing the query issue, reducing the number of queries became sort of a holy grail

Every query was examined, and we looked into ways of eliminating them.

There are three basic approaches one can take here:

you can see if multiple queries can be combined into one, especially if the data is similar or overlapping

If you have multiple user interface components that consume the same data (for example, multiple web parts), they can issue a joint query, and consume data from the resulting dataset

And the simplest: cache as much data as you can. If the data that you are reading doesn’t actually change more than once a day or even once per hour, chances are that we can use a simple cache for it. Remember: if you ever need to optimize a query, the first question to ask is: do we need this query at all? Eliminating the query is the perfect optimization :)

Now obviously you need to think about the different invalidation algorithms etc – does your cache expire after a certain time, is it explicitly invalidated when data changes etc.

In the end, we had a sort of query police who had the right to ask difficult questions from everyone that introduced new database hits.

As an end result, SharePoint Portal Server 2003 had only 2 queries to render its homepage (this is the web page I was showing before). One for reading web part and list information (as this is something that can change in real time and thus cannot be cached – but it was all combined into one query), and one for checking if anything had changed in the navigation structure of the portal (if something had changed, the data would be reloaded, but in 99% of the cases it was just a very simple and cheap query).

In comparison, I have had to consult and troubleshoot many custom SharePoint installations where people have 20-30-40 queries to render a single page, and then they complain that SharePoint doesn’t scale.

Now the caveat here is that this can lead to the Doctor’s Office appliation model

trap_11.JPG

-Whenever I used to go to a doctor in the United States, the procedure usually involved a lot of waiting.

-First, I have to wait in the registration line, they take my data

-then, I have to wait in the waiting room, together with a bunch of other people. Sometimes they have chairs for everybody, sometimes they do not (memory pressure!)

-Then somebody asks me to come in and sit down somewhere, and I wait again

-Then a nurse comes and takes my blood pressure, after which I wait again

Then I finally get to see a doctor

The symptoms here are:

The place is full of people, they are being shunted from one stop to another

At every stage, someone performs one little procedure with them

In software, the symptom is that we have built tons of little caches everywhere, which behave like the lines in a doctor’s office

In case of SharePoint Portal, we cached so much data that it created huge memory usage, which obviously wasn’t good

Data ise copied around from one place in memory to another a lot

Now this is much better than dealing with Eesti Toll, but not quite perfect

But in most cases, this will actually be fine, as long as you’re sensible about what kind of data you are caching

Also, due to the nature of software layering (and remember that our themes is “trap of OOP” – Object-Oriented programming makes it very tempting to create lots of layers), you can end up doing caching in all those different layers, and then you wonder what your process is doing with all these hundreds of megabytes of memory.

trap_12.JPG

-Some of the approaches we took in the SharePoint applications to combat this:
-Cut out data transformations and data staging
-Created very highly optimized data paths for common operations. For example, everything is treated as a list in SharePoint, so built-in list rendering was made as fast as possible
-Essentially, we ended up translating the data directly from SQL to HTML, bypassing all of the object model layers.Obviously, there were downsides:
-Many of these codepaths became super complicated – they were efficient, but difficult to understand and maintain
-also, this approach does not work for custom development. If you are writing your own code on top of SharePoint, you are on your own, and have to do your own micro-optimizations.-But this is what I call the Hansabank application model trap_13.JPG

I recently had a very good experience doing my personal business in Hansabank.
Having just moved back to Estonia, I had to arrange a bunch of stuff, from my Teine Pensionisammas to getting new ATM cards.
The teller had all the relevant information about me, she was competent and technologically empowered to perform all the different procedures.

 
 
 

 

In software, this is the equivalent of processing all the relevant data in one place
There’s minimal data transfer between components, and data is not just copied from one place to another all the time

Obvious downside: this can get very complex and difficult to maintain, so save this approach for performance-critical areas

trap_141.JPG

Try to think what stages and transformations your data has to go through
You have to pick your application model at the start of the project, as it’s extremely difficult to change afterwards. For example, I’ve seen projects that have been finished with the Eesti Toll model. They get deployed, and obviously the performance will be bad. And then they bring me in and ask for a quick solution how to fix the performance, and I have to tell them that guys, you actually have to rewrite tons of stuff about how you are handling your data.
-Remember also that 90% of performance problems are designed in, not coded in. People sometimes think that Oh, I will write this code, and if the performance is bad, I will optimize my code, and fix it – does not work this way!
Never assume any performance characteristics about any technology, any code that you have written, or any code that anybody else in your team has written. If you haven’t measured its performance, chances are it will be bad. So profile your code, see what is taking up the CPU, what is taking up the memory – knowledge is power.
Also, things usually get worse on their own. You can have a pretty well performing piece of code, but once a bunch of people have added bug fixes and extra features to it, it will usually get a lot slower because they are not thinking about it in a holistic manner. So profile early, and profile often.
And remember to think about all aspects of performance, CPU, memory, I/o, network. Your model choice can shift the bottleneck from one place to another, so you want to know where to invest the effort.

trap_15.JPG

Finally, how to improve your understanding:
Investigate the components you are working with, read their source code if possible
If you don’t have the source, profile the components, examine their behavior
Do NOT become the engineer who built a skyscraper out of materials he did not understand (remember the picture on an earlier slide!)

trap_16.JPG

5 responses so far

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.

6 responses so far

May 14 2008

Programmeerijad ja rähnid

woodpecker.jpg building_collapse.jpg

Kui ehitajad ehitaksid maju samamoodi nagu programeerijad kirjutavad programme, siis esimene rähn hävitaks tsivilisatsiooni. – Murphy seaduste kogust

Leidsin riiulist mingi ehitusinseneridele mõeldud tehnilise taskuraamatu (pole aimugi, kuidas see sinna sai). Muuhulgas on seal palju tabeleid mitmesuguste materjalide omaduste kohta: tellised, teras, vineer, tihedus, kõvadus, tugevus. Arusaadav, et iga korralik insener peab omama ülevaadet, milliste materjalidega ta töötab, mis on nende tugevuspiirid ja muud tehnilised omadused. Seda enam on hämmastav, kui vähesed programmeerijad teavad, millest nad tegelikult oma programme kokku panevad. Rakendusprogrammeerija ei tea, mis toimub klassiteekide sees, mida ta kasutab. Teekide kirjutaja ei tea, mis toimub operatsioonisüsteemis. Süsteemprogrammeerija ei tea, mis toimub riistvaras. Kõige selle juures on imekspandav, et tarkvara üldse vahel töötab ja midagi mõistlikku teeb.

Kiire test: Kui sa oled C# programmeerija, siis kas sa tead, kui suur on mscorlib.dll? Kasutad XMLi? Kui suur on System.Xml.dll? (Java, C++ jne spetsialistid võivad mõelda oma põhiliste klassiteekide ja runtime’ide peale). Ei tea? Tegemist on umbes samasuguse probleemiga, kui ehitaja ei tea, kui palju kaalub tellis, sest iga kord kui keegi vastava rakenduse käima paneb, mõjutab laetud teekide hulk rakenduse mälutarvet ja sellega otseselt programmi jõudlust. Analoogiliselt, kui sa kasutad näiteks mingit stringitöötlusteeki, on hea teada, mis on nende operatsioonide tegelik ajaline keerukus, kui pilditöötlemisteeki, siis millised on selle sisemised andmestruktuurid, et saaks hinnata mäluvajadust jne.

Objekt-orienteeritud programmeerimine on väga hea asi, aga ebasoovitava kõrvalefektina on see veelgi süvendanud olukorda, kus inimesed:

  1. ei tea, mis klassiteegi sees toimub, sest kõik on ilusasti ära peidetud, pakendatud ja kapseldatud
  2. ei oska ilma spetsiaalse teegita ise üldse ühtki probleemi lahendada

Kord saadeti mind asja uurima suure, tähtsa ja rikka kliendi juurde, kes kurtis, et tema veebiserver ei skaleeru. Lasin nende avalehe profileerijast läbi ja leidsin tuhandeid String.Concat väljakutseid. Selgus, et nad panevad suure hulga oma HTMList lihtsalt stringiliitmise teel kokku, mis on C# kasutades muidugi rumal. Tegemist on tüüpilise näitega, kus programmeerija ei tea, kuidas tema vahendid tegelikult töötavad.

Osaks minu tööülesannetest on aeg-ajalt potentsiaalsete töösoovijatega vestlemine (veel enne tegelikku intervjuud/katseid). Küsin sealhulgas nende käest lihtsaid tehnilisi küsimusi, et leida, kas on üldse mõtet edasi vestelda või on tegu mõlemapoolse ajaraiskamisega. Tuleb siis selline tegelane, küsin tema käest, et kui tal on programmis näiteks massiiv punaseid palle ja rohelisi palle, kuidas oleks kõige parem neid sorteerida, nii et punased pallid satuvad algusesse ja rohelised lõppu. Tema selle peale, et teeks ArrayListi ja kasutaks siis selle Sort meetodit. Kas ta teab, kuidas Sort meetod töötab? Ei. Aga kui ta peaks ise sellise meetodi kirjutama? Vaikus. Bzzzzzt, järgmine, palun. Esiteks pole klassiteekides leiduvad üldotstarbelised sorteerimisalgoritmid antud ülesande puhul sugugi optimaalsed, teiseks pole mul midagi peale hakata inimesega, kes arvutiteaduse põhikontseptsioonidega hätta jääb (nagu ehitusinsener, kes füüsikaeksamil põrub). Aja- ning mäluvajaduse keerukusest ei jõudnud muidugi rääkima hakatagi.

 matrix.jpg

Uuri allikteksti, sula ühte koodiga – Linus Torvalds

Inimesed küsivad mult vahel nõu programmeerimisõpikute kohta. Häid õpikuid on palju, aga minu meelest on hea programmeerija parimaks lektüüriks hea kood :) Mitmesuguste andekate inimestega koos töötamise järel olen oma Microsofti-kogemuse juures rõõmus võimaluse üle igasugust huvitavat koodi lugeda, Windows, Office, .Net Framework, kõigis neis on geniaalseid lahendusi, rääkimata asjade mõistmisest tulenevast rahuldusest ja teadmistest, mis võimaldavad mul oma tööd efektiivsemalt teha (ma ei räägi siin mingitest sala-APIdest, vaid lihtsalt algoritmide tasemel mõistmisest). Väljaspool Microsofti on loomulikult samuti tuhandeid võimalusi uurida, kuidas asjad töötavad, olgu siis Open/Shared Source’i maailmas või mujal, ja suureks vaheks hea programmeerija ning tipp-programmeerija vahel on tihti see, kui palju ta igasuguste vidinate uurimisele on aega kulutanud. Kui alliktekstid pole saadaval, uuri jõudluskarakteristikuid, profileeri klassiteeke jne, et aru saada, kuidas asjad töötavad.

Ja hoidu rähnide eest :)

8 responses so far

May 09 2008

Programmeerija kolm voorust: laiskus, kannatamatus ja edevus

virtue.jpg 

We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.” – Larry Wall

Klassikalised kristlikud voorused on: mõistlikkus, mõõdukus, meelekindlus, õiglus, usk, lootus ja armastus. Samas, nii palju kui ma ka ei püüaks klassikalist vooruslikku elu elada, on vähemalt minu naise arvates mind märgatavalt paremini varustatud laiskuse, kannatamatuse ja edevusega. Kuna aga vähemalt professionaalses elus on viimased kolm mind kõvasti rohkem edasi aidanud kui esimesed seitse, siis tuleb ilmselt olukorrast võtta, mis võtta annab :) Siin ei tule asja muidugi nii mõista, et me neid kolme omadust kogu aeg ja igas situatsioonis peaksime kasutama, küll aga on nad meile suureks abiks oma igapäevase koodi kirjutamisel.

 laziness.jpg

Esimene voorus: laiskus

Tarkvarafirmal Joostes Marss tuleb teha Hulkuvate Kasside Riiklikule Inspektsioonile statistiliste aruannete moodul, toomaks eraldi välja, kui palju erinevate ajaperioodide lõikes koeri ja kasse kaotatakse ja leitakse. Jagatakse siis ära: pooled aruanded Priidule ja pooled Pärtlile. Priit hakkab asjaga kohe hoolega pihta, kirjutab ühe lehekülje keerulist andmebaasikoodi teise järel. Ajaperioodide arvestamisel on teatavasti palju erijuhtumeid, teha päringut näiteks juuni viimasest pühapäevast 5. septembrini pole triviaalne ja Priidu kood koosneb lõpuks suurest hulgast if-then-else klauslitest, igaühe sees omakorda keeruline arvutus. Priit muudkui kirjutab, möödub päev ja teine, projektijuht Joosep küsib, kuidas läheb, Priit näitab suurt hulka koodi ja seletab pikalt, kui keerulise ülesandega ikka tegemist on, ja kuidas tal veel kolm korda nii palju koodi tuleb kirjutada, enne kui asi valmis. Kuna koodihulgast on ilmselgelt näha, et asjad edenevad, siis Joosep rahuneb natuke.

Pärtel ei tee samal ajal pealtnäha suurt midagi, nokitseb asja kallal, sirgeldab ühtteist paberile, lõpuks teeb siiski kompilaatori ka lahti. Joosep on mures ja küsib Pärtli käest, et näe, Priidul juba nii palju koodi valmis, mida sina teed? Pärtel vastu, et pole hullu, küll saab. Ja teatab õhtul, et temal on kõik valmis. Joosep ei usu, sest koodi pole pealtnäha nagu ollagi, aga näeb siis, et tõepoolest, kõik töötab, kiiresti ja korralikult. Pärtel ei viitsinud palju koodi kirjutada ja tekitas lihtsalt denormaliseeritud vahetabeli, kuhu enne aruannete koostamist andmed kopeeritakse, ja mille pealt päringute tegemine on selge, lihtne ja lühike.

Tegelikult on laiskus arvutitega lahutamatult seotud. Kuna arvuti on loodud selleks, et inimese eest töö ära teha, poleks virk inimene kunagi sellise leiutise peale tulnud. Hea programmeerija püüab teha kõik, et omaenda vaeva võimalikult vähendada. Las arvuti töötab, tema on rauast. Ma ise pean konkreetset kooditoksimist küllaltki tüütuks ega viitsi sellega palju vaeva näha, selle asemel püüan nuputada, kuidas võimalikult vähese arvu ridadega hakkama saada või üleüldse mõnd olemasolevat komponenti kohandada. Selline nuputamine on palju huvitavam ja inimesele kohasem ning rahuldust pakkuvam tegevus, rääkimata sellest, et tähtajad saavad kiiremini valmis ja ka tulemus on enamasti kvaliteetsem (vigade hulk kipub kasvama koos koodi hulgaga).

Laiskus soodustab veel mitmeid häid harjumusi nagu

  • korduvate tegevuste jaoks spetsiaalsete utiliitide kirjutamine
  • koodi hoolikam testimine ja debugimine (sest tarkvara põhiteoreemi järgi kulub meil testimata ja debugimata koodi peale rohkem aega)
  • selge ja lihtsa koodi kirjutamine, selle kommenteerimine ja dokumenteerimine (et hoida kokku aega, mis muidu kuluks teiste inimeste aitamisele ja rumalatele küsimustele vastamisele)
  • taaskasutatavusele optimiseerimine, et me ei peaks sama koodi mitu korda kirjutama
  • jne

 impatience.jpg

Teine voorus: kannatamatus

Ma arvan, et inimeste kannatamatus on asjaolu, mis on otseselt põhjustanud Moore’i seaduse ja palju muud lahedat.

Kannatamatusega saab mõõta näiteks selliseid asju:

  • Mitu korda ma pean sama koodi uuesti kirjutama, enne kui ma selle jaoks uuestikasutatava mooduli teen?
  • Mitu korda ma viitsin oma programmi testides samu liigutusi teha kuni ma sagedasemate operatsioonide jaoks lühema ja intuitiivsema meetodi välja mõtlen?
  • Kui kaua ma jaksan mingi olemasoleva tarkvara järel oodata enne kui ma parema ja kiirema lahenduse välja mõtlen ja sellega palju raha teenin?
  • Kui kaua ma mõne inimese või teenuse järel ootan, enne kui ma asja ise kiiremini ja efektiivsemalt ära teen või veel parem, automaatse lahenduse leiutan?
  • Kas ma kannatan olukorda, kus inimesed minu tiimis kirjutavad tuhat rida koodi, kui hakkama saaks ka viiesajaga? Või korraldan ma neile koolituse, et nad parematest metoodikatest aimu saaksid?

 pimp.jpg

Kolmas voorus: edevus

Kui Pärtel oli oma aruanded ennetähtaegselt valmis saanud, ei jäänud ta siiski rahule sellega, et juba enne olemas olnud, valmis koodis käisid paljud aruanded liiga aeglaselt. Päringud olid kirjutatud täpselt kliendi tellimuse kohaselt, imiteerides protsesse, mida klient Kustavi alluvuses töötavad kontorirotid enne kas siis Exceli või ka paberi ja pliiatsi abil sooritasid. Selle tõttu kopeeriti ka andmeid liigselt ühest kohast teise, päringud käisid üle seitsmeteistkümne erineva tabeli korraga jne. Pärtel uuris veel natuke asja, kombineeris mõned tabelid kokku, lisas paar indeksit, kirjutas mõne stored procedure’id lihtsalt päringusse lahti jne. Järgmisel päeval ehmus Joosep, et kas kõik testandmed on ära kustutatud või milles asi, et aruanded järsku mitukümmend korda kiiremini toimivad. Pärtlile ei läinudki eriti korda, kas kliendi jaoks on oluline vahe, kas aruanne käib kümme sekundit või kümnendik sekundit, kuid tal oli võimalus näidata, kes on ettevõttes alfaprogrammeerija.

Hubris ei tähenda küll päris täpselt edevust, aga mulle meeldib “edevus” tähendusväljana isegi rohkem. Tegemist on jõuga, mis paneb programmeerijat seatud ärilisi eesmärke ja tehnilisi nõudeid ületama, mis sunnib neid kirjutama eriti elegantset koodi, mis vastab headele tavadele ja standarditele, kuid teeb asju siiski efektiivsel ja isikupärasel moel. Tihti ei pane lõppkasutaja selliseid töövõite otseselt tähelegi, aga edevale programmeerijale on tähtis eelkõige kolleegide imetlus. Seetõttu katsub ta kirjutada koodi, mille kohta kellegil midagi norida ei oleks, mis on tarkvara kvaliteedi seisukohalt muidugi väga hea.

Lisaks koodi efektiivsusele avaldub edevus muidugi ka muudes asjaoludes:

  • Kes saab oma töölõigu esimesena valmis?
  • Kelle koodis on kõige vähem vigu?
  • Kelle tehtud kasutajaliides on kõige uhkem?

Kui edevat programmeerijat selliste asjade eest piisavalt tunnustada, kasvab produktiivsus mühinal, piitsa ja präänikut ei lähe üldse vajagi.

One response so far