Web application reattiva

venerdì 30 marzo 2012 - 16.45

paolo973 Profilo | Senior Member

per rendere più veloce, più reattiva una web application che usa asp.net, database access e c# con provider aruba,
cosa cambiare?

ciao

andrestu Profilo | Expert

domanda da cento milioni di dollari...
anche io utilizzo Aruba e mi son trovato di fronte allo stesso problema dopo aver progettato un mini gestionale per agenzie immobiliare, su pc di casa funzionava velocemente, messo su aruba addio velocità.
Ho visto che Aruba fornisce diversi servizi un pò più dedicati per chi vuole prestazioni migliori ma il costo aumenta, e comunque penso che se riesci ad ottimizzare al massimo la tua web app in modo da farla girare veloce anche con hosting di base sei già a metà della strada.
Quello che ti consiglio a parer mio è l'utilizzo massicio di Ajax in modo da non dover aggiornare ad ogni chiamata l'intera pagina. Per quanto riguarda i dati opera su dati disconnessi così limiti al massimo le chiamate al Db... applicando bene queste due regole penso che noti già un miglioramento.
Magari limita il più possibile l'utilizzo dei controlli Aspnet, per farti un esempio banale se devi visualizzare un immagine che non richiede nessuna elaborazione server-side non utilizzare il controllo dedicato ma inserisci direttamente codice Html.
Perdonami se i miei suggerimenti ti sono sembrati molto banali ma non conoscendo il tuo grado di competenza...

Gluck74 Profilo | Guru

sono d'accordo con i suggerimenti tranne l'utilizzo dei dati disconnessi.
Notoriamente asp.net lavora meglio con i dati connessi (per capirci DataTable/DataSet sono disconnessi, DataReader è connesso)

Proprio perché siamo in ambiente "riservato", ed il pool non dispone di risorse infinite, meglio usare dati connessi che non vengono messi in memoria.

Sono aperto a confronti su questo argomento

____________
Ricordati di utilizzare il tasto "Accetta" se i nostri consigli ti sono serviti a risolvere il problema.
È il modo per ringraziare chi ti ha aiutato.

andrestu Profilo | Expert

x Gluck74:
si forse hai ragione e sicuramente hai molta più esperienza di me, vorrei però capire meglio alcune cose.
prendiamo ad esempio un e-commerce sviluppato in Aspnet e ipotizziamo che 100 utenti effettuano query filtrate sui dati contemporaneamente, non sarebbe più veloce se i dati fossero già in memoria?

Andrea Restucci - Web Developer

massimo.missaglia Profilo | Newbie

Domanda: Perchè non passi a SQL Server e, utilizzando correttamente indici e stored procedure, otterrai sicuramente dei vantaggi in termini di prestazioni.

In SQL Server inoltre viene mantenuto in cache il piano di esecuzione delle stored procedure, pertanto se una query viene chiamata 100 volte, con i medesimi paramtetri, sarà molto performante.

Il mio sito www.massimomissaglia.com è un CMS da me interamente costruito e lavora su database SQL Server.

andrestu Profilo | Expert

x Massimo:
complimenti per il CMS dev'essere stato un lavoro lungo e complicato...
io utilizzo già Sql Server e in aggiunta 'trasformo' i dati in collection residenti in memoria per poi elaborarli con LINQ to object.
effettuo la chiamata al db una volta solo, mappo i dati in memoria con il vantaggio di crearmi facilmente delle collection di tipi customizzati che non sono legati esclusivamente alla logica in cui sono strutturati nel db, e per interrogarli non devo fare nessuna connessione aggiuntiva.
Come controindicazione devo però gestire la reinizializzazione delle collection ad ogni modifica fatta al db.
Prendiamo in considerazione l'esempio dei 100 utenti che fanno query in contemporanea, meglio avere zero connessioni al db oppure 100 contemporaneamente?


Andrea Restucci - Web Developer

Gluck74 Profilo | Guru

>x Gluck74:
>si forse hai ragione e sicuramente hai molta più esperienza di
>me, vorrei però capire meglio alcune cose.
>prendiamo ad esempio un e-commerce sviluppato in Aspnet e ipotizziamo
>che 100 utenti effettuano query filtrate sui dati contemporaneamente,
>non sarebbe più veloce se i dati fossero già in memoria?
>

si, certo, ma dipende anche dalla situazione.
Prima di tutto meglio prendere i dati dal datareader e metterli in oggetti custom consoni alla nostra applicazione (cosa che stai già facendo mi sembra)
La domanda sorge spontanea: ma allora che differenza c'è? posso usare le datatable e i dataset.
SI, anche, ma la differenza sostanziale è che usando oggetti custom ho tutto tipizzato (che è cosa buona e giusta), e non sono strettamente legato alla struttura delle tabelle/query fatte sul DB.

Inoltre:
Se i dati visualizzati dagli ipotetici 100 utenti, sono dati che non variano spesso, DEVONO essere messi in memoria ed evitare continue query sul DB.
Come? sconsiglio la Session, bensì la cache (System.Web.Cache).

Nativamente comunque i dataSourceControl fanno già un minimo di questo, sfruttando il ViewState; Quando vengono effettuati postback da controlli (una griglia che passa in edit mode ad esempio) se ci fai caso la query sul DB non viene rieseguita. Ma il ViewState non lo toccherei più di tanto, anzi, lo disabiliterei proprio per i controlli DataSource, e opterei per soluzioni più performanti

Inoltre già l'ObjectDataSource permette di mettere i dati in cache semplicemente "a design time", poi per cose più raffinate, allora puoi usare del codice custom fatto ad hoc, o addirittura appoggiarti a librerie apposite tipo Enterprise Library (http://msdn.microsoft.com/en-us/library/ff664753(v=pandp.50).aspx) per .NET fino a 3.5, integrata nel framework dal .NET 4.0
(Citazione: ASP.NET Web application or Web service if you need features not included in the ASP.NET cache)




ciao

____________
Ricordati di utilizzare il tasto "Accetta" se i nostri consigli ti sono serviti a risolvere il problema.
È il modo per ringraziare chi ti ha aiutato.

andrestu Profilo | Expert

io normalmente utilizzo l'oggetto application per memorizzare le collection di 'base' e poi faccio cache dei risultati delle query (Linq) in session.
per gestire il tutto utilizzo ObjectDataSource collegato ad un oggetto creato ad hoc che appunto gestisce la cache su session.
a questo punto visto che non ne so niente di System.Web.Cache ti chiedo:
come mai sconsigli l'utilizzo dell'oggetto session?
che differenza cè se utilizzassi System.Web.Cache?

Andrea Restucci - Web Developer

Gluck74 Profilo | Guru

>io normalmente utilizzo l'oggetto application per memorizzare
>le collection di 'base' e poi faccio cache dei risultati delle
>query (Linq) in session.
>per gestire il tutto utilizzo ObjectDataSource collegato ad un
>oggetto creato ad hoc che appunto gestisce la cache su session.
>a questo punto visto che non ne so niente di System.Web.Cache


Ciao,
dunque, bisogna fare una piccola distinzione tra le tre scelte:
Application: si può usare per dati condivisi in tutta l'applicazione, per tutti gli utenti
Session: si può uasare per dati NON condivisi tra utenti. Ognuno ha i suoi
Cache: si può usare per dati condivisi tra gli utenti, per l'applicazione

ora, sembrerebbe che tra "application" e cache non ci sia differenza..... ed in effetti, a livello pratico non c'è nè molta.
Sicuramente la cache offre molta più flessibilità visto che è possibile stabilire una scadenza basata su tempo, chiave, database.
Con "Application" non abbiamo nessuna politica di gestione, quindi tutto da fare a mano!!!!
In termini di performance non c'è differenza
(un test con circa 200 thread che accedono a dati per un minuto consecutivo, ha mostrato 130 accessi al sencodo di "Application" contro 138 della cache)
Una differenza abbastanza sostanziale sta invece nel fatto che la chache gestisce internamente accessi simultanei, mentre con la "Application" c'è bisogno di stabilire un meccaniscmo di lock al codice.

Molto diverso invece il discorso per Session.
Oltre ad avere uno spazio di memoria separato per ogni utente, tutto rimane simile ad "Application" se abbiamo la SessionState InProc.
Tutto cambia se abbiamo la SessionState StateServer o SqlServer. In questi due casi sono ammessi solo oggetti serializzabili, e non sono ammessi oggetti MarshalByRef.


Oltre a questi aspetti tecnici, comunque io uso la cache per dati "condivisi", esempio dati per popolare le dorpdownlist, dati che sono comunque comuni a tutti gli utenti e che vengono richiesti spesso (menù, parametri, ruoli, liste di oggetti ecc, ecc), mentre la session la uso (quasi mai comunque) per dati che sono personalizzati da ogni utente (liste filtrate da ricerche, parametri di ricerca, permessi utente)


>come mai sconsigli l'utilizzo dell'oggetto session?
>che differenza cè se utilizzassi System.Web.Cache?
>
Sconsiglio l'utilizzo della session perché, a detta di alcuni esperti in materia, non è gestita bene da ASP.NET. Ci sono altri metodi (non specificati) a detta di questi esperti per fare la stessa cosa.
Io uso la cache con key personalizzate con l'ID utente


Spero di averti chiarito un po le idee.
Alcuni riferimenti:
http://www.west-wind.com/weblog/posts/2004/Dec/22/ASPNET-Cache-and-Session-State-Storage
http://www.codeproject.com/Articles/26621/Cache-Session-and-ViewState


____________
Ricordati di utilizzare il tasto "Accetta" se i nostri consigli ti sono serviti a risolvere il problema.
È il modo per ringraziare chi ti ha aiutato.

andrestu Profilo | Expert

Grazie mille sei stato molto efficente nel spiegarmi tutto, un ultima cosa:

>Una differenza abbastanza sostanziale sta invece nel fatto che la cache gestisce internamente accessi simultanei, mentre con la "Application" c'è bisogno di stabilire un meccaniscmo di lock al codice.

nel mio caso utilizzo "Application" per memorizzare collection a cui hanno accesso più utenti (sessioni) simultaneamente, non ho progettato nessun meccanismo di lock e non so neacnhe di cosa si tratta (immagino che intendi un meccanismo che gestisca l'accesso al codice), dovrei preoccuparmene?

Andrea Restucci - Web Developer

Gluck74 Profilo | Guru

se accedono in sola lettura no,
il problema è quando si va a scrivere, chi va a scrivere, ed ogni quanto va a scrivere.

Se queste collection che vengono lette dagli utenti, vengono create una tantum quando parte l'applicazione, non hai problemi.
Se vengono ricreate per ogni sessione che si avvia.... c'è qualcosa che non va
se vengono modificate da ogni utente, occhio alla perdita di tati
se vengono modificate spesso, devi gestire l'accesso concorrente

____________
Ricordati di utilizzare il tasto "Accetta" se i nostri consigli ti sono serviti a risolvere il problema.
È il modo per ringraziare chi ti ha aiutato.

andrestu Profilo | Expert

be per farti un esempio banale prendiamo in considerazione un ecommerce:

la lista di prodotti la salvo in application,
Application["listaProdotti"] = 'nuova lista'
questa lista viene letta da più utenti in simultanea e faccio cache su session dei risultati delle query
e fin qui tutto ok
ma ammettiamo che voglia fare aggiornare i prodotti da qualsiasi utente, in questo caso potrei avere dei problemi?

>se vengono modificate da ogni utente, occhio alla perdita di tati

cioè potrei non riuscire a riscrivere dentro l'oggetto Application sulla stessa chiave
Application["listaProdotti"] = 'nuova lista ricreata da un utente'
in questo modo faccio una nuova assegnazione della chiave "listaProdotti", potrei avere problemi?


Andrea Restucci - Web Developer

Gluck74 Profilo | Guru

>be per farti un esempio banale prendiamo in considerazione un
>ecommerce:
>
>la lista di prodotti la salvo in application,
>Application["listaProdotti"] = 'nuova lista'
questo potrebbe andare bene

>questa lista viene letta da più utenti in simultanea e faccio
>cache su session dei risultati delle query
questo non l'ho capito. che vuol dire fai cache su session?
fai ulteriore cache per ogni utente in base ai filtri di ricerca?
Inutile, se i prodotti sono già in memoria sprechi solo risorse

>e fin qui tutto ok
>ma ammettiamo che voglia fare aggiornare i prodotti da qualsiasi
>utente, in questo caso potrei avere dei problemi?
Sicuramente!!!!!

>cioè potrei non riuscire a riscrivere dentro l'oggetto Application
>sulla stessa chiave
>Application["listaProdotti"] = 'nuova lista ricreata da un utente'
>in questo modo faccio una nuova assegnazione della chiave "listaProdotti",
>potrei avere problemi?
non solo potresti avere errore perché due thread stanno cercando di scrivere nello stesso istante lo stesso dato,
ma anche se la scrittura fosse in due momenti diversi, ma intramezzo alle letture, la seconda scrittura vanifica la prima.
esempio:

utente 1 legge "pere:5, mele:4"
utente 2 legge "pere:5, mele:4"
utente 1 compra una mela: scrive "pere:5, mele:3"
utente 2 compra una pera: scrive "pere:4, mele:4"
utente 3 legge: "pere:4, mele:4"

ora questo è un esempio stupido (in realtà non succede proprio così), ma se metti 100 utenti che navigano il sito, vedi che forse l'esempio stupido potrebbe anche avverarsi, oltre ad altri problemi di concorrenza in memoria.

cerca su internet "asp.net thread safe" e troverai tantissime info.
qui un esempio:
http://blogs.msdn.com/b/benchr/archive/2008/09/03/does-asp-net-magically-handle-thread-safety-for-you.aspx



>
>
>Andrea Restucci - Web Developer


____________
Ricordati di utilizzare il tasto "Accetta" se i nostri consigli ti sono serviti a risolvere il problema.
È il modo per ringraziare chi ti ha aiutato.

andrestu Profilo | Expert

ok ho capito cosa intendi con l'esempio delle pere e mele, allora in tal caso sarà meglio che inizio ad usare System.Web.Cache così gestisce in automatico questo aspetto.
Per quanto riguarda la cache in session delle query ti spiego meglio.

>Inutile, se i prodotti sono già in memoria sprechi solo risorse

La collection si trova in application.
l'utente la legge da application e la filtra tramite LINQ, il risultato (che sarà ovviamente una nuova collection diversa dall'originale) deve finire da qualche parte, quindi o in application con la gestione di chiavi che identificano la sessione (come dicevi prima) oppure direttamente in session
si che i prodotti sono già in memoria ma la query genera per forza una nuova collection (ovviamente nel caso in cui vengono applicati filtri)
oltretutto quando mi sposto di pagina con un datasource non devo rifare nuovamente la query se si trova già da qualche parte
l'ideale sarebbe salvare il risultato in application e identificarla in qualche modo cosi da renderla disponibilie se rischiesta da qualche altro utente, ma per il momento non voglio complicarmi la vita...




Andrea Restucci - Web Developer
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5