ZaΦßteΦnφk

PokroΦil²

Profesionßl

Optimalizace /3. dφl

Cφl: RychlejÜφ a efektivn∞jÜφ programov² k≤d

 

Budete pot°ebovat p°ibli₧n∞ 70 minut

OperaΦnφ systΘm pou₧it² v p°φsp∞vku: Windows 2000

V²vojovΘ nßstroje: Visual Basic 6.0 SP5

 

 

Milφ Φtenß°i,

 

dneÜnφm dφlem zakonΦφme problematiku optimalizace zdrojovΘho k≤du ve Visual Basicu 6. V p°edeÜl²ch Φßstech jste se dov∞d∞li, jakΘ mo₧nosti optimalizaΦnφch nastavenφ vßm VB 6 nabφzφ a rovn∞₧ tak vφte, jak zm∞°it rychlost provßd∞nφ jistΘho ·seku programovΘho k≤du. T°etφ a zßv∞reΦnφ Φßst bude v∞novßna praktick²m ukßzkßm optimalizace k≤du. Budeme zkoumat, jak² dopad na v²kon k≤du budou mφt nßmi pou₧itΘ techniky optimalizace.

 

Obsah

Experiment Φ. 1: Zßhady pou₧itφ datov²ch typ∙

M∞°enφ tempa programovΘho k≤du p°i pou₧itφ prom∞nn²ch r∙zn²ch datov²ch typ∙

Experiment Φ. 2: KritickΘ omezenφ rychlosti prßce ovlßdacφch prvk∙

 

 

Experiment Φ. 1: Zßhady pou₧itφ datov²ch typ∙

 

Pokud mßme mluvit o komplexnφ optimalizaci programovΘho k≤du, musφme vychßzet ze zßkladnφ programovacφ entity, kterou je prom∞nnß. Kdyby existoval jenom jeden datov² typ, kter² by byl pou₧iteln² na vÜechny programovacφ operace, bylo by mo₧nΘ do n∞j ulo₧it tak°ka cokoliv a jeho pou₧itφ by nijak neovlivnilo rychlost provßd∞nφ programov²ch instrukcφ, nebyla by otßzka pou₧itφ vhodn²ch datov²ch typ∙ prom∞nn²ch ani zdaleka tak d∙le₧itß. I kdy₧ je p°edstava ideßlnφho datovΘho typu jakkoliv lßkavß, p°i praktick²ch pokusech zßhy zjistφme, ₧e o n∞jakΘm äideßlnφmô stavu si m∙₧eme nechat jenom zdßt.

 

Visual Basic 6 poskytuje znaΦnΘ mno₧stvφ rozliΦn²ch datov²ch typ∙, kterΘ dovedou uchovßvat r∙znΘ hodnoty. ProblΘmem pochopiteln∞ nenφ deklarace prom∞nnΘ k²₧enΘho datovΘho typu. Kdepak. Daleko slo₧it∞jÜφ je vypracovßnφ si jistΘ intuice, kterß vßm bude °φkat, jak² nejvhodn∞jÜφ datov² typ byste m∞li zvolit v zßvislosti od °eÜenΘho problΘmu. Bohu₧el otßzka optimßlnφ volby datovΘho typu pro danou operaci je n∞kdy natolik slo₧itß, ₧e ani pokroΦilφ programßto°i Φasto nev∞dφ, zdali ta jejich volba byla opravdu optimßlnφ.

 

Prvnφ dobrß rada znφ: V ka₧dΘm p°φpad∞ deklarujte prom∞nnΘ pomocφ klφΦovΘho slova As a specifikace vhodnΘho datovΘho typu. Visual Basic sice umo₧≥uje deklaraci prom∞nn²ch bez udßnφ platnΘho datovΘho typu, ovÜem v tomto p°φpad∞ vφce ztratφte, ne₧li zφskßte. Jestli₧e p°i deklaraci prom∞nnΘ nebudete specifikovat jejφ datov² typ, bude ji automaticky p°i°azen datov² typ Variant. Typ Variant je jedin² typ, kter² m∙₧e uchovßvat hodnoty jin²ch datov²ch typ∙. Na druhΘ stran∞ je to takΘ ä₧rout pam∞tiô, proto₧e ka₧dß instance prom∞nnΘ tohoto datovΘho typu zabere 128 bit∙ (16 bajt∙) pam∞ti.

 

GenerickΘ prom∞nnΘ, co₧ je nßzev pro prom∞nnΘ, kterΘ nemajφ explicitn∞ determinovßn specifick² datov² typ, jsou ovÜem v mnoha p°φpadech u₧iteΦnΘ (nap°φklad, kdy₧ budete chtφt vytvo°it instanci jistΘ t°φdy za b∞hu programu, no v dob∞ psanφ k≤du nebudete znßt specifick² typ t°φdy, pou₧itφ generickΘ prom∞nnΘ m∙₧e vy°eÜit vßÜ programßtorsk² problΘm). Naopak, v₧dy, kdy₧ je to mo₧nΘ, m∞li byste explicitn∞ urΦit specifick² typ prom∞nnΘ. Budete-li chtφt spustit instanci aplikace Microsoft Word a p°idat do nφ jeden dokument, budete deklarovat objektovou prom∞nnou pomocφ specifickΘho typu t°φdy Word.Application:

 

Dim Objektovß_Prom∞nnß As Word.Application

Set Objektovß_Prom∞nnß = New Word.Application

 

With Objektovß_Prom∞nnß

ááá .Documents.Add

ááá .Visible = True

End With

 

Pou₧itφ specifickΘho typu objektovΘ prom∞nnΘ v uvedenΘm p°φklad∞ demonstruje takΘ mechanizmus, jemu₧ se °φkß early-binding, neboli ΦasnΘ vßzßnφ (vznikl²m instancφm t°φdy se pak °φkß objekty s Φasnou vazbou). Pou₧itφ ΦasnΘho vßzßnφ je velmi u₧iteΦnΘ takΘ pro vßs, jako programßtory. Ve chvφli, kdy uvedete specifick² typ objektovΘ prom∞nnΘ, bude Visual Basic v∞d∞t, jakΘ metody a vlastnosti danß t°φda obsahuje a tyto vßm zp°φstupnφ prost°ednictvφm technologie IntelliSense p°i pou₧itφ teΦkovΘho operßtoru.

 

Aby uveden² fragment programovΘho k≤du pracoval spolehliv∞, musφte do vaÜφ aplikace zavΘst odkaz na objektovΘ knihovny: Microsoft Office 10.0 Object Library a Microsoft Word 10.0 Object Library. V IDE Visual Basicu vyberte nabφdku Project a klepn∞te na polo₧ku References. V seznamu pak vyhledejte uvedenΘ knihovny a zahr≥te je do projektu.á

 

Poznßmka: ObjektovΘ knihovny verze 10.0 p°inßle₧φ softwaru Microsoft Office XP (2002). Pokud mßte na svΘm poΦφtaΦi nainstalovanou jinou verzi, pou₧ijte samoz°ejm∞ tu vaÜφ.áá

 

V nßsledujφcφ sekci se podφvßme na to, jak² vliv na v²kon provßd∞nφ programovΘho cyklu bude mφt zvolen² datov² typ p°edm∞tn²ch prom∞nn²ch.

 

 

M∞°enφ tempa programovΘho k≤du p°i pou₧itφ

prom∞nn²ch r∙zn²ch datov²ch typ∙

 

Nynφ si p°edstavφme obsahy dvou udßlostnφch procedur dvou tlaΦφtek. V obou p°φpadech budeme provßd∞t matematickΘ v²poΦty, ovÜem poka₧dΘ s jinou sadou datov²ch typ∙ prom∞nn²ch. V udßlostnφ procedu°e Click prvnφho tlaΦφtka budou deklarovßny prom∞nnΘ datovΘho typu Long:

 

Dim lng╚φtaΦ As Long, x1 As Long, x2 As Long

Dim zaΦßtek As Single

 

zaΦßtek = Timer()

 

For lng╚φtaΦ = 1 To 200000

Randomize

x1 = Rnd() * 10000 + Rnd() * 500

x2 = x1 ^ 2

Next lng╚φtaΦ

 

MsgBox "Cyklus s prom∞nn²mi typu Long byl vykonßn za " & _

Format(Timer - zaΦßtek, "0.000")

 

V udßlostnφ procedu°e Click druhΘho tlaΦφtka budou zase pou₧ity prom∞nnΘ datovΘho typu Variant:

 

Dim var╚φtaΦ As Variant, x1 As Variant, x2 As Variant

Dim zaΦßtek As Single

 

zaΦßtek = Timer()

 

For var╚φtaΦ = 1 To 200000

Randomize

x1 = Rnd() * 10000 + Rnd() * 500

x2 = x1 ^ 2

Next var╚φtaΦ

 

MsgBox "Cyklus s prom∞nn²mi typu Variant byl vykonßn za " & _

Format(Timer - zaΦßtek, "0.000")

 

Jednotlivß m∞°enφ jsou uvedena v tab. 1.

 

Tab. 1

 

╚φslo m∞°enφ

Prom∞nnΘ datovΘho typu Long

Prom∞nnΘ datovΘho typu Variant

1.

0, 418 s

0, 484 s

2.

0, 418 s

0, 480 s

3.

0, 422 s

0, 520 s

Pr∙m∞r

0, 419 s

0, 495 s

á

Po provedenφ test∙ m∙₧eme prohlßsit, ₧e k≤d s prom∞nn²mi datovΘho typu Long byl proveden v pr∙m∞ru o p°ibli₧n∞ 76 tisφcin vte°iny rychleji ve srovnßnφ se sv²m ävariantnφmô prot∞jÜkem (obr. 1).

 

 

Obr. 1 û P∙sobenφ r∙zn²ch datov²ch typ∙ na rychlost provßd∞nφ programovΘho k≤du

 

PokraΦujme aktivacφ pokroΦil²ch optimalizaΦnφch nastavenφ, kterΘ nßm nabφzφ samotn² Visual Basic. Postupujte takto:

 

  1. Vyberte nabφdku File a klepn∞te na polo₧ku Make JmΘno_Aplikace.exe.
  2. V okn∞ Make Project klikn∞te na tlaΦφtko Options.
  3. V dialogovΘm okn∞ Project Properties aktivujte zßlo₧ku Compile.
  4. Zde se ujist∞te, ₧e jsou vybrßny volby Compile to Native Code a Optimize for Fast Code.
  5. Klepn∞te na tlaΦφtko Advanced Optimizations a v stejnojmennΘm dialogovΘm okn∞ zatrhn∞te vÜechny polo₧ky pokroΦil²ch optimalizaΦnφch nastavenφ.
  6. Vygenerujte samostatn∞ spustiteln² (.EXE) soubor.

 

Po op∞tovn∞ proveden²ch testech jsem zφskal novΘ ·daje, kterΘ jsou zobrazeny v tab. 2.

 

Tab. 2

M∞°enφ v²konu programovΘho k≤du s pou₧itφm pokroΦil²ch optimalizaΦnφch nastavenφ

 

╚φslo m∞°enφ

Prom∞nnΘ datovΘho typu Long

Prom∞nnΘ datovΘho typu Variant

1.

0, 391 s

0, 449 s

2.

0, 391 s

0, 449 s

3.

0, 402 s

0, 441 s

Pr∙m∞r

0, 395 s

0, 446 s

 

Z tabulky je jasn∞ patrnΘ, ₧e exekuce programovΘho k≤du obou udßlostnφch procedur byla op∞t rychlejÜφ. áV²kon programovΘho k≤du s prom∞nn²mi datovΘho typu Long byl lepÜφ v pr∙m∞ru o Φty°iadvacet tisφcin vte°iny. Zrychlila se rovn∞₧ exekuce programovΘho k≤du s prom∞nn²mi datovΘho typu Variant, a to v pr∙m∞ru o 49 tisφcin vte°iny. Ze vzßjemnΘho rychlostnφho porovnßnφ udßlostnφch procedur op∞t vφt∞zφ ta, v t∞le kterΘ jsou deklarovßny prom∞nnΘ datovΘho typu Long. V²konnostnφ nßskok Φinφ p°ibli₧n∞ 51 tisφcin sekundy (obr. 2).

 

 

Obr. 2 û V∞tÜφ rychlost exekuce k≤du pomocφ aktivace pokroΦil²ch optimalizaΦnφch nastavenφ

 

Jak je vid∞t, zapnutφ optimalizaΦnφch voleb zabezpeΦilo jeÜt∞ dalÜφ nav²Üenφ v²konu programovΘho k≤du. Komplexnφ ukßzku porovnßnφ rychlosti k≤du bez a s pou₧itφm optimalizaΦnφch nastavenφ m∙₧ete vid∞t na obr. 3.

 

 

Obr. 3 û Ukßzka vlivu optimalizace na rychlost provßd∞nΘho k≤du

 

 

Experiment Φ. 2: KritickΘ omezenφ rychlosti prßce ovlßdacφch prvk∙

 

Pokud pracujete Φasto s mnoha ovlßdacφmi prvky, mo₧nß, ₧e jste ji₧ narazili na problΘm, kterΘmu se v programßtorskΘ hant²rce °φkß äkritickΘ omezenφ rychlostiô. Ka₧d² ovlßdacφ prvek je samostatnou entitou, kterß je zalo₧ena na zßkladnφch principech objektov∞ orientovanΘho programovßnφ. Jednφm z princip∙ je takΘ zapouzd°enφ programovΘho k≤du ovlßdacφho prvku, kter² nenφ v ₧ßdnΘm p°φpad∞ p°φstupn² svΘmu okolφ (klientskΘ aplikaci). Na jednΘ stran∞ je existence zapouzd°enφ jasnou v²hodou pro autora ovlßdacφho prvku, proto₧e ten mß jistotu, ₧e k samotnΘmu jßdru prvku se nikdo äzvenkuô nedostane. Na druhΘ stran∞ ovÜem vyvstßvß otßzka, jak dokonale zvlßdnul autor optimalizaci programovΘho k≤du svΘho ovlßdacφho prvku. Je prßce s ovlßdacφm prvkem flexibilnφ nebo ne? A prßv∞ te∩ se dostßvßme k vysv∞tlenφ ji₧ p°edest°enΘho syndromu kritickΘ omezenφ rychlosti ze strany ovlßdacφho prvku. Jakmile jednou v programovΘm k≤du dovolφte ovlßdacφmu prvku, aby p°evzal chod programu do sv²ch rukou, nemßte ₧ßdnou Üanci na jakoukoliv optimalizaci jeho Φinnosti. Uve∩me si mal² p°φklad:

 

  1. Ve VB 6 zalo₧te nov² projekt typu Standard EXE.
  2. Na formulß° p°idejte instanci ovlßdacφho prvku CommandButton a takΘ instanci ovlßdacφho prvku ListBox.
  3. Do udßlostnφ procedury Click tlaΦφtka p°idejte tento k≤d:

 

Dim x As Integer, Φas As Single

 

Φas = Timer()

 

For x = 1 To 30000

List1.AddItem x

Next x

 

MsgBox "Napln∞nφ seznamu trvalo " & Format(Timer - Φas, "0.000")

 

Pov∞zme, ₧e procesor bude pot°ebovat p°ibli₧n∞ jednu sekundu na to, aby do seznamu p°idal 30 tisφc Φφsel. I kdybyste zapnuli vÜechna optimalizaΦnφ nastavenφ, nedosßhli byste ₧ßdnΘho signifikantnφho nßr∙stu rychlosti k≤du. Tento okam₧ik je oznaΦen jako kritickΘ omezenφ rychlosti ze strany ovlßdacφho prvku. Hlavnφm ävinnφkemô je metoda AddItem ovlßdacφho prvku ListBox. Jak jsme si ji₧ pov∞d∞li, kdy₧ p°edßme °φzenφ k≤du do rukou metody AddItem, nem∙₧eme dßle optimalizovat rychlost p°idßvßnφ polo₧ek do seznamu, proto₧e touto kompetencφ disponuje jenom samotn² ovlßdacφ prvek ListBox. á

 

AΦkoliv nem∙₧eme v tomto p°φpad∞ zabezpeΦit zv²Üenφ absolutnφ (resp. objektivnφ) rychlosti programovΘho k≤du, m∙₧eme b∞hem doby prßce metody AddItem zam∞stnat u₧ivatelovu pozornost a informovat ho o tom, ₧e aplikace prßv∞ dokonΦuje jeden ze sv²ch pracovnφch ·kol∙. Na rozpt²lenφ u₧ivatele se v²born∞ hodφ ovlßdacφ prvek ProgressBar (ukazatel pr∙b∞hu).

 

Instanci ovlßdacφho prvku p°idßte na formulß° nßsledovn∞:

 

  1. Vyberte nabφdku Project a klepn∞te na polo₧ku Components.
  2. Ujist∞te se, ₧e je vybrßna zßlo₧ka Controls a v seznamu vyhledejte polo₧ku Microsoft Windows Common Controls 6.0 (SP4).
  3. Zatrhn∞te vybranou polo₧ku a aktivujte tlaΦφtko OK. Do soupravy nßstroj∙ (ToolBox) se p°idß n∞kolik ovlßdacφch prvk∙, mezi jin²mi takΘ ProgressBar.
  4. Poklepejte na ikonu ovlßdacφho prvku, Φφm₧ p°idßte jeho instanci na formulß°.
  5. Vlastnost Align prvku ProgressBar upravte na hodnotu 2 û vbAlignBottom. Tφm p°ikß₧ete, aby byl ukazatel pr∙b∞hu umφst∞n² na spodnφ stran∞ formulß°e.á Podle pot°eby m∙₧ete rovn∞₧ upravit velikost vlo₧enΘ instance ovlßdacφho prvku ProgressBar.

 

Zdrojov² k≤d v procedu°e CommandButton1_Click modifikujte podle vzoru, jen₧ je zobrazen nφ₧e:

 

Dim x As Integer, Φas As Single

 

Φas = Timer()

 

Form1.MousePointer = vbHourglass

DoEvents

 

Dim h As Object

Set h = ProgressBar1

 

With h

ááá .Min = 1

ááá .Max = 30000

End With

 

For x = 1 To 30000

ááá List1.AddItem x

ááá h.Value = x

Next x

 

h.Value = h.Min

 

Form1.MousePointer = vbDefault

 

P°i studiu k≤du si m∙₧ete vÜimnout n∞kolik zajφmav²ch programovacφch prvk∙:

 

 

╚as, kter² bude pot°ebn² pro vykreslenφ a aktualizaci ukazatele pr∙b∞hu bude, p°es vÜechny pokusy o optimalizaci zdrojovΘho k≤du, o n∞co delÜφ, ne₧li p∙vodn∞ zjiÜt∞nß hodnota. Vskutku, takΘ ovlßdßnφ ovlßdacφho prvku ProgressBar n∞co stojφ. Pro dosa₧enφ optimßlnφho v²sledku je zapot°ebφ najφt rovnovßhu mezi objektivnφ a subjektivnφ rychlosti aplikace.

 

Jestli₧e chcete, m∙₧ete uvedenou situaci vy°eÜit jeÜt∞ jinak:

 

1.      Nemusφte pou₧φt ovlßdacφ prvek ProgressBar, ale jenom zm∞≥te kurzor myÜi na p°es²pacφ hodiny.

 

2.      Vytvo°te specißlnφ formulß°, kter² zobrazφte u₧ivateli b∞hem naΦφtßnφ polo₧ek do seznamu (aby byl formulß° °ßdn∞ p°ekreslen, po jeho zobrazenφ zavolejte funkci DoEvents). Formulß° bude u₧ivateli °φkat, ₧e aplikace prßv∞ provßdφ d∙le₧itou operaci, dokonΦenφ kterΘ si vy₧aduje dodateΦn² Φas. á

 

3.      NaΦφtejte polo₧ky do seznamu p°edem, nap°φklad p°i startu aplikace.

 

4.      Pokuste se naΦφst polo₧ky v menÜφch mno₧stvech. Tedy nebudete naΦφtat vÜech 30 tisφc polo₧ek najednou, ale vytvo°φte menÜφ skupiny polo₧ek (t°eba po p∞ti tisφcφch), kterΘ potΘ naΦtete rychleji.

 

 

 

Jßn Hanßk