Pouze tento týden sleva až 80 % na e-learning týkající se C# .NET. Zároveň využij akci až 30 % zdarma při nákupu e-learningu - Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
discount 30 + hiring
Avatar
dbarvik
Člen
Avatar
dbarvik:18.3.2018 18:03

Zdravím,
vytvořil jsem si aplikaci, kde pomocí sériového portu přijímám data a ukládám je do queue. Ty data je třeba protáhnout filtrem, a tak bych potřeboval poradit, zda existuje elegantnější řešení než to co používám :
Z queue odstraňuji hlavičku paketu, a data převádím do pole, a poté pomocí for cyklu dlěám filtraci, kdy využívám 8 předchozích prvků pole. Potýkám se s tím, že aplikace je moc pomalá. příjímám totož 4 bytes za 1 ms a tak než se projede celé queue tak to trvá.
Budu rád, když mě někdo popostrčí s efektivnějším řešením a doufám, že jsem vše popsal srozumitelně.

 
Odpovědět
18.3.2018 18:03
Avatar
Odpovídá na dbarvik
sadlomaslox25:19.3.2018 0:24

Co to znamena aplikace je pomala ? Pokud vim tak seriova linka je schopna zpracovavat okolo 0,5 MB/s a prumerny procesor je urcite schopny zpracovavat daleko vic nez 0,5 MB/s :).

 
Nahoru Odpovědět
19.3.2018 0:24
Avatar
dbarvik
Člen
Avatar
dbarvik:19.3.2018 9:56

Zapomněl jsem dodat, že ty data vykresluji navíc do grafu, a chová se to tak, že přijímám data 3 sekundy, a než aplikace zpracuje a zobrazí všechny data tak uplyne cca minuta.

 
Nahoru Odpovědět
19.3.2018 9:56
Avatar
Odpovídá na dbarvik
sadlomaslox25:19.3.2018 10:26

pokud pocitam spravne tak 12kB zpracovavas 3 minuty. Pokud tam nedelas super analyzy tak mas spatne napsany ten algoritmus zpracovani. Asi by bylo vhodne ho sem napostovat jinak ti nikdo nedokaze poradit kde je problem.

 
Nahoru Odpovědět
19.3.2018 10:26
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:19.3.2018 18:50

Bez kódu ti fakt nikdo nepomůže, ale mně třeba zaráží, že "projíždíš" frontu-proč?
Počítám že frontu tam máš jakobuffer kvůli tomu že zpracování dat trvá déle než jejich příjem a pak si přece taháš prvek z čela fronty a ten zpracuješ - vytažení dvou čísel (souřadnice grafu) bude trvat - ať nežeru - mikrosekundu, ale spíš míň

 
Nahoru Odpovědět
19.3.2018 18:50
Avatar
dbarvik
Člen
Avatar
dbarvik:19.3.2018 19:58

Tady přikládám kód, kde mám příjem dat, a zobrazení v grafu. Už tohle trvá strašně dlouho. Nejsem žádný zkušený programátor, proto uvítám rady, kde by se dalo něco optimalizovat.

Serial_plot

 
Nahoru Odpovědět
19.3.2018 19:58
Avatar
Odpovídá na dbarvik
Tomáš Vitek:19.3.2018 20:58

Jsem moc líný na to, abych si to pročítal úplně celé, nicméně jsem si všiml, že značnou část zpracování tvých dat děláš v try bloku, který umí kód docela zpomalit. Nešlo by to ošetřit nějak jinak?

 
Nahoru Odpovědět
19.3.2018 20:58
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na dbarvik
ostrozan:19.3.2018 23:38

Mám otázku :
opravdu je to tvoje aplikace?
Nebo jsi to celé (nebo část) převzal- ztřeba z nějakého SDK (asi měřáku , nebo měřící karty)?
Pokud je to ten druhý případ, tak by to mělo být funkční a chybu bych hledal v tvojich úpravách, pokud jsi nějaké dělal.
V druhém případě bych to dělal asi jinak, ale neznám protokol toho zařízení, co ty data posílá, tím myslím formát zprávy, jestli a jak velké mezery jsou mezi paketama.

Editováno 19.3.2018 23:39
 
Nahoru Odpovědět
19.3.2018 23:38
Avatar
Odpovídá na dbarvik
sadlomaslox25:19.3.2018 23:51

pokud ti chodi data skutecne kazdou 1ms tak se nediv ze je to tak pomale kdyz se pokousis neustale prekreslovat UI. pro tvoje potreby staci aby se data vykreslily tak jednou za 30 ms. To same se souborem. Pokud mas stary plotnovy HDD tak zapisovat jeden znak kazdou milisekundu zasekne system.

private List<int> _localBuffer = new List<int>();
        private DateTime _lastUpdate = DateTime.MinValue;
        private List<int> _fileLogBuffer = new List<int>();

        private void DataProcessing(byte[] data)
        {
            int capRaw = (data[0] * 256) + data[1];
            _localBuffer.Add(capRaw);

            if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 30)
            {
                int capAverage = (int)Math.Round(_localBuffer.Average());
                _localBuffer.Clear();
                _fileLogBuffer.Add(capAverage);

                CapWrite("Relative Capacitance: " + capAverage.ToString());
                DrawChart1(pointindex, capAverage, 0);
                pointindex++;

                if (_fileLogBuffer.Count > 10)
                {
                    using (StreamWriter sw = File.AppendText(path))
                    {
                        foreach (int value in _fileLogBuffer)
                            sw.WriteLine(value.ToString());
                    }

                    _fileLogBuffer.Clear();
                }
            }
        }

dal toto staci udelat jen jednou a ne v kazdem vykresleni:

chart1.ChartAreas["ChartArea1"].AxisY.Maximum = 4000;
chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 1000;
chart1.ChartAreas["ChartArea1"].AxisY.Title = "C[raw]";
chart1.ChartAreas["ChartArea1"].AxisX.Title = "samples";

dal do ControllLoop do smycky dat nejake thread.Sleep jinak to zbytecne spotrebovava strasne moc CPU (nebo pouzit nejaky synchronizacni prostredek nebo nejlip nahradit BlockingCollection)

dal Queue<> neni bezpecne pouzivat mezi ruznyma vlaknama presne tak jak to delas ty. doporucuju nahradit BlockingCollection nebo synchronizovat pristup.

a dal je tam podle me spatne zpracovani tech paketu protoze ty pocitas stim ze maji fixni delku ale v kodu mas poznamku ze ta delka muze byt variabilni.

 
Nahoru Odpovědět
19.3.2018 23:51
Avatar
Odpovídá na sadlomaslox25
Marian Benčat:20.3.2018 0:00

eh... stačily mi 2 věty, dále jsem popravdě nečetl.. vezmu tedy reakci na první 2 věci co mě zarazily...

  1. to, že něco JAKKOLIV zapíšeš na disk v žádném případě neznamená, že se to tam jde fyzicky zapisovat... to že někam něco zapíšeš znamená, že si zapsal něco někam do paměti (určené většinou nějakým file descriptorem).. operační systém, jeho filesystém, konkrétně nějaký FSFLUSH si určuje sám, kdy na ten disk reálně zapíše, většinou volí nějakou lineární srtategii tak, aby zapisoval po cestě a nemusel hýbat tolik hlavou...
  2. To že něco děláš často na nějaké propertě neznamená, že se stejně často překresluje UI a neni to pouze .NET/ Winforms specific, ale je to celkově pro všechny UI frameworky.. ano - existují nějaké výjimky, které dělají nějaký forced-reflow, ale to že něco Xkrát za sekundu někde nastavíš rozhodně nemusí znamenat, že se to Xkrát za sekundu překresluje..
Editováno 20.3.2018 0:01
Nahoru Odpovědět
20.3.2018 0:00
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
sadlomaslox25:21.3.2018 0:56
  1. teorie hezka, jeste by to chtelo zkusit v praxi, kde se napr. dozvime ze do souboru se ty data sice fyzicky nezapisuji ale jelikoz je stream writer v bloku using tak si neustale alokuje a dealokuje handly + napr. na windows 10 se k tomu prida indexace souboru ktera vytizi pocitac nasobne vic nez samotny zapis.
  2. to ze nekdo vola chart1.Series[se­ri].Points.Ad­dXY(x, y); rozhodne zpusobi prekresleni celeho grafu. a prekreslovani standartni Winform komponenty Chart (ktera je z hlediska optimalizace nejhorsi komponenta co je Winformech) trva cca 5ms pro 50 bodu a pro 15ms pro 1000 bodu na i7.

... asi by to chtelo pri studiu cist vic nez 2 vety.

 
Nahoru Odpovědět
21.3.2018 0:56
Avatar
Odpovídá na sadlomaslox25
Marian Benčat:21.3.2018 1:53

OH bože ty zase krmis.. Baťovci raději měli zůstat u dělani cviček...

1)nejdříve meles o HW a plotnovem disku a zápisu na fyzické medium, když ti povim ze je to hloupost, tak to raději stocis k SW implementaci.. Nebudu zde ani mluvit o tom, ze OS určité při zápisu žádný index obsahu souboru nedělá, zaindexuje si tak maximálně path. TY vytizenej počítači..

  1. winforms a jeho messagequeue funguje ve většině strategii tak, ze udela vždy všechny tasky co ma v queue a az pak dělá sama repaint UI... pokud si komponenta neforcne synchronni repaint sama.. Pro což ve valné většině případů není důvod. .. Ani ten chart to nedělá.. A proto musíš dělat nějaký třeba invalidate() a pak update(), pokud chceš synchronní repaint.. (Hned). A ty cisilka co SIS tady vycucal z prstu, jsou úplně irelevantní. Prostě změna property 1000x za sec neznamená nutne 1000x za sec repaint.

    A ted mi odpovez ty, proč s lidmi jako ty ztracim čas.. ? Už mi tu jen chybí místní CEO co přijde jednat z pozice moci a vyhrožovat nějakým banem, jako bych se mel z toho asi zhroutit.

Nahoru Odpovědět
21.3.2018 1:53
Totalitní admini..
Avatar
Marian Benčat:21.3.2018 1:54

Sakra, nenapsal jsem.moc znaku za sekundu, abych ITnetworku nezasekal systém..

Nahoru Odpovědět
21.3.2018 1:54
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
sadlomaslox25:21.3.2018 10:59
  1. jo souhlasim
  2. to sem nevedel ze to nevola instantne repaint, ale v danem pripade je to volane z jineho vlakna pres invoke kazdou 1ms takze to skutecne zpusoby prekresleni a s roustoucim poctem bodu je kazde prekresleni pomalejsi a pomalejsi.

ale ackoli je to paradoxni, tak mnou navrzena uprava kodu stale vyresi autoruv problem :-D

to ze je batovka na**** souhlasim, ale podle pohovoru absolventu v aktualni a minule firme na tom ostatni skoly nejsou o moc lip :-)

 
Nahoru Odpovědět
21.3.2018 10:59
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 14 zpráv z 14.