Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

LINQ performanse

[es] :: .NET :: LINQ performanse

[ Pregleda: 2505 | Odgovora: 13 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon LINQ performanse06.11.2009. u 16:32 - pre 176 meseci
Ne znam kako vi rešavate probleme sa kreiranjem raznih RDLC izveštaja,
ali ja napravim tabelu u DataSet-u, povežem polja sa kontrolama na izveštaju i onda pravim metode
koje pune tu tabelu.
Nekada izveštaji zahtevaju komplikovane procedure, dosta foreach petlji itd. pa mi tada
punjenje tabele bude sporo.
Da li je neko probao da tako komplikovane zadatke reši koristeći LINQ i kakvi su rezultati?
A vi,kako 'te?
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon Re: LINQ performanse28.01.2010. u 15:20 - pre 173 meseci
Evo na kraju ću sam sebi da odgovorim na pitanje :)

Scenario:
Imamo 5.000 klijenata u jednoj tabeli (Klijent), druga tabela o mesečnim zaduženjima (Zaduzenja - 30.000 zapisa), treća o uplatama (Uplate - 60.000)
Zadatak: Izlistati sve Klijente sa sumiranim zaduženjima, uplatama i preostalim dugom, koristeći podatke u DataSet-u.
Framework 2.0: Select metode, foreach petlje: trajanje nekoliko minuta!
Framework 3.5 i LINQ: trajanje 2-3 sekunde!!

Rešavanje konkretnog problema nije toliko bitno koliko sam hteo da pokažem ogromnu razliku u performansama!
Pozdrav!
A vi,kako 'te?
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: LINQ performanse28.01.2010. u 15:50 - pre 173 meseci
To poredjenje slabo znaci jer LINQ ne ucitava sve podatke na klijenta da bi radio agregaciju vec agregaciju radi na serveru, samim tim nije LINQ brzi od dataseta vec je sql brzi u agregaciji od custom foreach petlje ;). Napravi dataset sa semom rezultata agregacije i u select komandi ubaci agregatni SQL i dobices (bar za taj volume koji si naveo) priblizno iste rezultate.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon Re: LINQ performanse28.01.2010. u 17:27 - pre 173 meseci
Ja sam ovde radio sa podacima koji su već bili učitani u DataSet, dakle koristio sam LINQ to DataSet, tako da nije bilo obraćanja serveru,
a za ovo što si naveo potpuno se slažem.
Rezultat ovog testa je da je LINQ brži od klasičnih metoda selektovanja i dobijanja podataka iz DataSet-a.
A vi,kako 'te?
 
Odgovor na temu

sallle
Sasa Ninkovic
GTECH
Beograd

Član broj: 146
Poruke: 480
91.148.84.*

ICQ: 20785904


+4 Profil

icon Re: LINQ performanse28.01.2010. u 19:21 - pre 173 meseci
rezultat testa je da ti je prethodni algoritam bio katastrofalan
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
91.148.95.*



Profil

icon Re: LINQ performanse28.01.2010. u 20:10 - pre 173 meseci
Citat:
sallle: rezultat testa je da ti je prethodni algoritam bio katastrofalan

Ok možda je i to tačno, hajde možda dobijem neku korisnu informaciju od vas kako to da uradim bolje, a da i dalje ostanem na framework-u 2.0
Evo konkretnog zadatka: U DataSet-u su 3 tabele: Klijent(id, ime, prezime), Uplata(idKupac, iznos, datum), Zaduzenje(idKupac, iznos, datum), napunjene SVIM podacima iz baze.
Postoje odgovarajuće relacije između tih tabela.
Traži se sledeća tabela: ime, prezime, ukupne uplate, ukupnaZaduzenja, ukupanDug;
Koristiti podatke koji se već nalaze u DataSet-u (koji je, recimo, tipizirani), dakle bez obraćanja serveru, kako bi se kreirao ovaj izvestaj.

Ovo sada nema nikakve veze sa pitanjima sledećeg tipa: "A zašto povlačiš sve podatke iz baze", "A zašto ne kreiraš upit na serveru".. itd...
Nije poenta kako organizovati pristup podacima, već kako rešiti ovaj konkretan primer, i naravno njemu slične...

Eto očekujem neke nekatastrofalne alogritme :)
A vi,kako 'te?
 
Odgovor na temu

sallle
Sasa Ninkovic
GTECH
Beograd

Član broj: 146
Poruke: 480
91.148.84.*

ICQ: 20785904


+4 Profil

icon Re: LINQ performanse29.01.2010. u 02:29 - pre 173 meseci
pretpostavljam da si ti radio nesto tipa:
Code:

foreach (datarow dr in dtKlienti.rows)
{
       foreach (datarow drr in dtUplate.select ("klient_id="+dr["klient_id"]))
       {
             sumUplata = sumUplata + drr.uplata
       }

       forach (datarow drr in dtZaduzenja.select("klient_id="+dr["klient_id"])
       {
             sumZaduzenja = sumZaduzenja+drr.zaduzenje
       }
}

ovi selecti pretpostavljam rade sekvencijalno pretrazivanje, i ne koriste to sto ti imas relaciju.

a verovatno ovako ide mnogo brze:
Code:

foreach (datarow dr in dtklienti.rows)
{
       foreach(datarow drr in dr.getchildrows(klient_uplata))
       {
                sumUplata = sumUplata +drr.uplata;
        }
        foreach (datarow drr in dr.getchildrows(klient_zaduzenje))
        {
                 sumzaduzenje = sumzaduzenje + drr.zaduzenje;
        }
}


probaj pa vidi ima li efekta


 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: LINQ performanse29.01.2010. u 11:43 - pre 173 meseci
Zapravo LINQ mora da ti bude malcice (jedva primetno) sporiji zato sto moras da radis left outer join (preko LINQ group joina) da bi pokrio situacije u kojima klijent nema nijednu uplatu ili nijednu isplatu, obican linq join to proguta dok obican foreach to implicitno odradi. U svakom slucaju krajnji linq for datasets izraz je ovaj (pa uporedi to sa foreach verzijom ). Linq ima svoje dobre strane, ali u ovom primeru je problem resiv sa manje koda bez njega.

Code:
var final = from k in ds.Klijent
            join uu in
                (from u in ds.Uplata
                 group u by u.IDKupac
                 into uu
                     select new {IDKupac = uu.Key, UkupnoUplata = uu.Sum(x => x.Iznos)})
                on k.ID equals uu.IDKupac into ug
            join uz in
                (from u in ds.Zaduzenje
                 group u by u.IDKupac
                 into uz
                     select new {IDKupac = uz.Key, UkupnoZaduzenje = uz.Sum(x => x.Iznos)})
                on k.ID equals uz.IDKupac into zg
            from uglo in ug.DefaultIfEmpty()
            from zglo in zg.DefaultIfEmpty()
            select
                new
                    {
                        k.ID,
                        k.Ime,
                        k.Prezime,
                        UkupnoUplata = uglo == null ? 0 : uglo.UkupnoUplata,
                        UkupnoZaduzenje = zglo == null ? 0 : zglo.UkupnoZaduzenje
                    };

// foreach ;)
foreach (MainDataSet.KlijentRow krow in ds.Klijent)
{
    decimal sumU = 0, sumD = 0;
    foreach (MainDataSet.UplataRow uplataRow in krow.GetUplataRows()) sumU += uplataRow.Iznos;
    foreach (MainDataSet.ZaduzenjeRow zaduzenjeRow in krow.GetZaduzenjeRows()) sumD += zaduzenjeRow.Iznos;
}


Sto se tice vremena, oba su kod mene (sa obim podataka iz tvoje prve poruke) izvrsila (sa sve punjenjem tabele rezultatima) uvek za manje od 200ms. Uostalom pogledaj attached projekat
Kreiranje sample podataka
:: Start (FOREACH)
:: Stop (FOREACH), Rows: 5000 Time: 00:00:00.1100062
:: Start (LINQ)
:: Stop (LINQ), Rows: 5000 Time: 00:00:00.1840105

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
Prikačeni fajlovi
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon Re: LINQ performanse01.02.2010. u 16:14 - pre 173 meseci
Hvala na odgovoru!

Ovo je sigurno tačno, nema šta, samo mene zanima sledeće:
Recimo da imamo jos i vrstu zaduženja i uplate, recimo za osnovnu pretplatu, dodatke i ostalo
Moj realan problem je sto ne mogu preko GetUplataRows odmah da dobijem željene podatke, već koristim Select metode DataTable objekata.
Recimo na sve ono ši napravio dodamo i te vrste uplata, i napravimo 2 metode: double ukupneUplate(int id_klijent) i double ukupnaZaduzenja(id_klijent)
koje u sebi imaju Select poziv pa onda foreach.
Misliš li da bi to možda bio problem što meni ovo baš i ne radi najsjajnije preko foreach-a?
Evo izmenjenog projekta, zanima me da li sam ovde negde na gubitku?


A vi,kako 'te?
Prikačeni fajlovi
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: LINQ performanse01.02.2010. u 19:39 - pre 173 meseci
To sto sad hoces se zove pivoting i postoji resenje za to i preko foreach i preko LINQa. Dacu ti to sutra ujutro, sad nemam VS pored sebe.

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: LINQ performanse02.02.2010. u 09:31 - pre 173 meseci
Ok, nije pivoting, malo sam zbrzao odgovor jer sam video tri vrste uplata a tebi treba samo jedna kategorija (Osnovne uplate) tako da nam pivot ne treba. Odmah da ti nesto kazem, sve (ali BAS SVE) sto moze da uradi Select() mozes da uradis i u foreach petlji BOLJE i BRZE od select metoda, razlika nije ubiustvena ali uvek postoji. Iz tih razloga ja nikad ne koristim taj metod, ni pre LINQa ga nisam koristio. parametar select metoda je WHERE klauzula koja moze da se implementira sa prostim foreach+if/then

Dakle resenje sa foreach petljom bi ti bilo:

Code:
foreach (MainDataSet.KlijentRow krow in ds.Klijent)
{
    decimal ukUplate = 0, ukZaduzenja = 0;
    foreach (MainDataSet.UplataRow uplataRow in krow.GetUplataRows()) 
        if (uplataRow.vrstaUplate == vrstaZaduzenjaUplate.Osnovna.ToString()) ukUplate += uplataRow.Iznos;
    foreach (MainDataSet.ZaduzenjeRow zaduzenjeRow in krow.GetZaduzenjeRows()) 
        if (zaduzenjeRow.vrstaZaduzenja == vrstaZaduzenjaUplate.Osnovna.ToString()) ukZaduzenja += zaduzenjeRow.Iznos;
}


i vreme izvrsavanja pada sa 500ms na oko 300ms, u oba slucaja medjutim nema govora o nekoliko minuta, cak ni sa select tako da mi nije bas jasno kako si dobio takav rezultat. Najvece usporenje ovde ti pravi poredjenje stringova pre nego kompleksnost algoritma (poredjenje strigova uvek dodaje *O(n) u ciklicni algoritam jer za svaku iteraciju mora da uradi internu petlju da uporedi n karaktera), ako enum kodiras numericki i smestis u int polje brzina ce biti skoro identicna kao u pocetnoj varijanti. U svakom slucaju LINQ varijanta ovog upita (cije vreme izvrsavanja je otprilike isto) je:

Code:
var final = from k in ds.Klijent
            join uu in
                (from u in ds.Uplata
                 where u.vrstaUplate == vrstaZaduzenjaUplate.Ostalo.ToString()
                 group u by u.IDKupac
                     into uu
                     select new { IDKupac = uu.Key, UkupnoUplata = uu.Sum(x => x.Iznos) })
                on k.ID equals uu.IDKupac into ug
            join uz in
                (from u in ds.Zaduzenje
                 where u.vrstaZaduzenja == vrstaZaduzenjaUplate.Ostalo.ToString()
                 group u by u.IDKupac
                     into uz
                     select new { IDKupac = uz.Key, UkupnoZaduzenje = uz.Sum(x => x.Iznos) })
                on k.ID equals uz.IDKupac into zg
            from uglo in ug.DefaultIfEmpty()
            from zglo in zg.DefaultIfEmpty()
            select
                new
                    {
                        k.ID,
                        k.Ime,
                        k.Prezime,
                        UkupnoUplata = uglo == null ? 0 : uglo.UkupnoUplata,
                        UkupnoZaduzenje = zglo == null ? 0 : zglo.UkupnoZaduzenje
                    };

Nema neke mudrosti, samo se ogranici sors tabela pre agregacije.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
Prikačeni fajlovi
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon Re: LINQ performanse02.02.2010. u 09:48 - pre 173 meseci
Misliš da bi foreach bio brži i od situacije kada bih, recimo, imao tabelu od 100.000 zapisa, a trebaju mi, npr. sve osnovne uplate za zadataog klijenta??

To što meni radi mnogo sporije od ovih testova, verovatno je posledica toga što radim na jednom ne tako malom sistemu, i što sam pokušavao da
mi kod bude što sređeniji i da ga ima što manje, a da nisam pazio na te stvari. Bilo je tu dosta "pakovanja" u metode, klase,
verovatno mi treba malo vremena da istražim o čemu se tu radi.
A vi,kako 'te?
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: LINQ performanse02.02.2010. u 10:00 - pre 173 meseci
Da, bio bi. Ljudi generalno prave neke paralele o performansama izmedju datasetova i SQL Servera i prave paralele izmedju LINQa i T-SQLa, obe te paralele ne postoje. SQL Server ima query language kao LINQ ali SQLServer ima Query Optimizer i indekse koje LINQ nema. Isto tako dataset ima relacije, ali dataset takodje nema indekse. Bilo koja operacija tipa (select nesto from tabela where uslov) na SQL Serveru moze biti optimizovana, u DataSet i LINQ varijanti ne moze. Kako god da okrenes i sta god da koristis ta operacija se svodi na foreach+if i "skenira" kompletnu tabelu, select je najsporji, foreach najbrzi (zapravo najrza je for petlja preko indexera, to nismo pominjali), linq je u sredini. Postoji naravno i ona druga strana medalje vezana za trud, dal ti se isplati da potrosis sate za neki komplikovan query radjen preko for petlje ako to mozes za 2 minuta da uradis preko LINQa, a sve to da bi ustedeo 200ms na izrazu koji se pokrene jednom dnevno.

PS: Moram da se ispravim samo, for nije najbrzi, cak je najsporiji, interna struktura dataRows nije linearna vec je izvedena preko RBTree da bi ubrzala insert/update operacije. Posledica je da svaki table.Rows[index] zahtev mora da resi tabelu da bi vratio red na indeksu, tj svodi se na .Where(r => r.Index == x). Foreach sa druge strane putuje preko svih listova i ne mora da pretrazuje (on je zapravo pretrazivac). Sa for peltjom zapravo ceo ovaj proces moze da potraje podosta minuta, da nisi to mozda koristio?

[Ovu poruku je menjao mmix dana 02.02.2010. u 11:49 GMT+1]
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

vbvlada
Petrović Vladimir
Beograd

Član broj: 59233
Poruke: 209
*.viser.edu.rs.



Profil

icon Re: LINQ performanse02.02.2010. u 11:06 - pre 173 meseci
Ne, koristio sam Select u većini slučajeva jer mi je tako bilo zgodno da dobijem podatke zbog korišćenja izraza,
a tipizirane metode GetChildrows uopste nisam koristio, misleci da tu nema razlike.
Ali evo upravo sam na konkretnom sistemu testirao pomocu tih metoda umesto Select-a i razlika je osetna!
A vi,kako 'te?
 
Odgovor na temu

[es] :: .NET :: LINQ performanse

[ Pregleda: 2505 | Odgovora: 13 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.