一、 引言
在Web表單中,我們使用
AJax來從客戶端(通過JavaScript)調用服務端方法,而在
AJax內部則進行XMLHttpRequest調用。我測試了一些以不同方式實現的AJAX函數。另外,我還監控分析了進行AJax調用的性能和生命周期。結果,我發現在Web表單中使用
AJax時存在一些嚴重的問題。不過,我也找到了這些問題的一種解決方法。在本文中,我正是想與各位分析這一問題及其相應的解決方案。
二、 在使用AJax時所遇到的性能問題 對於每一個AJAX調用來說,我們都要創建包含AJax方法的類的一個實例。另外,如果我們在類級上使用new關鍵字的話,我們還要為字段、屬性及其它類級的變量創建實例。
三、 實現方案 我創建了一個工程,它包含兩個Web表單:WebForm1.aspx和WebForm2.ASPx,還有一個類Student.vb。這兩部分code-behind頁面都使用了一個
AJax函數getData()和一個Student類型的公共變量。借助於MXLogger類,我記錄下每一個階段的執行流程。
注意:Webform2.ASPx的AJax函數GetData()是共享的,而在WebForm1中,它不是共享的。
'Student.vb
Public Class Student
Sub New()
MXLogger.AddLog("From Student.Constructor")
End Sub
Dim _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal Value As String)
_Name = Value
End Set
End Property
End Class
'WebForm1.ASPx.vb
Public Class WebForm1
Public Student As New Student
Sub New()
MXLogger.AddLog("From WebForm1.Constructor")
End Sub
<Ajax.AjaxMethod(AJax.HttpSessionStateRequirement.Read)> _
Public Function getData() As String
MXLogger.AddLog("From WebForm1.AJax.getData()")
Return "I m a Non Shared Function"
End Function
End Class
'WebForm2.ASPx.vb
Public Class WebForm2
Public Student As New Student
Sub New()
MXLogger.AddLog("From WebForm2.Constructor")
End Sub
<Ajax.AjaxMethod(AJax.HttpSessionStateRequirement.Read)> _
Public Shared Function getData() As String
MXLogger.AddLog("From WebForm2.AJax.getData()")
Return "I m a Shared Function"
End Function
End Class
'Student.vb
Public Class Student
Sub New()
MXLogger.AddLog("From Student.Constructor")
End Sub
Dim _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal Value As String)
_Name = Value
End Set
End Property
End Class
'WebForm1.ASPx.vb
Public Class WebForm1
Public Student As New Student
Sub New()
MXLogger.AddLog("From WebForm1.Constructor")
End Sub
<Ajax.AjaxMethod(AJax.HttpSessionStateRequirement.Read)> _
Public Function getData() As String
MXLogger.AddLog("From WebForm1.AJax.getData()")
Return "I m a Non Shared Function"
End Function
End Class
'WebForm2.ASPx.vb
Public Class WebForm2
Public Student As New Student
Sub New()
MXLogger.AddLog("From WebForm2.Constructor")
End Sub
<Ajax.AjaxMethod(AJax.HttpSessionStateRequirement.Read)> _
Public Shared Function getData() As String
MXLogger.AddLog("From WebForm2.AJax.getData()")
Return "I m a Shared Function"
End Function
End Class
四、 測試應用程序 · 測試用例1:
運行webform1.ASPx並且從JavaScript中調用getData() AJax函數三次。
· 測試用例2:
運行webform2.ASPx並且從JavaScript中調用getData()AJax函數三次。
對於上面的測試用例,我得到如下的日志輸出數據:
//請注意,為了解釋之目的,我在其中手工加入了一些日志行
LOG for the Test Case 1: ( Non AJax Shared Function )
-------While Loading The Page--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:37:30 AM>>From Student.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.AJax.getData()
LOG for the Test Case 2: ( Shared AJax Function )
-------While Loading The Page--------
5/9/2006 10:37:09 AM>>From Student.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
//請注意,為了解釋之目的,我在其中手工加入了一些日志行
LOG for the Test Case 1: ( Non AJax Shared Function )
-------While Loading The Page--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:37:30 AM>>From Student.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.AJax.getData()
LOG for the Test Case 2: ( Shared AJax Function )
-------While Loading The Page--------
5/9/2006 10:37:09 AM>>From Student.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
//請注意,為了解釋之目的,我在其中手工加入了一些日志行
LOG for the Test Case 1: ( Non AJax Shared Function )
-------While Loading The Page--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:37:30 AM>>From Student.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.AJax.getData()
LOG for the Test Case 2: ( Shared AJax Function )
-------While Loading The Page--------
5/9/2006 10:37:09 AM>>From Student.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
//請注意,為了解釋之目的,我在其中手工加入了一些日志行
LOG for the Test Case 1: ( Non AJax Shared Function )
-------While Loading The Page--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:37:29 AM>>From Student.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.Constructor
5/9/2006 10:37:29 AM>>From WebForm1.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:37:30 AM>>From Student.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.Constructor
5/9/2006 10:37:30 AM>>From WebForm1.AJax.getData()
LOG for the Test Case 2: ( Shared AJax Function )
-------While Loading The Page--------
5/9/2006 10:37:09 AM>>From Student.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.Constructor
5/9/2006 10:37:09 AM>>From WebForm2.AJax.getData()
-------First Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Second Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
-------Third Call For GetData()--------
5/9/2006 10:38:11 AM>>From WebForm2.AJax.getData()
我們可以看到,在上面的日志輸出數據中,對於測試用例1來說,我們能夠看到更多的來自於Webform1和Student的構造器的日志數據。
五、 結論
我的建議是,在所有可能的地方,我們應該使用針對於AJax的共享方法,以便它不會創建更多的Web表單實例和類級的字段。這樣以來,我們就可以減少從GC中調用Finalize()的次數。