Jak zrychlit kód? – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Jak zrychlit kód? – .NET – Fórum – Programujte.comJak zrychlit kód? – .NET – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
Mutagen0
Super člen
17. 4. 2013   #1
-
0
-

Zdravím, mám tento kód co mi stáhne zdrojový kód stránky, ale jde mi o to, že po někdě 1000 požadavcích, už projetých se to začne spomalovat a hlavně ani nevím proč. Jede to ve vlastním vlákně. Nějaký připomínky, proč se to pak začne zpomalovat? A potřebuju stáhnout někdě 65tisíc stránek ... Nějaký nápady? Díky moc

	private string GetSourceCode(string url)
        {
            try
            {
                WebRequest req = HttpWebRequest.Create(url);
                req.Method = "GET";

                string source;
                using (StreamReader reader = new StreamReader(req.GetResponse().GetResponseStream()))
                {
                    source = reader.ReadToEnd();
                }
                string text = source.Substring(source.IndexOf("<p class=\"text\">") + 16);
                string text2 = Regex.Split(text, "</p>")[0];

                return ReplaceString(text2);
            }
            catch 
            { 
                return "null"; 
            }
        }
Nahlásit jako SPAM
IP: 89.190.90.–
velurex0
Stálý člen
17. 4. 2013   #2
-
0
-

V té metodě všechny instance nově vznikají a zase zanikají. Teoreticky by to mělo běžet při srovnatelné velikosti stránek pořád stejně. Co se s tím vráceným řetězcem děje pak? Není problém až tam?

Nahlásit jako SPAM
IP: 46.167.210.–
Mutagen0
Super člen
17. 4. 2013   #3
-
0
-

#2 velurex

        private string ReplaceString(string text)
        {
            string replaceString = text.Replace("<br />", Environment.NewLine).Replace(";\"", "").Replace("<", "[").Replace(">", "]").Replace("span style=\"color: ", "c:").Replace("/span", "/c").Replace("&lt;", "<").Replace("&gt;", ">");
            return replaceString;
        }

Tohle je jenom nahrazení nějakejch věcí ... Jinak tohle je ta funkce

        private void GetLamerDatabase()
        {

            for (int index = 1; index <= lamerMessagesCount; index++)
            {
                Messages lamerMessages = new Messages();
                lamerMessages.Message = GetSourceCode("http://www.lamer.cz/quote/" + index);
                lamerMessages.ID = index;
                lamerMessage.Add(lamerMessages);
                Invoke((MethodInvoker)delegate()
                {
                    LB_Hlasky.Items.Insert(0, "Hláška : " + index);
                    progressBar1.Value = index;
                });
            }
        }
Nahlásit jako SPAM
IP: 89.190.90.–
RomanZ
~ Anonymní uživatel
272 příspěvků
18. 4. 2013   #4
-
0
-

Ahoj, já v tom kódu takhle na první pohled nic závadného nevidím.

V podobných situacích postupuji tak, že si do metody přidám stopky a loguji čas zpracování. Pokud je čas zpracování metody v každém kroku delší než byl v předchozí, hledám ve svém kódu, jestli tam třeba někde nemám sčítání stringů místo StringBuilderu apod. - prostě nějakou prasárnu, která v malém objemu nevadí a ve velkém ano. Umístím stopky na více míst a najdu tak to místo, které za pomalost může.

Pokud je naopak čas zpracování v prvních x krocích přibližně stejný (rychlý) a po těch x krocích se to zlomí a začne to být pomalé, tak se začnu zajímat o paměť, cache a takové věci. Zkontroloval bych, jestli program nespotřebovává stále více paměti - ono tomu pak dojde RAM, začne swapovat na disk a to může být ten zlom ve výkonu. Případně nějaké cache, limity v počtu otevřených spojení apod.

Nahlásit jako SPAM
IP: 90.176.60.–
RomanZ
~ Anonymní uživatel
272 příspěvků
18. 4. 2013   #5
-
0
-

Mimochodem, co je to LB_Hlasky? Není to nějaký listbox nebo nějaká komponenta na formuláři? Pokud ano, zkus ten řádek zapoznámkovat a pustit to bez něj, jestli to bude pomalé i pak.

Nahlásit jako SPAM
IP: 90.176.60.–
ingiraxo+15
Grafoman
18. 4. 2013   #6
-
0
-

A napadlo tě taky, že problém nemusí být na tvé straně, ale na strane serveru? Třeba ma limit v počtech dotazů nebo omezení mezi dotazy.. třeba to stahování vnímá jako flood, zkus nastavit delay mezi stahováním stránek třeba na 200-500ms

EDIT: tohle se mi stalo, když jsem stahoval asi 600 filmů (informací o fillmech) z csfd.cz, po nějakých 200 dotazech to začlo jet pomalu a potom jsem mel dokonce blokovaní na serveru asi 20min i přes prohlížeč.... jediná možnost bude razantně snížit rychlost stahování, aby si to nebralo jako flood

EDIT 2: teď mě napadlo, že zkusit dynamicky měnit user agenta (celou GET hlavičku), aby si to myslelo, že to jě několik lidí přes prohlížeč a ne jeden a ten samej (může být důvod toho zpomalení)

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
KIIV
~ Moderátor
+43
God of flame
18. 4. 2013   #7
-
0
-

ja kdyz naposledy zazil razantni zpomaleni scriptu v bejvaly praci (posilani sms pres soap), tak to bylo zpusobeno neuvolnovanim soap clienta z pameti (vytvarel se ve funkci, ale z nejakyho duvodu se garbage collector nechytl)  ale nebylo to v C# ...   dalo se to snadno zjistit tim ze furt roste zabrana pamet...

A kdyz se vyhnes stalemu znovuvytvareni toho downloaderu, tak doporucuju drzet keepalive ..

Pak regularni vyrazy nejsou dobrej napad.. ne kdyz hledas prvni </p> ...

Mozna by bylo rychlejsi pouzit wget a pak si jen zpracovat stranky z disku

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Mutagen0
Super člen
18. 4. 2013   #8
-
0
-

#4 RomanZ
Jako ono to je rychlý, to ano, ale pak prostě 1000 požadavků a výrazně se to zpomalí, že třeba za 10 sec to sebere 20 - 30 prispevku, ale ze začátku to jelo třeba 5sec 30příspěvků neli víc. Ale možná to bdue jak tu psal ingiraxo
že server mě začně omezovat v případě moc častých požadavků. Dneska mě napadlo si to rozdělit třeba do 10 vláken po 6,5k příspěvků, takže se na to zkusím vrhnout a uvidíme zda to bude lepší. Tak jako nejde mi o to, aby to stahovalo furt znova, ale prostě si chci vytvořit databázi (jen jednou) a pak si to uložit třeba do xml souboru. A jo, je to listbox kde se mi zobrazuje počet hlášek, a když to zakomentuju tak nevím jak rychle mi to hlavně jede.

A když už jsi u toho, jak bych měl kdyžtak vyčistit RAM pamět od toho? Ale co sem tak koukal, tak využívá maximálně od 100kB - po pár mB což není tak hrozný.

#6 ingiraxo
Kdybych tam měl takovouhle pauzu mezitím, tak stahování někdě 65k stránek by se strašně prodloužilo až o hodiny si myslím. Když už jsi to nakousl tak jak můžu měnit tu GET hlavičku?

#7 KIIV
Tak mi porad jak bych mohl držet ten stav (keepalive), protože absolutně nevím.

Jinak ten regulerní výraz používám, protože nechci ukládat celou stránku, ale jen část (pokud máš něco rychlejšího tak mě poraď jak)

Jinak s tím wgetem neumím, a příjde mi to trošku zdlouhavější. Ale jako možnost to je též.

Nahlásit jako SPAM
IP: 89.190.90.–
Řešení
ingiraxo+15
Grafoman
18. 4. 2013   #9
-
0
-
Vyřešeno Nejlepší odpověď

#8 Mutagen
čistit pamět není potřeba, stream se uvolňuje/zavírá po stažení stránky a tu hlavičku změníš přes Headers

req.Headers.Add("hlavicka");

můžeš zkusit generovat hlavičky třeba z pole, aby vždy byla jiná (třeba z 5 hlaviček) + nastavit timeout na 200ms
s více vláknama si moc nepomůžeš, efekt bude stejnej když snižíš timeout místo více vláken

WebRequest nic jako keepAlive neumí, ono stajne stahuješ jednotlivý stránky, takže se vždy musí ukončit stream.. maximálně použít WebClient a ten nechat zapnutej pro všechny stránky, ale to si myslim, že nepomůže, páč stejně musíš vytvářet připojení pro každou stránky zvlášť

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
RomanZ
~ Anonymní uživatel
272 příspěvků
18. 4. 2013   #10
-
0
-

O čištění paměti mi nešlo. Šlo mi o to zjistit, jestli ten program při běhu neustále bobtná. Pokud ano, je třeba zjistit, kde Ti ta paměť teče a tu díru ucpat.

A dále: než začneš cokoliv optimalizovat, napřed zjisti, co Ti to brzdí. Teprve až bude jasné, co je špatně, můžeš to zlepšovat. Proto jsem navrhoval to měření se stopkami (System.Diagnostics.Stopwatch) a logovat (znáš log4net?), abys zjistil, kde je úzké hrdlo. Koukání na listbox Ti dává jen přibližnou a bohužel hodně zkreslenou představu. A nezjistíš z toho, která část kódu je pomalá.

No a pokud v rámci zpracování strkáš tisíce položek do listboxu, tak s vysokou pravděpodobností je pomalé jeho vykreslování.  Vyzkoušej, jak se používá Stopwatch a potom změř čas na načtení nějakého množství položek s tím listboxem a pak zkus ten listbox vyřadit a změřit čas načtení stejného množství položek bez něj. Pokud to bude výrazně lepší, tak si ty data v průběhu zpracování strkej do nějaké kolekce a do listboxu je přiřaď až nakonec, ne v cyklu. Před naplněním listboxu na něm zakaž překreslování a po naplnění ho zase zapni.

Nahlásit jako SPAM
IP: 90.176.60.–
ingiraxo+15
Grafoman
18. 4. 2013   #11
-
0
-

tohle je na 99.9% na straně serveru, i kdyby celý stránky ukládal jen do pole a nikde nevypisoval, tak se to zpomalovat bude stejně, já tohle vyřešil vetším timeoutem, sice se doba prodloužila, ale aspoň to jelo stále stejně "rychle"

co se týče tý paměti, tak i kdyby tam někde měl mem leak, tak .NET je paradoxně plnej mem leaků, proto existuje GC (ovšem to neznamená, že je budeme vytvářet schválně), jen tím chci říct, že tohle nemá vliv na rychlost stahování stránky ;-) (pokud stahuje async neco z jinýho vlákna)

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
RomanZ
~ Anonymní uživatel
272 příspěvků
18. 4. 2013   #12
-
0
-

#11 ingiraxo
Na memory leak v pravém slova smyslu jsem nemyslel. Z těch kousků kódu, co tu jsou, není patrné, co se s těmi načtenými daty děje. Pokud je hromadí v paměti, tak jeho program bude bobtnat a mne zajímalo, jestli nebobtná nade všechny meze, až by nestačila RAM a šlo to do swapu.

Co se týče GC, tak ten sbírá jen objekty, na které už neexistuje reference. Takže ono se sice tvrdí, že v .NET nejde napsat memory leak (a on asi nějak jednoduše nejde), ale ve skutečnosti stačí někde zapomenout odmazat reference na objekty a paměť se pak spotřebovává taky (není to sice pravý leak, ale GC to neuklidí). Měl jsem tedy na mysli spíš nějakou nevhodnou práci s event handlery nebo tak něco.

Zajímavé počtení třeba tady:

http://blogs.msdn.com/b/davidklinems/archive/2005/11/16/493580.aspx

Nahlásit jako SPAM
IP: 90.176.60.–
Mutagen0
Super člen
18. 4. 2013   #13
-
0
-

#11 ingiraxo
Hele a když už jsi u toho, tak jak by měla vypadat taková hlavička? Nako formát té hlavičky?

Nahlásit jako SPAM
IP: 89.190.90.–
ingiraxo+15
Grafoman
18. 4. 2013   #14
-
0
-

#12 RomanZ
noo, jestli myslíš ten zdroják co tady napsal, tak ten je v pořádku (nikde nic neuniká), tohle bych vůbec neřešil

#13 Mutagen
co třeba zkusit google? první link http://www.user-agents.org/

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Mutagen0
Super člen
18. 4. 2013   #15
-
0
-

#14 ingiraxo
Ano opravdu s více hlavičkama to jede jak blázen! Ještě rychlejc než bez hlavičky ... za 10sec v pruměru získám kolem 80 requestu neli víc. Opravdu děkuju :)

Nahlásit jako SPAM
IP: 89.190.90.–
Mutagen0
Super člen
18. 4. 2013   #16
-
0
-

#14 ingiraxo
Jenom takovej problem tady je ... Je to možná mrtě rychlý, ale nestahuje mě to stránku ... Pri mým kodu to vrací string "null" ...

Nahlásit jako SPAM
IP: 89.190.90.–
Mutagen0
Super člen
18. 4. 2013   #17
-
0
-

Kod je zde ...

private string GetSourceCode(string url)
        {
            string[] Headers = new string[12];
            Headers[0] = "Mozilla/3.0 (compatible; Linkman)";
            Headers[1] = "Mozilla/3.0 (compatible; PerMan Surfer 3.0; Win95)";
            Headers[2] = "Mozilla/3.0 (compatible; REL Software Web Link Validator 2.x)";
            Headers[3] = "Mozilla/3.0 (compatible; Web Link Validator 2.x)Web Link Validator http://www.relsoftware.com/ link validation software";
            Headers[4] = "Mozilla/4.0 (compatible; BOTW Spider; +http://botw.org)";
            Headers[5] = "Mozilla/4.0 (compatible; Check&Get 3.0; Windows NT)";
            Headers[6] = "Mozilla/4.0 (compatible; DepSpid/5.0x; +http://about.depspid.net)";
            Headers[7] = "Mozilla/4.0 (compatible; IE-Favorites-Check-0.5)";
            Headers[8] = "Mozilla/4.0 (compatible; KeepNI web site monitor)";
            Headers[9] = "Mozilla/4.0 (compatible; Link Utility; http://net-promoter.com)";
            Headers[10] = "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME; Link Checker 2.x.xx http://www.kyosoft.com)";
            Headers[11] = "Mozilla/4.0 (compatible; MSIE 5.5; AOL 4.0; Windows 98; GoBeez (www.gobeez.com))";

            try
            {
                Random rand = new Random();
                int number = rand.Next(0, Headers.Length);

                WebRequest req = HttpWebRequest.Create(url);
                req.Method = "GET";
                req.Headers.Add(Headers[number]);

                string source;
                using (StreamReader reader = new StreamReader(req.GetResponse().GetResponseStream()))
                {
                    source = reader.ReadToEnd();
                }
                string text = source.Substring(source.IndexOf("<p class=\"text\">") + 16);
                string text2 = Regex.Split(text, "</p>")[0];

                return ReplaceString(text2);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return "null"; 
            }
        }
Nahlásit jako SPAM
IP: 89.190.90.–
KIIV
~ Moderátor
+43
God of flame
18. 4. 2013   #18
-
0
-

nemel bys ten header pridat celej?   Jako "User-Agent: ...." ?

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Mutagen0
Super člen
18. 4. 2013   #19
-
0
-

#18 KIIV
Nevím jak má přesně vypadat hlavička vid.

Nahlásit jako SPAM
IP: 89.190.90.–
KIIV
~ Moderátor
+43
God of flame
Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
guest
~ Anonymní uživatel
24 příspěvků
28. 4. 2013   #21
-
-1
-
Mimo téma

To co delas je pekna prasarna... zamysli se nad tim, muzes zahltit cely server. Zkus si uvedomit, jak moc bys byl reda kdyby tohle nekdo delal tobe.

Nahlásit jako SPAM
IP: 89.177.116.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 18 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý