webForumDet fria alternativet

Prestanda / Struktur

9 svar · 496 visningar · startad av Brimba

BrimbaMedlem sedan dec. 19995 875 inlägg
#1

Hej!

När man jobbar med ett stort projekt där man har flera klasser som länkas in i varandra. Exempelvis man har en klass som är transport. I transport har man sedan

transport.salesman(x).name
transport.salesman(x).country.name
transport.vehicleType.truck.driver.name
transport.vehicleType.truck.regnr.value
transport.vehicleType.truck.space.value
transport.deliverdate

Det finns alltså massor av kopplingar fram och tillbaka. Klassen country används på massa andra ställen men i detta fallet laddas den även när man laddar in transport eftersom man kan vilja komma åt den datan.

Strukturen här blir ju optimal men prestandan blir lidande.

Jag skulle vilja ha en diskussion om hur ni löser såna här fall?

erkaMedlem sedan dec. 19996 522 inlägg
#2

Jag brukar göra ett UML-diagram och sedan implementera exakt efter diagrammet.

GladhMedlem sedan maj 20012 812 inlägg
#3

caching caching caching...

I den funktion som laddar in din Countryclass, så har du en kontroll mot en cache om country redan finns i cachen så hämtar du den därifrån, annars hämtar du från databasen och lägger i en cache.

En O/R Mapper hade löst det enkelt med en caching funktion.

- M

fredrikMedlem sedan dec. 19991 072 inlägg
#4

caching caching caching...

Menar du då att cacha mha av typ "Cache"-objektet som isf får skickas med vid varje förfrågning mot BL?

Om BL även ska fungera från tex. en Winform, vilket cache-objekt kan man i så fall använda?

En O/R Mapper hade löst det enkelt med en caching funktion.

På vilket sätt skulle det ha underlättat? Du menar (som tidigare diskuterat) att varje klass skulle ha sin egen logik och då bara laddas i samband med det eller då vissa parametrar skickades in?

Intressant diskussion...! :)

GladhMedlem sedan maj 20012 812 inlägg
#5

Menar du då att cacha mha av typ "Cache"-objektet som isf får skickas med vid varje förfrågning mot BL?

Om BL även ska fungera från tex. en Winform, vilket cache-objekt kan man i så fall använda?

Cache objektet som finns i ASP.NET skall du inte använda, och precis som du säger så fungerar det inte speciellt i en WinForm lösning.

MS har gjort ett Cache Application Block som man kan använda. Eller så skriver man ett eget, det är inte speciellt svårt (tror jag har beskrivit det tidigare här i forumet, sök sök sök).

[hittade länken: http://www.webforum.nu/showthread.php?s=&forumid=191&threadid=93714&highlight=cache]

I en O/R Mapper så hämtar och skapar O/R mappern datan till/från databasen. Alltså all databas access sker genom O/R Mappern, typ så här.

BussinessLager -> O/R Mapper -> DAL -> Databas.
Databas -> DAL (som skickar ett DataTable) -> O/R Mappern (som skapar och skickar ett objekt) -> BussinesLagret

Om man då vill ha en cache med så går man så här.

BussinessLager -> O/R Mapper -> Cache.
Cache (skickar objektet) -> O/R Mappern (som skickar vidare objektet) -> Bussineslagret.

Så om det object som du efterfrågar redan finns i cachen så hämtas det därifrån, annars så fortsätter O/R Mappern till DAL:et och hämtar ut data från databasen, skapar objectet och lägger in det i cachen.

Med den lösningen så slipper du fråga databasen igen, samt att du slipper skapa objektet igen eftersom det redan finns i cachen. Det är en riktigt prestandahöjare att använda sig av cachen, den har ju dock en nackdel, den bokstavligen ÄTER Minne.

Har du 1 object som tar upp 1 MB i minne, så tar 1000 av dessa objekt upp 1 GB i ramminne!!!! Så det vill till att man använder WeakReferens när man skapar sin cache.

- M

PDahlenMedlem sedan apr. 2004778 inlägg
#6

Om man gör en uppdatering i databasen, cachar O/R-mappern om då så att man inte hämtar gammal data från cachen när det finns ny data i databasen nästa gång?

GladhMedlem sedan maj 20012 812 inlägg
#7

Om man gör en uppdatering i databasen, cachar O/R-mappern om då så att man inte hämtar gammal data från cachen när det finns ny data i databasen nästa gång?

Antingen så cachar du om objektet, eller så slänger du det som finns i cachen, och väntar på att någon vill komma åt objektet nästa gång. Oftas är man ju färdig med objektet om man spara det. Men det gör man som man vill.

Sedan har man problemet med att flera applikationer använder samma data, vad händer om App1 laddar in ett objekt i cachen, sedan så hämtar App2 samma objekt från databasen och ändrar, sedan spara man ner det till databasen, om App1 nu återigen vill åt objektet så ligger det i cachen och hämtas därifrån, det är dock inte samma objekt som finns i databasen. Alltså borde man har en gemensam cache server för alla sina applicationer. Så ut med O/R Mappern och cachen på en applicationsserver och kör med .NET Remoting för att hämta data från O/R Mappern.

Det är inte säkert att man skall cacha alla sina objekt heller, objekt som man använder sällan, kanske 2-3 gånger per session, kan man fundera på om RAM minnet är mer värt än vad prestandan är. Ju mindre minne man har kvar desto oftare kickar GC igång och vill städa upp, och den är ju inte direkt prestanda vänligt, specillet inte ur skalbarhet, då den kräver att ALLA trådar i applikationen lägger ner sitt arbete så GC kan jobba ostört.

Finns mycket att välja tänka på, viktigast är dock att använda sig av WeakReferensce om man bygger sin egen cache, så GC kan plocka bort objekten därifrån om minnet börjar ta slut. Använder man inte WeakReference så kan man faktiskt binda upp allt minne genom att fylla på en massa objekt i cachen. GC kan då inte ta bort dessa objekt, eftersom det finns referenser till dessa objekt från ditt cache objekt.

- magnus

PDahlenMedlem sedan apr. 2004778 inlägg
#8

Ok, det är som jag gjort tidigare då, utan O/Rmapper. Jag brukar tömma cachen om jag gör en uppdatering i databasen.
Problemet med att två användare kan få olika data kan du få även om du inte cachar.
Användare 1 hämtar data i databasen till sitt webbformulär. Medans 1 gör ändringar så hämtar användare 2 samma data i webbformuläret. 1 uppdaterar databasen medans 2 fortfarande har gammal data. Problemet uppstår dock bara när flera använder systemet samtidigt. Med cache som man "glömmer" uppdatera ligger problemet kvar tills någon uppdaterar.

Som sagt, mycket att tänka på. Är mitt uppe i att designa en webbapplikation och man kommer på nya saker att ordna med i varje iteration.

GladhMedlem sedan maj 20012 812 inlägg
#9

Medans 1 gör ändringar så hämtar användare 2 samma data i webbformuläret

Det kan du lösa med Transactioner, så du låser tabellen så ingen kan läsa från den medans någon skriver till den.

I en cache har du inte den möjligheten, eftersom du inte vet när någon skriver, om man nu inte har löser det med event från databasen....

Det är roligast att design och skissa fram lösningar, de har en förmåga att växa "lite" utanför vad som är nödvändigt bara för att det är kul att implementera nya saker :)

- M

PDahlenMedlem sedan apr. 2004778 inlägg
#10

Jo, men det är ju när du ska hämta och skriva i samma transaktion.
Om du öppnar en webbsida så hämtar du data och fyller ditt formulär. Sedan sitter du där och ändrar i formuläret och submittar till databasen när du är klar.
Om du ska låsa så måste du alltså låsa tabellen när du hämtar, sedan kan ingen hämta data i tabellen medans du sitter och skriver i formuläret. Om du sedan struntar i att submitta dina ändringar utan bara stänger fönstret så skulle tabellen förbli låst.

Rent teoretiskt alltså.

Ja, det är väldigt kul att designa och skissa. Jag har alltid varit så att jag designar, bygger, går tillbaka, ändrar och bygger ut, osv. Med andra ord Iterationer redan innan jag läst in mig på UML och UP. ;)

132 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
128 ms — hämta tråd, inlägg och bilagor (db)