ASP.NET應用程序性能優化
2024-07-10 13:04:24
供稿:網友
 
本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
[把前一段時間給單位項目所做性能優化的一些想法整理了以下,分享交流]
asp.net 應用程序性能優化
1 前言
性能優化的主要目標是提高“并發用戶數量”,“吞吐量”,“可靠性”這樣幾個指標。
本質上說,性能優化的工作應該是多方面的,要做到“點面結合、由表及里”。比如:從代價的角度來考慮,應盡量做到改動量小,易實施;從用戶角度看,應做到快速響應或快速提示;從軟件結構的角度看,又要兼顧到系統結構的合理性和可擴展性。由此不難發現,在嘗試一些改進方法時往往很難做到面面俱到。
舉一個簡單的例子:
在一個業務邏輯類中,我們封裝了一些處理方法,其中有一個方法的功能是查找一個節點id在xml文件是否已經存在。那我們自然會想到寫兩個方法:
xmldocument loadxml(string strfileid)   //加載xml 
bool checkidexisit(string strfileid,string strid)   //判斷節點是否存在
而且,加載xml的方法在其他地方還可以重用;表面上看,這段代碼的結構和功能都沒有問題。可是在運行時,如果你的邏輯中直接或間接調用了loadxml多次的話,你會發現程序很慢。原因就在于加載xml文件是個耗時動作,解決的方法很簡單,我們再提供幾個方法即可:
bool checkidexisitbyxml (string strxml,string strid)   //判斷節點是否存在
或 bool checkidexisitbyxml (xmldocument objxml,string strid)   //判斷節點是否存在
這樣,我們就可以通過“一次加載”實現多次借用,效率明顯提升。所以,在軟件結構設計時就應將可重用“珍貴”數據源的因素考慮進來。(這里的“珍貴”數據源是指那些經過復雜處理或長時間計算才得到的各種對象或記錄集)。
性能優化的工作又應是長期的,因為我們的工作始終是建立在os,web server, db server,  complier & program language等等的基礎上的。如果你熟悉.net, java,iis, j2ee, 你就會發現有些功能或api這個平臺提供了,另一個卻沒有;所以更多時候我們需要過渡的解決方案,等到新版本出來時,我們可能就會拋棄過渡方案直接配置或更簡便的實現一些功能。[...]
 
2 需求篇
性能優化的第一步是看看需求是否合理,這是對項目本身的一次回檢。某種意義上說,是一種逃避原則。但如果從軟件工程的角度來說這是必須的,因為客戶的需求是無止境的,而任何軟件都是有生命期的,os都是這樣何況應用軟件。我們總是希望用戶顯示與業務邏輯分開的越遠越好,卻忽略了一個基本問題:兩者終歸要銜接起來,如何定義兩者之間的i/o關系,讓它們能有效的相互配合并最終讓用戶滿意是非常重要的。
所以,在性能優化時回檢需求就是要把用戶交互定義好,使之更科學化。從業界發展動態看,現在已經有專門的人在研究用戶交互,這就像傳統行業里的所謂“工業設計”一樣,正越來越被重視!
在回檢需求時往往會“修改需求”,這時應該結合“需求定義人員”和“開發人員”兩方面的意見,因為各方角度不同,一定要取長補短。
 
3 交互響應篇
前面提到性能優化時可按“由表及里”的順序,這主要有兩方面的考慮:
第一,           這是用戶直接看到的東西,見效快;
第二,           改動難度比改動內核要小。
基于b/s結構的應用程序有前臺(用戶)與后臺(server)交互的問題,所以交互響應過程實際包括“后臺計算”與“加載到客戶端”兩個過程。那么很顯然,我們如果盡量減少需要下載到客戶端的數據量,會減小響應時間。
根據測試,我們發現將4萬條記錄綁定到grid的時間在35s左右,而實際上我們不會在頁面一下子顯示這么多條記錄,用戶也不可能一下子瀏覽這么多記錄。通常我們使用分頁的方式,而所謂的分頁只不過是重新綁定一下數據。所以,如果如果我們每次只綁定所請求的那一頁則到客戶端的數據量會陡降。這就是我們提出的“計算全部數據,加載局部數據”的思路(如下圖)。
圖 3-1 “即時按頁綁定”原理圖
 
我們再從用戶的角度看另外兩個問題,曾使用asp應用程序的人會發現asp.net應用程序使用時刷新頻率很高,一個小小的動作都要提交到服務端去處理。從軟件設計的角度看,我們覺得很合理,因為沒有耦合且邏輯可重用。可是“魚與熊掌不可兼得”,我們還是應該采取折中的手法。回到我們的系統中來,我們發現多數頁面在對于使用較頻繁的“增-刪-改”操作時,都是每一次操作都從數據庫重新讀,重新綁定。如此頻繁的刷新,用戶不會很認可,同時如果數據量大也會影響交互時間。
實際上,如果數據是顯示在grid中,那么刪除和修改時根本不需要重新load, 直接用控件本身的方法就可以了,雖然也會提交但與重新綁定還是有明顯區別的,速度也快得多!對于treeview則“增-刪-改”都不需要重新load,因為它不需要分頁。
另一個問題是對于復雜并可能耗時的計算過程,用戶雖可理解,但還是應該給出提示或進度條。這并不屬于性能優化的范疇,但卻是重要的ui規范,建議納入測試要求。關于進度條的顯示有兩種方式:
1 前臺顯示等待或完成進度,后臺處理完了,前臺進度條關閉,處理結果顯示;
2 提交任務到后臺后,轉到一個等待頁面,等后臺完成后轉到確認頁面。這種方式通常基于xmlhttprequest[13]技術,在后臺創建單獨的計算線程,其優點是可以避免后臺過于繁忙導致第一種顯示方式中客戶端長時間沒有反映,連進度條都不動了。
 
4 部署篇
部署其實是一個很大的概念,涵蓋了軟件和硬件。這里我們暫將系統部署結構、軟件設置、硬件配置都納為部署范圍。關于怎樣去部署一個軟件系統這里就不贅述了,僅將一些具體做法列舉出來。
 
4.1 asp.net
在有大數據量傳輸時,經常會遇到“out of memory”的異常。這時可調節machine.config文件中processmodel子項中的memorylimit 屬性的值,使得.net可以利用更多的內存。
4.2 其他4.2.1優化配置server & iis4.2.1.1擴大iis高速緩存
服務器保留了一部分內存空間用作iis高速緩存,為將來的請求存儲對象,這樣iis就可從高速緩存中檢索對象而不用從硬盤中檢索。調整iis高速緩存的容量需要修改注冊表,表項如下:
hkey_local_machine ystem/currentcontrolset ervices/inetinfo/parameters/memorycachesize
=0x 1e84800(類型為reg_dword,using hexadecimal notation.)
也可設為十進制,范圍0-4gb,缺省值為3072000(3mb)。一般來說此值最小應設為服務器內存的10%。
iis通過高速緩存系統句柄、目錄列表以及其他常用數據的值來提高系統的性能。這個參數指明了分配給高速緩存的內存大小。如果該值為0,那就意味著“不進行任何高速緩存”。在這種情況下系統的性能可能會降低。如果你的服務器網絡通訊繁忙,并且有足夠的內存空間,可以考慮增大該值。必須注意的是修改注冊表后,需要重新啟動才能使新值生效。
4.2.1.2調整iis占用cpu時間
服務器的cpu處理器能力總是有限的。哪一個應用程序占用處理器的時間最長,誰的性能就能得到最大的提高。
(1)在nt的控制面板中,雙擊系統圖標。  
(2)單擊性能標簽。  
(3)在應用程序性能下將游標拖到none的位置,這樣就可以使所有正在運行的服務,包括iis,使用處理器的時間達到最大值。
 (4)選擇最大化網絡應用程序的總處理能力。然后單擊“ok。” 
4.2.1.3協議及相關優化
(1)為了提高性能和節約資源,應該只運行需要的協議。
(2)應該將iis服務器,設置為獨立的服務器,不要讓服務器去承受域控制器要求的額外負荷。
(3)可以把nt服務器的頁交換文件分布到多個物理磁盤上,注意是多個“物理磁盤”,分布在多個分區上是無效的。另外,不要將頁交換文件放在與windows nt引導區相同的分區中。
(4)使用磁盤鏡像或磁盤帶區集可以提高磁盤的讀取性能。
(5)關于日志的記錄,應該采用文件記錄而不是記錄到odbc數據源。此外,還可以在記錄期間增加用來記錄日志的內存緩沖區的容量來減少磁盤的活動。該緩沖區的缺省容量值為64kb。
(6)最好把所有的數據都儲存在一個單獨的分區里。然后定期運行磁盤碎片整理程序以保證在存儲web服務器數據的分區中沒有碎片。使用ntfs有助于減少碎片。
(7)雖然ssl可以提供相當可靠的加密傳輸。但是所需的額外開銷會導致iis服務器速度下降,尤其是在處理大型文件的時候。所以應該只對確實需要保護的目錄進行ssl加密。
4.2.1.4 調整失效時間
hkey_local_machine ystem/currentcontrolset ervices/inetinfo/parameters/objectcachettl=0x8ca0.
4.2.1.5 調整最大線程數
hkey_local_machine ystem/ currentcontrolset ervices/w3svc/asp/parameters,增加processorthreadmax,減小這個值,看看性能的變化;或者增大這個值。)
4.2.1.6 注冊表中的其他可優化項
以“hkey_local_machine ystem/currentcontrolset ervices/inetinfo/parameters/”為父節點;
cachesecuritydescriptor indicates whether security descriptors are cached for file objects. a value of 1 enables this feature. a value of 0 disables this feature. when enabled (the default setting), security descriptors for files are saved when caching a file object. as long as the file is cached, iis will not need to re-access the file to determine access rights for new users. this value is most useful for sites that authenticate users and not useful for sites that allow anonymous access.
checkcertrevocation indicates whether iis checks to see if a client certificate is revoked. if you issue your own certificates and make local certificate checks, you might want to enable this feature. otherwise, the feature should be disabled, which is the default. a value of 1 enables this feature.
disablememorycache indicates whether iis memory caching is enabled or disabled. by default, memory caching is enabled (meaning this value is set to 0). disable memory caching only for testing or development purposes.
listenbacklog specifies the maximum number of active connections that iis maintains in the connection queue. the default value is 15 and the range of acceptable values is from 1 to 250.
maxcachedfilesize determines the maximum size of a file that can be placed in the file cache. iis will not cache files that are larger than this value. the default value is 262,144 bytes (256 kb).
maxconcurrency specifies how many threads per processor should be allowed to run simultaneously if there is a pending input/output (i/o) operation. the default value (0) allows iis to control the number of threads per processor. you can also set a specific value.
maxpoolthreads sets the number of pool threads to create per processor. each pool thread watches for a network request for a cgi application and processes it. this value does not control threads that are used by isapi applications. by default, the value is set to 4. on a single processor system, this means that only four cgi applications could run simultaneously.
memcachesize sets the maximum amount of memory that iis will use for its file cache. if iis does not need this much memory, it will be left for other applications to use. by default, iis uses 50 percent of the available memory. the valid range is from 0 megabytes to the total amount of physical memory available in megabytes.
objectcachettl sets the length of time (in milliseconds) that objects are held in memory. if the object hasn't been used in this interval, it is removed from memory. the default value is 30 seconds (300,000 milliseconds).
poolthreadlimit sets the maximum number of pool threads that can be created on the server. this limit is for all iis threads. the default value is twice the size of physical memory in megabytes.
4.2.1.7禁用不必要的服務:
禁用專用 web 服務器不需要的 windows 2000 服務。方法是:單擊開始,依次指向程序、管理工具,然后單擊計算機管理。在“計算機管理(本地)”下,展開“服務和應用程序”,然后單擊服務。當前所運行服務的狀態 列中顯示已啟動 。以下服務是專用 web 服務器上不需要的: 
   警報器 
   剪貼簿 
   計算機瀏覽器 
   dhcp 客戶端 
   dhcp 服務器 
   傳真服務 
   文件復制 
   紅外線監視器 
   internet 連接共享 
   信使 
   netmeeting 遠程桌面共享 
   網絡 dde 
   網絡 dde dsdm 
   nwlink netbios 
   nwlink ipx/spx 
   后臺打印程序 
   tcp/ip netbios 支持服務 
   電話 
   telnet 
   不間斷電源 
 ================================================
   記下與要停止的服務有依存關系的那些服務。方法是: 
   雙擊所需的服務。例如,雙擊信使。 
   單擊依存關系 選項卡。 
   在“服務名 依賴這些服務”列表中(其中,服務名是所選服務的名稱),記下該服務依賴的那些服務。 
   在“這些服務依賴服務名”列表中,記下沒有該服務就無法啟動的那些服務。 
   單擊確定。 
   禁用所需的服務。方法是: 
   右鍵單擊要禁用的服務,然后在出現的快捷菜單上單擊屬性 。 
   在“啟動類型”列表中,單擊禁用。 
   如果要立即停止服務,請單擊停止。如果顯示停止其他服務 對話框,依賴于該服務的其他服務也將被停止。請記下受影響的服務,然后單擊是。 
   單擊確定。該服務的啟動類型 列中會顯示禁用 。 
   重復執行第 4 步,禁用其他不必要的服務。 
   備注:禁用每個服務之后,應測試 web 服務器計算機是否運行正常。這樣就最大程度地減少了禁用可能需要的服務而帶來的影響。 
    備注:如果 iis 服務器是 windows 2000 域成員,則必需 tcp/ip 支持服務,以便將組策略正確地應用到計算機中。
4.2.1.8 最大化網絡應用程序數據吞吐量 
在工作內存中運行iis 5.0 進程可分頁代碼。方法是: 
   在桌面上右鍵單擊網上鄰居,然后在出現的快捷菜單中單擊屬性 。 
   右鍵單擊所需的本地連接 圖標,然后在出現的快捷菜單中單擊屬性 。 
   在“此連接使用下列選定的組件”列表中,單擊“microsoft 網絡的文件和打印機共享”(但不要清除其復選框),然后單擊屬性。 
   單擊“最大化網絡應用程序數據吞吐量”,然后單擊確定 兩次
4.2.1.9優化后臺服務的性能
iis 5.0 進程 (inetinfo.exe) 作為后臺服務運行。要提高后臺服務的性能,請按以下步驟操作: 
   單擊開始,指向設置,然后單擊控制面板。 
   在“控制面板”中,雙擊系統。 
   單擊高級 選項卡,然后單擊性能選項。 
   在“應用程序響應”下,單擊“后臺服務”,然后單擊確定 兩次。 
   退出“控制面板”。
4.2.1.10 最小化 iis 5.0 日志記錄 
禁止對不需要的 web 站點、虛擬目錄或文件及文件夾進行日志記錄。方法是: 
   單擊開始,依次指向程序、管理工具,然后單擊internet 服務管理器。 
   展開“*服務器名”,其中 服務器名 是 web 服務器的名稱。 
   找到所需的項,然后用右鍵單擊該項。在出現的快捷菜單上,單擊屬性。例如,右鍵單擊默認 web 站點,然后在出現的快捷菜單上單擊屬性 。 
   執行下列操作之一: 
   如果選擇 web 站點,則單擊主目錄 選項卡。 
    - 或 - 
   如果選擇虛擬目錄,則單擊虛擬目錄 選項卡。 
    - 或 - 
   如果選擇實際目錄,則單擊目錄 選項卡。 
   單擊“日志訪問”復選框,將其清除,然后單擊確定。 
 
   要禁止整個 web 站點的日志記錄,請單擊web 站點 選項卡,單擊啟用日志記錄 復選框,將其清除,然后單擊確定。 
   退出“internet 信息服務”管理單元。
4.2.1.11啟用帶寬限制 
限制各 web 站點可用的網絡帶寬。方法是: 
   啟動“internet 服務管理器”。 
   展開“*服務器名”,其中服務器名 是 web 服務器的名稱。 
   右鍵單擊所需的 web 站點(例如,默認 web 站點),然后在出現的快捷菜單上單擊屬性 。 
   單擊性能 選項卡,然后單擊“啟用帶寬限制”復選框,將其選中。 
   在“最大網絡使用”框中,鍵入所需的值,然后單擊確定。 
   退出“internet 信息服務”管理單元。
4.2.1.12 限制處理器使用 
限制 web 站點對處理器的占用量。方法是: 
   啟動“internet 服務管理器”。 
   展開“*服務器名”,其中服務器名 是 web 服務器的名稱。 
   右鍵單擊所需的 web 站點(例如,默認 web 站點),然后在出現的快捷菜單上單擊屬性 。 
   單擊性能 選項卡,然后單擊“啟用進程限制”復選框,將其選中。 
   在“最大程度使用 cpu”框中,鍵入所需的值。 
   單擊“強制性限制”復選框,將其選中,然后單擊確定。 
 備注:如果不啟用強制性限制 選項,則不會強制執行“最大程度使用 cpu”的限制。在 web 站點超過其允許的 cpu 使用限制時,即會在“事件日志”中寫入事件。 
   退出“internet 信息服務”管理單元。
 4.2.1.13限制 web 站點連接 
限制各 web 站點可用的連接數量。方法是: 
   啟動“internet 服務管理器”。 
   展開“*服務器名”,其中服務器名 是 web 服務器的名稱。 
   右鍵單擊所需的 web 站點(例如,默認 web 站點),然后在出現的快捷菜單上單擊屬性 。 
   在連接下,單擊限于。 
   在“連接”框中,鍵入要允許的連接數量。 
 
   備注:連接的每個客戶端大約同時使用四個連接。例如,將連接數限制在 200 大約允許 50 名用戶訪問 web 站點。 
   單擊確定,然后退出“internet 信息服務”管理單元。
4. 2.1.14 使用“保持 http 連接” 
默認情況下,能夠使用“保持 http 連接”。要驗證是否啟用了“保持 http 連接”,請按以下步驟操作: 
   啟動“internet 服務管理器”。 
   展開“*服務器名”,其中服務器名 是 web 服務器的名稱。 
   右鍵單擊所需的 web 站點(例如,默認 web 站點),然后在出現的快捷菜單上單擊屬性 。 
   在連接下,確認“已啟用保持 http 連接”復選框已被選中,然后單擊確定。 
   退出“internet 信息服務”管理單元。
 
4.2.2 優化配置dbserver4.2.2.1 sqlserver
內存是影響microsoft sql server系統性能的一個重要因素。
sql server數據庫安裝時將為具有32mb物理內存的機器缺省配置16mb可用內存,16mb物理內存的機器缺省配置4mb可用內存。應在microsoft sql server數據庫安裝后進行內存選項(memory)設置。為了確定sql server系統最適宜的內存需求,可以從總的物理內存中減去windows 2000 server需要的內存以及其它一些內存需求后綜合確定。 
 以下是sql server內存選項(memory)設置方法 
 (1)從microsoft sql server程序集中啟動sql enterprise manager;
 (2)從server manager窗口中選擇“server”菜單選項; 
 (3)在“server”菜單中選擇“configurations”選項; 
 (4)在“server configuration”對話框中選擇”configuration”標簽,
 (5)選中“memory”項目,在“current”欄填入新值; 
 (6)停止并重新啟動sqlserver服務,使設置生效。 
 
合理擴充虛擬內存、增大sql server可用內存 
  當sql server系統確實需要擴大可用內存時,應在磁盤空間充足的情況下擴充供虛擬
內存,并相應增大 sql server可用內存。具體做法是,系統管理員首先擴充服務器的虛擬內存,然后再參考上表增大sql server可用內存,關鍵是要根據系統的負載情況綜合決定是否擴充。
使用tempinram 
 sql server使用tempdb臨時數據庫作為一些查詢連接操作時排序或創建臨時表的工作
空間。將tempdb創建在ram中可以使系統操作性能有較大提高,而且因為tempdb在每次重啟動服務器時都重建,這樣即使有非正常的關閉也是較為安全的,例如停電故障。要將tempdb創建在ram中,可以使用sp_configure進行設置,具體用法請參閱有關資料。
 由于tempdbinram使用的內存是由系統從內存體單獨分配的,與sql server的內存選
項設置的可用內存池是分開的,使用tempdbin ram將減少整個系統的可用內存,應根據sql server和服務器運行情況進行配置,否則就可能適得其反,影響系統性能。另外,適當增加tempdb數據庫空間,即使不使用tempdbin ram,也可以提高數據庫的運行速度。
 注意事項:在生產環境中sql server不要設置小于32mb內存,而且數據庫服務器上盡量擴充供虛擬內存、增大sql server可用內存,應考慮物理內存使用狀況和磁盤空間;在可能的情況下,要為系統留有部分額外的內存,這樣在服務器上打開一個服務或添加一個進程且不改變sql server內存配置時,不致于使nt服務器的運行速度受到影響(變得很慢),一般認為最小為2mb最大為20mb。
 
4.2.3硬件提升4.2.3.1 cpu/內存
如果測試確定存在處理器問題,您的第一個選擇當然就是將處理器升級或切換到多處理器計算機。如果確定要升級處理器,應確保它有最大的 l2 緩存,iis 將因此而受益,因為它的許多指令路徑都包括多個組件,它們在高速緩存中運行時速度會大大加快。
計算機名/內存/可用內存 - 該計數器跟蹤系統中的可用內存總量。操作系統嘗試將該值保持在 4 mb 以上。為了達到最佳性能,該值最好為內存總量的 5%。
4.2.3.2 硬盤
不要將日志文件與 web 頁存儲在同一個硬盤上。這將阻止硬盤日志記錄線程干預檢索 web 頁的線程。
優化 web 頁存儲。站點上的所有相關 web 頁應該存儲在同一個邏輯分區,這樣可以提高文件系統緩存的性能。同時,web 頁文件不應有任何碎片,這樣可以極大地加快讀取單個文件的速度。
如果使用ultra2的scsi硬盤,可以顯著提高iis的性能。網絡接口卡,內存的升級自然不用多言。
 
 
5 session管理篇
http 協議之所以能夠獲得如此大的成功,其設計實現的簡潔性和無狀態連接的高效率是很重要的原因。而為了在無狀態的 http 請求和有狀態的客戶端操作之間達到平衡,產生了服務器端會話 (session) 的概念。session的引入極大地方便了web編程,但與之對應的session管理變得異常重要。目前asp.net可以通過“進程內”、“進程外專用狀態管理服務”和“sql server狀態服務管理”三種方式來進行狀態管理。對于默認的“進程內”管理方式只實現了一個進程內的基于內存的狀態管理,故而存在很多問題:
1.所有的 session 數據都保存在 web 服務的進程中,會造成服務器支持會話數量受到服務器內存資源的限制問題,同時也因為大量非活動會話導致內存被無效占用。
2.服務器進程崩潰會導致所有的會話數據丟失。
回到我們的實際系統,目前我們使用session變量大致有四種用途:
圖5-1 session變量使用范圍
 
顯然,前三種方式都是小數據量的,我們這里主要關注第四種方式——session數據集變量。
把整個數據集存放在session中,主要是為了用于后續處理或二次加工或用戶翻頁時重新綁定,一般情況下我們在編碼時會忽略數據集的大小給web-server和交互時間帶來的影響。實際上,一個超大數據集(記錄數在10萬條以上)所占用的空間是相當可觀的,如果有數個并發,web-server的內存會急劇緊張。下表是實際測試的關于sql執行時間的統計。
 
記錄數(萬)
執行時間(秒)
10
4
11
6
15
10
20
11
30
12
40
16
50
19
表 5-1 數據查詢執行時間統計表
有一種解決方法是將復雜查詢的“查詢條件”存于session中。這種方法簡潔又輕便,但是也會造成“由于頻繁查詢導致db-server繁忙”的局面(50萬條記錄的查詢時間大于15s);理想的解決辦法是實現在數據庫查詢時可進行分頁或者說可以按頁查詢,這時session中完全可只存放查詢條件,因為交互數據量也不大。oracle和sqlserver2005中可以比較方便地實現此功能,但sqlserver2000中實現起來比較麻煩,一般都會用存儲過程。
考慮到已有系統在實現上并沒有考慮大數據量而且也不是每個頁面或邏輯都會出現大數據量,所以不應該采用單一的session管理方案。實際上,我們可以構造具有自適應性的數據訪問執行器和session管理器,動態地去按不同的方式返回和存儲執行結果。由于目前系統的session管理模式為“進程內”(inproc)模式且由于iis沒有提供平滑的可配置二級(內存/硬盤)緩存介質切換 ,所以可自行構造虛擬存儲空間,緩解并發壓力。下面是該方案的總體結構圖:
圖5-2 全局session管理結構圖
 
首先,我們來看一下數據訪問執行的流程圖(圖5-3)。
由圖5-3可知,我們在執行查詢時會設定一個時間閥值,如果在規定時間內執行完畢說明數據量不是很大那么直接將結果集返回給前臺;如果超時了,則會返回一個小數據集(比如 top 1000),然后在后臺另辟線程繼續查詢動作并將最終結果集保存到session,注意這時的數據集在一般情形下是很大的但也可能由于服務器繁忙造成等待,所以我們會通過session manager去動態按適合的方式保存。
圖5-3 數據訪問執行器流程圖
 
下面是sessionmanager類結構的簡單示意圖,
圖 5-4 pagesessionmanager類結構簡單示意圖
必須說明這只是一個簡單示意圖,在具體實現時這個結構會大大豐富。比如,要加上當前session的保存方式和保存數量等。實現pagesessionmanager的目的是為了規范session的使用尤其是session數據集變量的使用,我們會根據數據集的大小來自動選擇存儲方式,下面是存儲session數據集變量的流程圖。
圖 5-5 保存數據集變量流程圖
可以看到,我們在sessionmanager中引入了一種新的存儲方式——虛擬存儲(virtual store)。其目的顯然是為了緩解web-server內存壓力,提高并發度。經檢測,這種方式還是比較快的;如果把xml保存到數據庫,則在獲取xml或讀取xml時會發生超時異常。實際上,我們是自行構造了一種進程外session管理器,那么也自然需要進行session的清除和失效管理,我們可以在后臺運行專門的失效管理進程,具體實現方法可參考下圖。
圖 5-6 虛擬存儲示意圖
另一個問題是虛擬存儲文件與http進程的對應關系如何建立。這并不難,我們只要創建一個guid存放在同名的實際session中,虛擬session的文件名以此guid為標識即可。
與存儲相對應的,在通過sessionmanager獲取session值的時候,sessionmanager也要自動根據當前存儲方式反饋相應結果,其實現過程并不復雜,這里就不贅述了。
總的來說,這套解決方案的特點是提高并發度和保證快速響應,但對某些問題的處理也有不便。比如,查詢需要二次加工的記錄集時希望一次得到全部數據集(即使很大),這時必須設定相應屬性值告訴adaptiveexecutor,使之按照指定方式執行;還有就是大數據量時,分頁控件在查詢結束時不能瞬時得到總頁數。
 
 
 
6 代碼篇
這里的代碼級優化是指對具體的代碼實現特別是某個業務邏輯的算法的改進。在前言中舉的一個例子就屬于代碼優化。代碼優化是深層次的,需要非常熟悉業務邏輯和數據流,所以難度也是最大的。但在除去業務邏輯之后,我們還是可以對編碼技巧或者算法結構達成共識的。本篇主要列舉一些實際編碼過程中基于性能考慮應當掌握的方法和注意點。
 
•          不要使用不必要的session,和asp中一樣,在不必要的時候不要使用session 
•          不使用不必要的server control
•          不使用不必要的viewstate 
•          不要用exception控制程序流程
•          禁用vb和jscript動態數據類型
•          使用存儲過程完成數據訪問
•          只讀數據訪問不要使用dataset 
•          關閉asp.net的debug模式
•          使用asp.net output cache緩沖數據
•          盡量用sql返回datagrid需要綁定的dataset,盡量不要對dataset進行二次加工,特別不要對dataset進行大量刪除,實踐證明這很慢。不如復制部分數據。
•          盡量不要對dataset二次加工或者在通過dataset拼成對象集;顯然,若有40000條記錄就意味著要拼>=40000次的對象
•          盡量把查詢數據的數據庫操作次數壓縮到最少,盡量1-2次數據庫操作就可完成;如果對查詢得到的dataset的每項數據再進行查詢,那么意味著如果有40000條記錄,至少要執行400001次數據庫操作,加上遍歷dataset、生成對象的時間,是相當驚人的
•          注意優化數據庫查詢操作,比如無條件查詢時不要通過離散值一個一個取;
•          注意限制大數據量查詢操作,比如預計一個頁面如果一個條件都不加會出現很多數據,則強制至少加一個查詢條件;
•          不要在頁面加載時默認選擇全部數據,盡管可以方便后續操作,但用戶會以為“還沒有操作就這么慢”
•          建議盡量用比較高效的sql代替后續復雜的dataset二次加工
•          僅在需要的時候打開數據庫連接
•          一旦數據庫操作完畢,一定關閉連接
•          在關閉連接時記得刪除臨時對象
•          在關閉連接前,確保關閉任何用戶定義事務
•          若要利用連接池,不要使用應用角色(application roles)
•          顯示非交互性數據,使用sqldatareader可以獲得最佳性能
•          通過在sql中得到html碼比用datagrid component格式化數據顯示具有更好的性能
•          一般而言,在循環中使用索引(index)比使用集合(collection)具有更好的性能。因為clr (common language runtime)有時可以根據數據索引進行優化,而集合則不然
•          注意共享那些經過復雜處理或漫長查詢才得到的數據
•          在頁面跳轉時記得終止當前頁面的處理
•          如果頁面加載或后臺計算中有一些數據不相關的處理邏輯,可以考慮采用多線程;頁面加載也可以考慮逐步加載(response.flush())
•          有大量連接的字符串操作不要使用+,改用stringbuilder
 
 
7 reference
1. http://www.microsoft.com/technet/prodtechnol/windows2000serv/technologies/iis/maintain/optimize/perflink.mspx
2.       http://www0.ccidnet.com/tech/web/2001/09/28/58_3369.html
3.       http://msdn.microsoft.com/library/chs/default.asp?url=/library/chs/cpguide/html/cpconaspoptimization.asp 
4.       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt06.asp 
5.       http://www.microsoft.com/china/technet/itsolutions/net/maintain/netopsgd.asp 
6.       http://www.programfan.com/showarticle.asp?id=2548 
7.       http://www.microsoft.com/china/msdn/library/webservices/asp.net/cachingnt2.mspx 
8.       http://www.programfan.com/showarticle.asp?id=2548 
9.       http://www.microsoft.com/china/msdn/library/webservices/asp.net/cachingnt2.mspx
10.   http://www.sql-server-performance.com/asp_net_performance.asp
11.   http://www.cnblogs.com/flier/archive/2004/08.html
12.   http://soft.yesky.com/softchannel/72342380468043776/20050223/1914105.shtml
13.   http://jibbering.com/2002/4/httprequest.html