702 messaggi dal 08 aprile 2009
Lavoro con le Generic.List e vorrei migliorare le perfomance di prestazioni nelle operazioni che eseguo.
Il dispositivo è android e sto lavorando su una lista di articoli di 20.000 record.
Anche una semplice OrderBy mi rallenta il sistema e una where mi pianta proprio il sistema.
Vorrei sapere se ci sono dei metodi per migliorare le performance.
Ho pensato anche di paginare i risultati ma prima della Skip e Take devo utilizzare per forza la orderby e questo mi rallenta.

Consigli utili???
11.730 messaggi dal 09 febbraio 2002
Contributi
Ciao,
paginazione e ordinamento devono necessariamente avvenire lato server, specie perché il tuo client è un dispositivo mobile. Come hai potuto constatare, ora la visualizzazione dei dati è lenta e presumo che anche il trasferimento dei dati dal server lo sia. La banda è preziosa :)

Conosci WCF Data Services? Grazie ad un'interfaccia REST che usa un protocollo standard chiamato ODATA ti permette di chiedere al server solo una pagina di risultati alla volta, filtrati e ordinati come preferisci tu.

Potresti utilizzare questo meccanismo anche in un servizio WCF "normale", leggi qui come fare:
http://weblogs.asp.net/cibrax/archive/2010/11/01/new-iqueryable-support-for-http-services-in-wcf.aspx

e poi questi:
http://wcf.codeplex.com/wikipage?title=WCF%20HTTP
http://wcf.codeplex.com/wikipage?title=Getting%20started:%20Building%20a%20simple%20web%20api

ciao
Modificato da BrightSoul il 03 dicembre 2011 12.08 -

Enjoy learning and just keep making
702 messaggi dal 08 aprile 2009
No i dati sono in locale e su file XML.
I dati vengono caricati in memoria in fase di login.
Per le ricerche non ci sono problemi.
Quello che rallenta è la Orderby su una List.
11.730 messaggi dal 09 febbraio 2002
Contributi
laurar181 ha scritto:

I dati vengono caricati in memoria in fase di login.


mmmh non è una soluzione che scala molto bene. Che succederebbe se i record fossero 100.000? Sei su un dispositivo mobile e le risorse vanno usare con parsimonia. Purtroppo se hai necessità di lavorare con un file xml così grosso non ci sono mote vie d'uscita. Vediamo...

Potresti provare ad interrogare la sorgente dati (il file xml) usando Linq to XML ma dubito che così facendo otterrai dei vantaggi tangibili perché l'intero documento deve comunque esser caricato in memoria.

Quando le prestazioni sono importanti si usa la classe XmlReader che ti fornisce un accesso read-only e forward-only al file xml ma così rinunci completamente all'espressività che ti offre LINQ e sarebbe comunque difficile riuscire ad inventarsi un modo più efficiente di ordinare i dati.

Quindi... perché non risolvere il problema alla radice ed utilizzare un database al posto del file xml? Potresti aggiungere degli indici sulle colonne su cui devi fare l'ordinamento e l'operazione sarebbe notevolmente più veloce. Credo che su Android tu possa usare SQLite, che dispone di un provider .NET.

Se i dati ti arrivano in xml puoi leggerli sequenzialmente con il già citato XmlReader ed inserirli nel database mano a mano che li leggi. Può andare?
Modificato da BrightSoul il 05 dicembre 2011 21.00 -

Enjoy learning and just keep making
702 messaggi dal 08 aprile 2009
I dati vengono caricati con il Serialize.
Lavoriamo con file xml e non con un database in quanto il cuore del sistema srà uguale per tutte le versioni che usciranno per i diversi dispositivi (windows ce, windows 7, android, IOS,....). Da studi effettuati non c'è un database che va bene per tutti e quindi abbiamo optato per questa soluzione.
Il software (in una versione precedente) già esiste ed è attivo in migliaia di licenze. Da una statistica effettuata (visto che vengono esportati dal gestionale solo gli articoli per cui l'agente di vendita è resposabile) si aggirano sempre tra i 2.000 e i 6/7.000 articoli. Ci sono delle singole eccezioni per cui dobbiamo gestire 20.000 articoli.
Al momento come soluzione ho trovato che al momento del serialize ordino gli archivi per un determinato campo, in questo modo risolvo ambiamente i problemi di ricerca dati nelle varie form.
Quello che non mi spiego è perchè una order by intacchi così tanto i tempi.
Ciao.

Lavoriamo con file xml e non con un database in quanto il cuore del sistema srà uguale per tutte le versioni che usciranno per i diversi dispositivi (windows ce, windows 7, android, IOS,....). Da studi effettuati non c'è un database che va bene per tutti e quindi abbiamo optato per questa soluzione.

Boh, così su due piedi ti direi che la soluzione adottata per la persistenza dei dati è un requisito di carattere non-funzionale. Il tuo design dovrebbe andare a gestire questi aspetti e fornire quindi un meccanismo che possa astrarre dai medesimi.

Quello che non mi spiego è perchè una order by intacchi così tanto i tempi.

Sì, è assolutamente normale.
Tanto per cominciare, per il problema dell'ordinamento stesso.
Mediamente, nella migliore delle ipotesi, avrai una complessità di natura logaritmica.
Aggiungo, poi, che da quanto scrivi sembra che tu stia utilizzando LINQ per il problema in oggetto.
Nello specifico, la clausola "OrderBy" invoca un delegato ogni volta che si deve ottenere la chiave di ordinamento.
In quest'ottica, Array.Sort è di gran lunga più efficiente.

Nicola Baldi
"Make things as simple as possible, but not simpler."
>>> My blog <<<
702 messaggi dal 08 aprile 2009
naighes ha scritto:



Boh, così su due piedi ti direi che la soluzione adottata per la persistenza dei dati è un requisito di carattere non-funzionale. Il tuo design dovrebbe andare a gestire questi aspetti e fornire quindi un meccanismo che possa astrarre dai medesimi.


Per quale motivo dici che la mia applicazione non ha il requisito di persistenza di dati???
Non si tratta di un gestionale dove vengono gestite in inserito e aggiornamento tabelle anagrafiche ma solo di inserimento ordini che poi vengono inviati al gestionale principale.
11.730 messaggi dal 09 febbraio 2002
Contributi
Ciao,
credo che naighes intendesse consigliarti di aggiungere un livello di astrazione tra l'applicazione client e il caricamento dei dati.

Effettivamente, in questo momento immagino che il client abbia una dipendenza da System.Xml se in uno dei metodi hai del codice tipo questo:
var xmldoc = new System.Xml.XmlDocument();
xmldoc.Load("file.xml");


Se è questo il caso, la classe XmlDocument è stata cablata all'interno del metodo per vostra scelta, come dicevi in un precedente post:

laurar181 ha scritto:

Da studi effettuati non c'è un database che va bene per tutti e quindi abbiamo optato per questa soluzione.


Alla luce dei problemi riscontrati con l'xml, forse dovreste riconsiderare questa scelta e disaccoppiare la logica di funzionamento del client dal metodo di persistenza, come suggeriva naighes.

Quindi, anziché lavorare direttamente con XmlDocument, potresti adoperare un'interfaccia molto semplice:
public interface IDataRepository{
  IEnumerable<TuoTipo> GetData();
  void SaveData(List<TuoTipo> data);
}
e poi scrivere delle implementazioni concrete per permettere all'applicazione di lavorare con varie tecnologie. Potresti quindi creare un SqliteDataRepository, XmlDataRepository, SqlCeRepository, e così via.

Riconosci le differenze tecnologiche che esistono tra le varie piattaforme e supportale nella tua applicazione affinché l'utente possa sperimentare il meglio che il suo dispositivo gli può offrire.
Ti assicuro che gli utenti apprezzeranno la conoscenza che avete maturato sulla sua piattaforma.

Invece, preferire l'XML (o altro sistema) perché è l'unico denominatore comune, vi semplificherà di certo lo sviluppo ma il tempo che risparmiate voi lo pagheranno poco per volta i tanti utenti che utilizzeranno l'applicazione.

Quindi, tornando in tema, usare un'interfaccia ti consente di astrarre il meccanismo di persistenza così che l'applicazione non saprà mai (ma neanche deve importargli) se sta lavorando con Sqlite, SqlCE o semplice XML.

Un livello di astrazione aggiunge complessità, è vero, ma esistono strumenti come uno IoC container che azzerano - quasi - la difficoltà di sviluppo che ne deriva. In pratica funziona così:
  • Il metodo della tua applicazione client NON userà più la parola chiave new per creare una nuova istanza, ma chiederà al container di dargli un'istanza di IDataRepository
  • Il container, automaticamente, crea l'istanza di un tipo concreto che implementa IDataRepository e gliela fornisce. Ma quale tipo concreto va ad istanziare? SqliteDataRepository o SqlCeDataRepository o altro? Questo dipende da come hai configurato il container. Quando dovrai creare il package di installazione per Android, andrai nel file di configurazione della tua applicazione e imposterai che l'istanza da restituire per IDataRepository è SqliteDataRepository. Quando crei il package per Windows Phone la rimapperai su SqlCeDataRepository, e così via. Così, senza dover mettere mano al tuo codice ma solo apportando piccole modifiche al file di configurazione potrai "ottimizzare" l'applicazione per il dispositivo su cui vai ad installarla.
  • Quando hai messo in piedi un sistema del genere ti si aprirà un mondo: gli scogli che prima ti ostacolavano lo sviluppo ora diventeranno discese da percorrere ben volentieri per offrire un software di miglior qualità all'utente

Questo è un po' di pseudo-codice per farti vedere come cambierebbe il metodo che si occupa di caricare i dati:

var repo = Container.Get<IDataRepository>();
var lista = repo.GetData();
foreach (var elemento in lista){
...
}
Ovviamente il metodo .GetData puoi personalizzartelo come vuoi, ad esempio per fargli supportare la ricerca e l'ordinamento.

ciao
Modificato da BrightSoul il 28 dicembre 2011 11.17 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.