Alternativ två är bättre ur prestandasynpunkt. Däremot är ju prestandavinsten ganska marginell, och alternativ ett kan kanske vara lättare att läsa - beroende på hur variablerna är döpta :)
Edit, när det handlar om adressering av index i arrayer så är prestandavinsten 0 med alternativ ett har jag sett efter ett antal test. Det bör ta lika lång tid för båda alternativen. Då profileras koden helt annorlunda, vid arbete med objekt (och instantiering av dem) däremot så behåller jag nog min ståndpunkt sen tidigare. ;)
Min andra fråga är om ovanstående kod är sämre ur prestandasynpunkt än nedanstående kod?
Nu kommer jag vara riktigt elakt mot dig, men allvarligt talat funderar du ens i sådan banor när du skriver kod?
Det måste finnas betydligt viktigare ställen att lägga sin kraft på när det gäller prestanda frågor. Det finns vissa saker när det gäller prestanda som man kan adressera innan man börjar utforma sin lösning, men i de flesta fallen så är det onödigt att lägga tid på prestandan innan du har upptäckt problemet, och just det här exemplet är verkligen ett sådan fall, att du ens lägger tid på att fundera över det är för mig obegripligt, jag hade resonerat så här.
Skall X kunna accessas utanför for-loopen. JA = lägg deklarering utanför, NEJ = Lägg deklareringen innanför. Om jag sedan hade upptäckt något prestanda problem så hade jag funderat på hur man skall kunna lösa det.
Det finns dock tillfällen där man skall fundera på sina lösningar med hänsyn till prestandan innan man börjar implementera dem, och ett exempel, är lösningar när man använder exceptions för att beskriva fel som du som utvecklare kan förvänta dig. Exceptions är extremt smidiga i vissa av dessa sammanhang och jag använder de flittigt eftersom de helt abrupt avbryter exekveringen och du kan själv välja var du vill att hanteringen av felet skall ske. Att bygga något liknande med egna metoder där man skall skicka tillbaka olika meddelande är betydligt mer komplicerat.
Men det man skall tänka på här är att Exceptions är resurskrävande och att använda dessa fel i exempelvis en högbelastad website, kan slå ihjälp prestandan rätt snabbt, men i en vanlig windows applikation där vi pratar enanvändar scenario, så är prestandahiten helt försumbar jämfört med felxibiliteten man får av exceptions.
Skall X kunna accessas utanför for-loopen. JA = lägg deklarering utanför, NEJ = Lägg deklareringen innanför. Om jag sedan hade upptäckt något prestanda problem så hade jag funderat på hur man skall kunna lösa det.
Men det där har faktiskt också lite med prestanda att göra. ;) Men jag håller med till fullo.
Om objektet inte ska användas utanför for-loopen så bör man deklarera det innanför loop-klamrarna. När for-loopen sen är klar, så vet GC om att objektet inte kommer att användas något mer - och minne frigörs. Görs deklarationen utanför kommer objektet att ta upp plats i minnet så länge förälder-blocket körs, även om det inte används någon annanstans än just i loopen.
Dock är ju JIT-kompilatorn bra på att profilera kod - så det här är faktiskt ganska triviala saker att bry sig om när man tänker ur prestandasynpunkt. Då är det bättre att göra koden förståelig och lättläst.
Jag tycker också att deklareringen skall göras innanför om det inte finns någon direkt anledning till att den skall ligga utanför.
Gladh skrev:
Men det man skall tänka på här är att Exceptions är resurskrävande och att använda dessa fel i exempelvis en högbelastad website, kan slå ihjälp prestandan rätt snabbt, men i en vanlig windows applikation där vi pratar enanvändar scenario, så är prestandahiten helt försumbar jämfört med felxibiliteten man får av exceptions.
- M
Jag håller inte riktigt med om din sista poäng, jag tycker att man kan lösa det mesta på andra sätt än exceptions även om det ibland kan vara enkelt att använda Exception's (finns förstås undantag som med allting, men här tycker jag att dom är få).
Och helt försumbar behöver den inte vara om det handlar om listor där saker sker repeterade gånger.
Det är det som är så härligt, att man tycker olika och implementerar olika, och därmed så lär man sig nya saker av varandra hela tiden, fast egentligen, vi vet ju båda 2 att jag har rätt :birp
Klart att det finns andra sätt att lösa det på och ibland är det ju så enkelt som att skicka tillbaka en boolean om något blev fel eller inte, men det blir ändå en mer komplex kod, eftersom du måste kontrollera detta värde och utifrån värdet exekvera olika koder, och om det är så att du lyckas gräva ner dig i ett antal metodanrop och vill avsluta din exekvering mitt i och komma tillbaka till "toppen" så måste du ju ha ett return värde från varje metod, och från varje ställe som metoden anropas så måste du göra en kontroll om metoden skall fortsätta att exekveras eller avslutas... Helt enkelt mycket mer komplext, än att utnyttja exceptions förmåga att avbryta koden abrupt.
Som Gladh säger, premeture optimazation är ofta onödig, dock ska man tänka på prestanda när vi kodar. Sedan kan kompilatorn analyzera vår kod och själv flytta om variablar utifrån vad som är optimalt och hur dom används, detta betyder inte att vi ska slarva!
När det kommer till exception, byt ut exception mot tester så ofta det går i kod, men ersätt ALLTID status koder med excetpion. Så returnera inte true eller false, eller 0,-1, 1 etc.
-> Alla
Jag är medveten om att det är minimal prestandabättring oavsett vilken metod man väljer. Jag ville bara få en bekräftelse på att det var som jag trodde. Jag lärde mig dock en ny sak i detta inlägg och det var detta med hur GAC:en fungerar. Det var intressant...
-> Gladh
Hehe, jag sitter inte och prestandaförbättrar på den nivån. Det jag skrev i mitt inlägg var att ibland ser man sådan kod och jag ville lära mig mer om hur ramverket fungerar. Detta tror jag du inte motsätter dig :)
Görs deklarationen utanför kommer objektet att ta upp plats i minnet så länge förälder-blocket körs, även om det inte används någon annanstans än just i loopen.
Detta är rätt intresant, Microsoft skrev i en gammal guidlines sa att CLRen kan se om ett objekt används senare eller inte, om den inte används senare i koden så kan den tidigare frigöra objektet. Men vad jag har hört vid senare tid så ska man inte ska lita på att det är så.. ;)
Även om föräldrar-blocket har nått slutet av sitt scope så kommer inte det betyda att objektet försvinner ur minnet, det kommer ligga kvar tills GC kommer köra en Collect, och när detta sker vet vi inte.. samma sak för dom objekt vi skapar innanför for loopen.
OBS! Strängar i .Net hanteras på ett unikt sätt.. Har jag tex:
string name = "Kalle";
string name2 = "Kalle";
Så kommer det bara finnas ett "Kalle" i heapen och name och name2 kommer peka på samma adress. Tänk på att en string är en reference type, men beter sig som en value type, skriver jag:
name = "kalle2";
Då kommer vi få två objekt i heapen, "kalle" och "Kalle2"..
skulle jag srkiva:
string name3 = "Kalle2";
Så kommer name3 peka på "Kalle2" i heapen och inte skapa ett nytt "Kalle2".
Detta är rätt intresant, Microsoft skrev i en gammal guidlines sa att CLRen kan se om ett objekt används senare eller inte, om den inte används senare i koden så kan den tidigare frigöra objektet. Men vad jag har hört vid senare tid så ska man inte ska lita på att det är så.. ;)
Ja, visst kan CLR se om ett objekt kommer att användas eller inte - men med en inneslutande variabel kan man ju garantera att objektet tillåts att tas om hand av GC (när tid finns).
fredrikn skrev:
Även om föräldrar-blocket har nått slutet av sitt scope så kommer inte det betyda att objektet försvinner ur minnet, det kommer ligga kvar tills GC kommer köra en Collect, och när detta sker vet vi inte.. samma sak för dom objekt vi skapar innanför for loopen
Ja, självklart ligger det kvar i minnet tills GC rensar ut - men man tillåter att GC plockar bort minnesreferensen och objektet, istället för att låta CLR avgöra om det ska finnas kvar eller inte.
OBS! Strängar i .Net hanteras på ett unikt sätt.. Har jag tex:
string name = "Kalle";
string name2 = "Kalle";
Så kommer det bara finnas ett "Kalle" i heapen och name och name2 kommer peka på samma adress. Tänk på att en string är en reference type, men beter sig som en value type, skriver jag:
name = "kalle2";
Då kommer vi få två objekt i heapen, "kalle" och "Kalle2"..
skulle jag srkiva:
string name3 = "Kalle2";
Så kommer name3 peka på "Kalle2" i heapen och inte skapa ett nytt "Kalle2".
Hmm, borde det inte vara likadant för alla valueobjekt?