Avatar billede davidfossil Nybegynder
23. maj 2005 - 20:34 Der 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?

Nogle fornuftige bud på "den optimale løsning"?

På forhånd tak :o)
Avatar billede arne_v Ekspert
23. maj 2005 - 20:40 #1
medmindre din SqlServerManager) klasse er ting at initialisere så bør du lave
en new per request.

request ind, new, lave en eller flere database oprationer, close, returner
resultat til browser

kombineret med en connection pool er det en god måde at få en ordentlig
skalerbarhed på

en connection per session vil kræve for mange connections og vil give fejl
ved høj volumen

en delt connection vil kræve en meget dyr synkronisering og vil få
performance  til at gå i bund
Avatar billede davidfossil Nybegynder
23. maj 2005 - 20:47 #2
arne_v (20:40:26)

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?
Avatar billede arne_v Ekspert
23. maj 2005 - 20:51 #3
jeg ville nok holde den åben for hele requesten og tage flere database queries
på samme connection

både p.g.a. bedre performance men også af funktionelle årsager (@@IDENTITY,
transaxction support etc.)

hvis ASP.NET ikke cacher konfigurations variable så bør du gøre det
Avatar billede burningice Nybegynder
23. maj 2005 - 21:01 #4
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
Avatar billede davidfossil Nybegynder
23. maj 2005 - 21:33 #5
"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?
Avatar billede burningice Nybegynder
23. maj 2005 - 22:02 #6
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.
Avatar billede davidfossil Nybegynder
23. maj 2005 - 22:04 #7
"Så længe det er igennem ConfigurationSettings.GetConfig("sectioName") vil det blive cached."

... også hvis man bruger en custom configurationhandler?
Avatar billede burningice Nybegynder
23. maj 2005 - 22:16 #8
"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.
Avatar billede davidfossil Nybegynder
23. maj 2005 - 22:23 #9
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? :)
Avatar billede burningice Nybegynder
24. maj 2005 - 02:04 #10
ja
Avatar billede davidfossil Nybegynder
26. maj 2005 - 17:21 #11
smid svar begge to :)
Avatar billede arne_v Ekspert
26. maj 2005 - 17:25 #12
ok
Avatar billede burningice Nybegynder
26. maj 2005 - 17:42 #13
.
Avatar billede davidfossil Nybegynder
27. maj 2005 - 12:38 #14
Og mange tak for hjælpen skal i have!
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester