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