日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

VB編程基礎(chǔ)教程21–優(yōu)化 | 異次元軟件世界

 a_cheng 2009-10-21

VB編程基礎(chǔ)教程21–優(yōu)化

收藏到QQ書簽 [ 程序樂園 ]

優(yōu)化具有科學(xué)和藝術(shù)兩重含義。從科學(xué)角度看,優(yōu)化意指具體的優(yōu)化技術(shù);而從藝術(shù)角度看,優(yōu)化指的是確定在什么地方、什么時候需要優(yōu)化。由此,優(yōu)化可定義為“通過選擇和設(shè)計數(shù)據(jù)結(jié)構(gòu)、算法以及指令序列,來提高程序效率(更小、更快)的過程”。
有關(guān)優(yōu)化的一個普遍存在的誤解是,認(rèn)為只是在應(yīng)用程序開發(fā)周期的最后階段才進(jìn)行優(yōu)化。而實際上,為了創(chuàng)建真正優(yōu)化的應(yīng)用程序,就必須在開發(fā)時實行優(yōu)化。一般來說,優(yōu)化的過程為:仔細(xì)選擇算法,并在速度、大小等諸多限制因素間進(jìn)行權(quán)衡,初步估計應(yīng)用程序各個部分的速度和大小,再在以后的開發(fā)過程中檢驗上述假設(shè)。
優(yōu)化的第一步是確定優(yōu)化目標(biāo)。優(yōu)化可以從以下幾個方面進(jìn)行:
真實速度(應(yīng)用程序?qū)嶋H計算或操作的速度)。

顯示速度(應(yīng)用程序屏幕顯示的速度)。

感覺速度(應(yīng)用程序運(yùn)行時給人的感覺速度,它往往和顯示速度有關(guān),但并不總是和真實速度相關(guān))。

占用內(nèi)存的大小。

圖形大?。ㄟ@直接影響占用內(nèi)存的大小,而且工作在 microsoft windows 中時往往會產(chǎn)生其它影響)。
一般來說,不可能在幾個方面同時得到優(yōu)化。一個經(jīng)過大小優(yōu)化的應(yīng)用程序往往會降低其速度;相應(yīng)的,經(jīng)過速度優(yōu)化的應(yīng)用程序則會增加其大小。由此可見,實現(xiàn)不同目標(biāo)的優(yōu)化技術(shù)往往是相抵觸的。
值得注意的是,優(yōu)化并不總是完全有益的。加快或降低應(yīng)用程序的速度,可能導(dǎo)致維護(hù)或調(diào)試方面的困難;還有些優(yōu)化技術(shù)與結(jié)構(gòu)化的程序設(shè)計相矛盾,這在將來擴(kuò)充應(yīng)用程序的功能或把它嵌入其它程序時會產(chǎn)生麻煩。
在確定應(yīng)用程序優(yōu)化策略時,有三方面的問題值得考慮:優(yōu)化什么、在何處優(yōu)化及何時結(jié)束優(yōu)化。
優(yōu)化什么:理解實際問題
如果沒有明確的優(yōu)化目標(biāo),就會因為方向錯誤而浪費(fèi)大量的時間。優(yōu)化的目標(biāo)是為了滿足用戶的需求。例如,速度對于計算銷售稅的應(yīng)用程序來說就至關(guān)重要,而對于可以從 internet 上下載的應(yīng)用程序,則其大小倍受關(guān)注。所以,正確理解優(yōu)化所要解決的問題所在,是確定優(yōu)化策略的關(guān)鍵。
即使已經(jīng)確定了某一優(yōu)化目標(biāo),仍需在開發(fā)過程中全面考慮優(yōu)化。在編寫代碼時,一步一步地瀏覽代碼,仔細(xì)思考其實際發(fā)生的情況,則會幫助了解很多東西。例如,設(shè)置屬性會產(chǎn)生許多事件,而恰好這些事件過程中有大量的代碼,則無謂的設(shè)置屬性語句會導(dǎo)致程序執(zhí)行時的巨大延遲。有時優(yōu)化即便是針對大小的,仍然可以在不增加大小的前提下實現(xiàn)速度的優(yōu)化。
在何處優(yōu)化:事半功倍
絕大部分的開發(fā)者不可能對應(yīng)用程序的所有地方都進(jìn)行優(yōu)化。增加時間等于增加開發(fā)成本,所以有必要進(jìn)行“優(yōu)化預(yù)算”。哪些地方能夠花一些時間換取最大的投資回報呢?顯然,那些速度慢、代碼冗長的地方最需要優(yōu)化,把精力花在這樣的地方就會有事半功倍的效果。
例如,速度是主要目標(biāo),則循環(huán)體往往是開始優(yōu)化的好地方。一旦循環(huán)體內(nèi)的操作得到加快,則該優(yōu)化會被放大,倍數(shù)是循環(huán)體執(zhí)行的次數(shù)。對于有大量重復(fù)的循環(huán),減少循環(huán)體內(nèi)的一個字符串操作,結(jié)果就會有很大的不同。同樣的規(guī)律也可以應(yīng)用于經(jīng)常調(diào)用的子程序。
何時結(jié)束優(yōu)化:效果的衡量
有時一些東西并不值得優(yōu)化。例如,為了十幾個項目的排序而編寫一個精致的快速排序程序是沒有意義的。一種排序的方法是把項目加到排序列表框中,再把它們按排好的順序讀出來。如果項目的數(shù)量巨大,則該方法效率極低;但對于少量的項目,該方法與其它方法的效率一樣,而且代碼出奇地簡單(只是有點(diǎn)難解)。
在一些情況下,優(yōu)化純屬浪費(fèi)。如果應(yīng)用程序的運(yùn)行受到驅(qū)動器或網(wǎng)絡(luò)速度的限制,則對代碼的任何優(yōu)化都無助于速度的提高。此時,就應(yīng)設(shè)法減少因延遲而造成對用戶的影響:如利用進(jìn)度欄提示當(dāng)前應(yīng)用程序的運(yùn)行狀況,或利用高速緩存減小延遲,或放棄控制,這樣用戶在等待時可以運(yùn)行其它的應(yīng)用程序,等等。
詳細(xì)信息 請參閱“響應(yīng)鼠標(biāo)和鍵盤事件”中的“中斷后臺處理”



優(yōu)化代碼
除非應(yīng)用程序是用來產(chǎn)生分形圖形的,否則應(yīng)用程序看上去并不受限于代碼的實際處理速度。其它典型的因素,如顯示速度、網(wǎng)絡(luò)延遲或磁盤操作,才是應(yīng)用程序速度的限制因素。比如,導(dǎo)致窗體加載慢的原因,是窗體上控件和圖形的個數(shù)太多,而不是由于 form_load 事件中的代碼太慢。盡管如此,代碼本身的速度也可以成為限制應(yīng)用程序速度的瓶頸,特別是經(jīng)常調(diào)用到的例程。這種情況下,可采用以下的幾種技術(shù)來優(yōu)化應(yīng)用程序的真實速度。
避免使用 variant 變量。

使用 long integer 變量和整數(shù)運(yùn)算。

將常用的屬性緩存在變量中。

使用內(nèi)嵌過程替代過程調(diào)用。

盡可能使用常數(shù)。

用 byval 傳遞參數(shù),而不用 byref。

使用類型確定的可選參數(shù)。

利用集合的優(yōu)點(diǎn)。
即使您并不想優(yōu)化代碼的速度,這也有助于了解這些技術(shù)及其基本原則。而且,一旦養(yǎng)成選擇高效率算法作為代碼的習(xí)慣,就可以從總體上大大改善應(yīng)用程序的速度。
避免使用 variant 變量
variant 變量是 visual basic 中的缺省變量。這對于初學(xué)者以及處理速度不成問題的應(yīng)用程序來說,是非常方便的。然而,如果想優(yōu)化應(yīng)用程序的實際速度,就要避免使用 variant 變量。因為,運(yùn)行時 variant 將轉(zhuǎn)化為其它適當(dāng)?shù)臄?shù)據(jù)類型,那么直接采用其它簡單的數(shù)據(jù)類型,就會避免不必要的操作而加快應(yīng)用程序的速度。
避免使用 variant 變量的一種好辦法是使用 option explicit 語句,此時所有的變量都必須聲明。要使用“option explicit”,就要在“工具”菜單中啟動“選項”對話框,選擇“編輯器”選項卡,選定“要求變量聲明”復(fù)選框。
在聲明多個變量時要小心:如果沒有用 as type 子句,它們實際上被聲明為 variant 變量。在下面的例子中,x 和 y 是 variant 變量:
dim x, y, z as long
重寫上面的語句,則三個變量為 long 變量:
dim x as long, y as long, z as long
詳細(xì)信息 關(guān)于 visual basic 數(shù)據(jù)類型的詳細(xì)信息,請參閱“編程基礎(chǔ)”中的“數(shù)據(jù)類型”。
使用 long 整型變量和整數(shù)運(yùn)算
算術(shù)運(yùn)算中要避免使用 currency、single 和 double 變量;并盡量使用 long 整型變量,尤其在循環(huán)體中。因為 long 整數(shù)是 32 位 cpu 的本機(jī)數(shù)據(jù)類型,所以其操作非常快;如果無法使用 long 變量,就要盡量使用 integer 或 byte 數(shù)據(jù)類型。很多時候,即使在要求使用浮點(diǎn)數(shù)的情況下,也可以使用 long 整數(shù)。例如,在窗體和圖形控件的 scalemode 屬性設(shè)置為緹或象素時,就可以在控件和圖形方法中使用 long 整型變量表示大小和位置。
進(jìn)行除法運(yùn)算時,如果不需要小數(shù)部分,就可以使用整數(shù)除法運(yùn)算符 (/)。由于浮點(diǎn)運(yùn)算需要轉(zhuǎn)移到協(xié)處理器上進(jìn)行,而整數(shù)運(yùn)算并不需要,所以整數(shù)運(yùn)算總是比浮點(diǎn)運(yùn)算快。如果確實需要做小數(shù)運(yùn)算,則 double 數(shù)據(jù)類型比 currency 數(shù)據(jù)類型快。
下表把各種數(shù)值數(shù)據(jù)類型按運(yùn)算速度順序列出。
數(shù)值數(shù)據(jù)類型 速度
long 最快
integer .
byte .
single .
double .
currency 最慢

將常用的屬性緩存在變量中
變量的訪問和設(shè)置速度比屬性快。如果經(jīng)常用到某一屬性的值(如在循環(huán)體中),可以在循環(huán)體外把該屬性值賦給某一變量,以后用該變量替代該屬性,這樣就能夠提高代碼的速度。一般來說,變量的處理速度比同類型的屬性處理速度快 10 到 20 倍。
除非知道屬性已經(jīng)改變,否則在過程中就無需再次讀取該屬性值??梢园褜傩灾蒂x予某一變量,然后在以后的代碼中使用該變量。例如,象這樣的代碼就非常慢:
for i = 0 to 10
   picicon(i).left = picpallete.left
next i
下面改寫的代碼就要快得多:
picleft = picpallete.left
for i = 0 to 10
      picicon(i).left = picleft
next i
同樣地,像這樣的代碼 . . .
do until eof(f)
   line input #f, nextline
   text1.text = text1.text + nextline
loop
. . . 比下面的代碼慢得多:
do until eof(f)
   line input #f, nextline
   buffervar = buffervar + nextline
loop
text1.text = buffervar
然而,下面的代碼完成了相同的功能,而且還要快:
   text1.text = input(f, lof(f))
如上述,幾種方法都實現(xiàn)了同樣的任務(wù);同時,最好的算法也是最優(yōu)的。
同樣的技術(shù)可用于處理函數(shù)的返回值。緩存函數(shù)的返回值,避免經(jīng)常調(diào)用運(yùn)行時的動態(tài)鏈接庫 (dll),msvbvm60.dll。
使用內(nèi)嵌過程替代過程調(diào)用
采用過程調(diào)用使代碼更具有模塊化的風(fēng)格,但模塊調(diào)用總是增加額外的操作和處理時間。如果循環(huán)體中多次調(diào)用某一過程,就可以直接把該過程寫到循環(huán)體中去,以消除過程調(diào)用時的額外負(fù)擔(dān)。但另一方面,直接把某一過程寫到好幾個循環(huán)體中時,重復(fù)的代碼無疑要增加應(yīng)用程序的大??;同時,在更改程序時,有可能忘記更改這些重復(fù)的代碼,這就增加了出錯的機(jī)會。
盡可能使用常數(shù)
使用常數(shù)可以加快應(yīng)用程序的運(yùn)行,增強(qiáng)代碼的可讀性,而且易于維護(hù)。如果代碼中的字符串或數(shù)字是不變的,則可把它們聲明為常數(shù)。常數(shù)在編譯時只處理一次,將適當(dāng)?shù)闹祵戇M(jìn)代碼;而變量在每次運(yùn)行應(yīng)用程序時都要讀取當(dāng)前值。
盡量使用對象瀏覽器中列舉的內(nèi)部常數(shù),而不要自己去創(chuàng)建。不要擔(dān)心應(yīng)用程序中引用的模塊包含多余的常數(shù);多余的常數(shù)在形成 .exe 文件時被刪除。
用 byval 傳遞參數(shù),而不用 byref
編寫含參數(shù)的 sub 或 function 過程時,按值 (byval) 傳遞參數(shù)比按地址 (byref) 快。盡管 visual basic 中參數(shù)傳遞的缺省方式是按地址的 (byref) ,但實際上需要改變參數(shù)值的過程極少。如果過程中不需改變參數(shù)的值,就可以按值 (byval) 來傳遞,舉例說明如下:
private sub dosomething(byval strname as string, _
byval intage as integer)
使用類型確定的可選參數(shù)
使用 visual basic 5.0 中類型確定的可選參數(shù),可以提高 sub 或 function 的調(diào)用速度。visual basic 以前版本中的可選參數(shù)只能是 variant 的。如果過程是按值傳遞參數(shù)的,正如下面的例子,16 個字節(jié)的 variant 變量保存在堆棧中。
private sub dosomething(byval strname as string, _
optional byval vntage as variant, _
optional byval vntweight as variant)
使用類型確定的可選參數(shù),每次調(diào)用時占用的堆??臻g較少,而且傳遞到內(nèi)存中的數(shù)據(jù)也較少:
private sub dosomething(byval strname as string, _
optional byval intage as integer, _
optional byval intweight as integer)
類型確定的可選參數(shù)的訪問速度比 variant 快,而且一旦數(shù)據(jù)類型錯誤,編譯時就顯示錯誤信息。
利用集合的優(yōu)點(diǎn)
可以定義和使用對象的集合是 visual basic 的強(qiáng)大功能之一。盡管集合是非常有用的,但還要正確使用才能獲得最好的效果:
使用 for each…next 替代 for…next。

添加集合的對象時避免使用 before 和 after 參數(shù)。

使用鍵集而不用幾組相同對象的數(shù)組。
集合可以用 for…next 循環(huán)進(jìn)行迭代。但采用 for each…next 可讀性更好,而且多數(shù)情況下更快。for each…next 是由集合的生成器實現(xiàn)迭代的,所以實際的操作速度將隨集合對象的不同而改變。由于 for each…next 的最簡單的實現(xiàn)機(jī)理就是 for…next 的線性迭代,因此 for each…next 不會比 for…next 慢。但是,有些情況下采用了比線性迭代更復(fù)雜的實現(xiàn)機(jī)理,所以 for each…next 要快得多。
如果沒有使用 before 和 after 參數(shù),則往集合中添加對象是非??斓?。否則,visual basic 必須在集合中檢測到其它對象后,才能添加新對象。
如果對象的類型都一樣,集合或數(shù)組都可以用來管理這些對象(如果對象的類型不一樣,則只能用集合)。從速度的觀點(diǎn)看,選擇何種方式取決于對象的訪問方式。如果能夠為每一對象分配唯一的鍵,則集合是訪問對象的最快方式。使用鍵從集合中檢索對象比從數(shù)組中順序遍歷對象快。當(dāng)然,如果沒有鍵而要遍歷對象時,則選擇數(shù)組比較好。就順序遍歷方式而言,數(shù)組比集合快。
如果對象的個數(shù)少,則數(shù)組使用的內(nèi)存小,并且搜索的速度快。當(dāng)對象的個數(shù)在 100 左右時,集合比數(shù)組的效率高;當(dāng)然,具體的數(shù)目還有賴于微處理器的速度和可用的內(nèi)存。
詳細(xì)信息   請參閱“再論編程”中的“用集合替代數(shù)組”。
優(yōu)化顯示速度



由于 microsoft windows 的圖形特性,圖形和其它操作的顯示速度在很大程度上決定了應(yīng)用程序的感覺速度。窗體出現(xiàn)及畫圖的速度越快,應(yīng)用程序就會顯得越快。以下的幾種技術(shù)可用來提高應(yīng)用程序的顯示速度:
將容器的 clipcontrols 屬性設(shè)置為 false。

恰當(dāng)?shù)厥褂?autoredraw。

使用 image 控件替代 picturebox 控件。

設(shè)置屬性時隱藏控件以避免多次重畫。

使用 line 替代 pset。
將容器的 clipcontrols 屬性設(shè)置為 false
除非正在使用圖形方法(line,pset,circle 和 print),否則將窗體、框架及 picturebox 控件的 clipcontrols 設(shè)置為 false(如果代碼包含了在其它控件之后繪圖的圖形方法,則這可能導(dǎo)致不可預(yù)測的結(jié)果)。當(dāng) clipcontrols 設(shè)置為 false 時,在重畫控件本身之前,visual basic 不會用背景覆蓋控件。這在窗體包含大量控件時,會大大提高顯示速度。
詳細(xì)信息 請參閱“使用文本和圖形”中的“使用 autoredraw 和 clipcontrols 使圖形分層”。
恰當(dāng)?shù)厥褂?autoredraw
當(dāng)窗體或控件的 autoredraw 設(shè)置為 true 時,visual basic 會利用位圖重畫該窗體或控件。這種方法雖然提高了簡單情況的重畫速度(例如,在刪除覆蓋在窗體或控件上的窗口后,窗體或控件重新顯示),但會降低圖形方法的速度。此時,visual basic 就會在 autoredraw 位圖上進(jìn)行圖形方法操作,再把整個位圖復(fù)制到屏幕上。這個過程也占用了相當(dāng)數(shù)量的內(nèi)存。
如果應(yīng)用程序產(chǎn)生的圖形復(fù)雜但是不常改變,autoredraw 設(shè)置為 true 較為合適。如果圖形需要經(jīng)常改變,則 autoredraw 設(shè)置為 false 的效果更好,并且在 paint 事件中進(jìn)行窗體或控件的圖形方法操作。
詳細(xì)信息 請參閱“使用文本和圖形”中的“使用 autoredraw 和 clipcontrols 使圖形分層”。
用 image 控件替代 picturebox 控件
優(yōu)化能夠提高應(yīng)用程序的速度,并減小其大小,所以要盡量應(yīng)用優(yōu)化技術(shù)。如果僅簡單顯示圖片,并只對單擊事件和鼠標(biāo)操作作出響應(yīng),應(yīng)使用 image 控件替代 picturebox。除非需要圖片框提供的特殊功能時,如圖形方法、包含其它控件的能力或動態(tài)數(shù)據(jù)交換 (dde),否則不要使用圖片框。
設(shè)置屬性時隱藏控件以避免多次重畫
重畫的代價是昂貴的。重畫的操作越少,應(yīng)用程序就顯得越快。減少重畫次數(shù)的一種方法,就是操作控件時使其不可見。例如,假設(shè)在窗體的 resize 事件中調(diào)整數(shù)個列表框的大?。?br>sub form_resize ()
dim i as integer, sheight as integer
   sheight = scaleheight / 4
   for i = 0 to 3
      lstdisplay(i).move 0, i * sheight, _
      scalewidth, sheight
   next
end sub
該示例產(chǎn)生四次獨(dú)立的重畫,每個列表框一次。把所有的列表框放在圖片框中,并在移動或調(diào)整列表框大小之前隱藏圖片框,就會減少重畫的次數(shù)。當(dāng)再次使圖片框可見時,所有的列表框一次畫出:
sub form_resize ()
dim i as integer, sheight as integer
   piccontainer.visible = false
   piccontainer.move 0, 0, scalewidth, scaleheight
   sheight = scaleheight / 4
   for i = 0 to 3
      lstdisplay(i).move 0, i * sheight, _
      scalewidth, sheight
   next
   piccontainer.visible = true
end sub
值得注意的是,該示例中使用了 move 方法替代設(shè)置 top 和 left 屬性。move 方法只需一次操作就設(shè)置了這兩個屬性,所以節(jié)省了多余的重畫。
使用 line 替代 pset
使用 line 比使用一系列的 pset 方法快。避免使用 pset 方法,把一些點(diǎn)組成一條線由 line 方法一次畫出。一般來說,簡單、不常改變的圖形元素采用形狀和直線控件來處理比較合適;而復(fù)雜的或經(jīng)常改變的圖形則最好采用圖形方法處理



編譯型和解釋型應(yīng)用程序的比較



按照缺省規(guī)定,visual basic 將應(yīng)用程序編譯成可運(yùn)行的解釋型或 p-code 程序。運(yùn)行時,動態(tài)鏈接庫 (dll) 將翻譯或解釋執(zhí)行程序中的指令。visual basic 專業(yè)版和企業(yè)版還可將程序編譯成 .exe 本機(jī)代碼。在許多情況中,運(yùn)行本機(jī)代碼比運(yùn)行解釋型代碼本質(zhì)上要快得多。但事情并非總是這樣。以下是一些有關(guān)本機(jī)代碼編譯的一般指南:
若代碼做了大量固定類型的、非字符串變量的基本操作,則其產(chǎn)生的本機(jī)代碼將與編譯的 p-code 操作碼產(chǎn)生最大的反差。然而,對于復(fù)雜的經(jīng)濟(jì)計算或生成分形圖形,用本機(jī)代碼有很多好處。

計算密集型程序,或在局部數(shù)據(jù)結(jié)構(gòu)中處理大量的位和字節(jié)操作的程序,用本機(jī)代碼就可獲得明顯的好處。

在許多程序中,特別是那些含有大量 windows api 調(diào)用,com 方法調(diào)用和字符串操作的程序,本機(jī)代碼不比 p-code 快多少。

如果應(yīng)用程序主要含有來自 visual basic for applications 運(yùn)行庫的函數(shù),那么就看不到多少本機(jī)代碼的好處,這是因為 visual basic for applications 運(yùn)行庫已經(jīng)高度優(yōu)化了。

含有大量子例程調(diào)用而非內(nèi)嵌過程的代碼,用本機(jī)代碼也似乎不太快。這是因為設(shè)置棧結(jié)構(gòu),初始化變量,返回時的清除等工作,用 p-code 引擎和用本機(jī)代碼所花費(fèi)的時間相同。
注意,調(diào)用一次對象、dll 或 visual basic for applications 運(yùn)行函數(shù),都會消弱本機(jī)代碼性能上的優(yōu)點(diǎn)。這是因為執(zhí)行代碼所花時間相對地少,而大量時間(常常達(dá)到 90-95%)花在窗體、數(shù)據(jù)對象、windows dll,或 visual basic for applications 運(yùn)行庫,以及處理內(nèi)部字符串和變量上。
實際測試中,典型情況是客戶應(yīng)用程序總的執(zhí)行時間有 5% 用于執(zhí)行 p-code。因此,如果本機(jī)代碼是瞬時執(zhí)行的,則在這些程序中用本機(jī)代碼也只能改進(jìn)性能最高達(dá) 5%。
本機(jī)代碼的目的是可讓程序員用 basic 編寫一小片代碼或有大量計算的算法。這些,由于性能問題,在以前是決不可能的。使用這些運(yùn)行非常快的“小片”,也能改善應(yīng)用程序特定部分的響應(yīng),從而改進(jìn)了整個應(yīng)用程序的感覺性能。
詳細(xì)信息 關(guān)于本機(jī)代碼的編譯的詳細(xì)信息,請參閱“再論編程”的“將工程編譯成本地代碼”。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多