23. maj 2005 - 20:34Der er
12 kommentarer og 2 løsninger
Performance - hvor/hvornår skal fx database instansieres?
Denne tråd vil muligvis føre til en del debat, hvilket jeg hilser meget velkomment. Læs dog venligst det jeg skriver igennem inden I svarer, så vi er enige om hvad vi snakker om :o)
Til en større webapplikation, hvor størstedelen af alle requests medbringer et eller flere databasekald, skal der udarbejdes den mest objekt- OG performance-orienterede datatilgang som muligt.
Applikationen indeholder en klasse (SqlServerManager), der implementerer et interface (IDataManager), som styrer alt data til og fra databasen. Klassen instansieres med en connection string (hentet fra web.config el. lign.) som parameter.
Mit spørgsmål er så: hvor/hvornår skal et objekt af klassen instansieres? For så vidt kan alle brugere sagtens dele den samme instans hvorfor man kunne overveje at gemme den som en application variable. Vil dette fungere fornuftigt performancemæssigt i praksis, eller bør man hellere oprette en ny instans internt i de sider der skal benytte sig af databasen?
Ved den første løsning formoder jeg at forbruget af hukommelse på serveren minimeres, idet der kun vil være én instans af SqlServerManager til hver en tid. Det jeg ikke er klar over, er om dette objekt vil komme til at udgøre en flaskehals for resten af systemet, når alle klienter vel sagtens kommer til at dele den samme SqlConnection?
Min SqlServerManager er forholdsvist "let" - den instansierer sådan set ikke andet en en SqlConnection. Denne connection bliver endvidere kun åbnet når der fortages en handling, hvorefter den lukkes igen.
Hvis jeg vælger at oprette en ny instans af SqlServerManager ved hvert request, bør jeg så åbne forbindelsen og først lukke den igen til sidst? Eller som nu open/close rundt om hver forespørgsel?
Vælger jeg denne løsning vil jeg skulle have fat i min connection string ved (næsten) hvert request, hvorfor jeg kunne forstille mig at det var smart at løfte denne op i en application variable, så der ikke skal læses fra en XML-fil (det bliver nok ikke web.config i dette projekt) hver gang. Korrekt?
at læse gennem ConfigurationSettings.AppSettings er ikke "dyrt" i og med at det bliver cached første gang.
Men jeg vil også give arne ret i, at du sagtens kan få en fin skalerbarhed ved at oprette en ny instans af din SqlServerManager-ved hvert request, og især hvis den ikke har noget nævneværdigt overhead ved oprettelse.
Omkring det med at åbne og lukke forbindelsen hele tiden må jeg nok melde pas. Hvor at man i gode gamle asp-dage, åbnede forbindelsen i toppen af siden, og lukkede den igen i bunden, så er det knap så simpelt mere. Nu kan ens logik jo være splittet op i mange forskellige objecter der hver især har brug for adgang til databasen. En mulighed er dog at gemme din connection i Items-collection'en i HttpContext. På den måde kan alle objecter der er en del af samme Context have adgang til den samme connection, og på den måde kan du åbne/lukke den i din global.asax i BegindRequest og EndRequest
"at læse gennem ConfigurationSettings.AppSettings er ikke "dyrt" i og med at det bliver cached første gang." (burningice)
Gælder dette generelt for web.config? Hvis man fx tilføjede en System.Configuration.SingleTagSectionHandler eller DictionarySectionHandler til sin web.config, ville indholdet af disse så også blive cached automatisk ved første get?
Det kommer lidt an på hvordan du henter configurationen. Så længe det er igennem ConfigurationSettings.GetConfig("sectioName") vil det blive cached. Hvis du bruger andet metoder må jeg desværre melde pas.
"Hvis du bruger andet metoder må jeg desværre melde pas."
... der kommer helt an på hvordan den er implementeret. Det bliver jo ikke cached ud af ingenting.
Det der gør at ConfigurationSettings cacher er at den internt har en instans af et IConfigurationSystem-object (konkret er det DefaultConfigurationSystem, som er en intern klasse i System.dll) som igen holder en reference til et ConfigurationRecord-object (igen en intern klasse). Så jeg kunne forestille mig at du selv skal implementere noget caching, evt. gennem et Singleton-pattern.
ConfigurationSettings gør følgende:
public static object GetConfig(string sectionName) { if (!ConfigurationSettings._configurationInitialized) { lock (typeof(ConfigurationSettings)) { if ((ConfigurationSettings._configSystem == null) && !ConfigurationSettings.SetConfigurationSystemInProgress) { ConfigurationSettings.SetConfigurationSystem(new DefaultConfigurationSystem()); } } } if (ConfigurationSettings._initError != null) { throw ConfigurationSettings._initError; } return ConfigurationSettings._configSystem.GetConfig(sectionName); }
hvor at _configSystem er det object der indeholder dataerne fra config-filen.
Hvis jeg forstår dette rigtigt (kan ikke helt gennemskue koden i din sidste kommentar), så er det du siger at så længe jeg bruger ConfigurationSettings.GetConfig("sectionName"), vil det object der returneres blive cached internt i metoden under første kald, og dermed ikke blive loaded og parset fra XML-filen ved følgende kald. Er det korrekt forstået? :)
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.