webForumDet fria alternativet

Något bra sätt att undvika stora loppar?

.NET

9 svar · 613 visningar · startad av Lukaspojken

Medlem sedan maj 20011 312 inlägg
Frågan#1

Jag hittade precis ett riktigt svårupptäckt fel som gjorde att minnet på webservern tog slut. Det var ett fel som uppstod ibland så det gick inte riktigt att återskapa felet och det var som att leta efter en nål i en höstack. Äntligen hittade jag det :)

Men hur gör man för att undvika att loopar blir för stora på ett bra sätt?

Om man tex har en loop som ser ut så här:

For X = 0 To Total
...
Next

Så här skulle man kunna göra för att underlätta felsökning och undvika stora loopar:

For X = 0 To Total
	...
	If X > 10000 Then
		Throw New Exception("Loop exception....")
	End if
Next

Skulle ni gjort så som ovan eller skulle ni försökt göra det på ett annat sätt? Sen undrar jag i vilka fall man bör lägga in felhantering i större loopar? Själv har jag aldrig sett någon felhantering på detta sätt i loopar men det kanske inte är så dumt? Det enda jag sett några gånger under de år jag jobbat som programmerare är tex en if-sats som kontrollerar räknaren och därefter gör en exit for eller liknande för att undvika evighetsloppar eller större loopar.

Medlem sedan dec. 19996 522 inlägg
#2

Aldrig felhantering innuti loopar i form av exception handling, ifsats kan man använda ibland. Mitt enda tips är välskrivna unit-tests, och kanske titta mer på Performance Monitoring (http://msdn2.microsoft.com/en-us/library/ms972959.aspx#monitor_perf_topic7).

Medlem sedan maj 20011 312 inlägg
#3

Varför rekommenderar du att man inte har felhantering i looparna? Skulle du lägga felhantering utanför loopen eller skulle du skipa det helt?

Jag har inte så stor erfarenhter av tex test-driven-utveckling men jag ser fördelar med det. Jag har dock svårt att se att man har den tillräckliga tid som krävs för att skriva vattentäta unit-tester. Jag skulle nog säga att ett bra komplement till unit-testerna skulle vara någon form av felhantering i loopar.

Performance monitoring är bra men den ger mer en övergripande bild över läget. Det är svårt att hitta ett specifikt fel i koden med hjälp av det.

Medlem sedan dec. 19996 522 inlägg
#4

Om du är orolig för loopar när datamängden kan vara väldigt stor får du sätta upp test som simulerar det, har du problem med koden kan du använda profilerverktyg såsom ants profiler för att se vart koden tar lång tid att exekvera. Skulle lagt felhanteringen utanför loopen

Medlem sedan feb. 2005280 inlägg
#5
while(x < _SafetyLimit && x < Total)
{
    ...
    x++;
}

Skulle jag nog gjort (typ)

Medlem sedan aug. 20068 090 inlägg
#6

Kan ingen moderator ändra rubriken. Jag såg fram emot att läsa en splatterstory om hur en medlem blivit attackerad av gigantiska loppor.

Medlem sedan maj 200732 inlägg
#7

Byt till Rails där test driven development är en fest!

Nej, men ärligt talat... Iterationer kan kräva mycket av servern. Beroende på vad du vill göra/gör kanske det kan vara idé att t.ex. låta databasen sortera och välja ut data. (Om det nu är data från en databas du arbetar med.) Db-servrar är ju skapade och optimerade för den typen av arbete.

Eftersom jag inte är en hejare på ASP så får du lite pseudo-kod ! :)

FEL:

hämta alla objekt
  för varje objekt
    om objektet(färg) == gul
    visa objektet
  slut

RÄTT

hämta alla objekt(färg == gul)
  för varje objekt
    visa objektet
  slut
Medlem sedan maj 20011 312 inlägg
#8

Detta förslag fick jag på ett annat forum och det är nog det vettigaste. På detta sätt slipper man gå in i en stor loop i fall det skulle vara fel. Jag får dock uppfattningen att många inte är för detta :) Inga ja-sägare?

If Total > 10000 Then Throw New Exception("Loop exception....")

For X = 0 To Total
...
Next
Medlem sedan juni 20008 205 inlägg
#9

Lukaspojken skrev:

Men hur gör man för att undvika att loopar blir för stora på ett bra sätt?

Jag har svårt att se det här som ett generellt problem.

I de fall där det beror på att man själv gjort nåt fel (typ skrivit en SQL-fråga som returnerar tusenfalt fler rader än man tänkt sig) är det bara en bugg, och det enda sättet man kan stampa ut buggar på är kodgranskning och tester. Att slänga in lite Debug.Assert, ArgumentExceptions och liknande i koden är förstås aldrig fel. Men gör det på rätt ställe, du bränner bara en massa processorcykler på att göra kollen inuti loopen. Effektivare:

If Total > 10000 Then
	Throw New Exception("Loop exception....")
End if
For X = 0 To Total
	...
Next

red. Så hinner du förstås skriva samma sak själv innan jag postar. Tacksamt :OO ;)

Nåväl, vidare i sak:

Sen finns de fall där det beror på användardata som kommer in, typ "antal poster på sidan". I de fallen är det bara helt vanlig indatavalidering som gäller, kanske kombinerat med en tyst korrigering, som i freguz exempel.

Men som sagt, jag har svårt att se det här som ett generellt problem :) Visst sätter mina program att loopa amok med jämna mellanrum, men det är inte konstigare än att mina if-satser får fel i sina villkor etc. Det bästa sättet att motverka det på tycker jag dock är spårutskrifter kombinerat med en debugger så man ser vad som händer.

Medlem sedan jan. 200475 inlägg
#10

Jag har svårt att se att stora loopar (ej evighetsloopar) skulle vara ett direkt problem med minneshanteringen. Jag ser inte heller själva loopkoden som en nödvändig bugg eftersom felet i så fall ligger i datamängden som inkommer i koden innan loopen.
Så länge man ej skrivit ett extremt resurskrävande program där man allokerar minne inuti loopen så är stora loopar mer ett prestandaproblem än minnesproblem. Man bör nämligen aldrig t.ex. deklarera nya variabler inuti en loop såvida det inte är absolut nödvändigt utan deklarera dessa innan loopen och gärna återanvända variablerna i varje loop iteration.
Nu har jag visserligen aldrig grävt ner mig ordentligt i minneshanteringen i .net och C# speciellt utan arbetar mest i C++ och dess minneshantering där man måste vara observant på minnesanvändning för att inte introducera minnesläckor.

261 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
125 ms — deklarationer (db)
0 ms — hämta statistik (cache)
130 ms — hämta tråd, inlägg och bilagor (db)
127 ms — ändringar (db)