<% ' Class library for timing sections of ASP code. ' ' Create instances of the SlTimerScope class in your code and make sure the lifetime of the instances matches ' what you want to time. ' You provide this class with an instance of the SlTimerContext class ' which you should keep alive for the life of your page. ' Call on the context class's Scopes property to get a dictionary containing SlTimerContextItem classes ' which hold information about the timing of the scopes, ' or just call the SummarizeTiming routine at the bottom of this file for a nice little tabular report. ' You can provide the SlTimerScope class with a "nothing" context to disable the more time-consuming ' profiling operations and the summary output. ' ' Instead of using the SlTimerScope class, you can use the SlTimerContext class's ' EnterScope and ExistScope methods directly. ' The main benefit of having a scope class is that you can just declare instances of the class ' in a function you want to time without worrying about calling ExitScope at all return points ' or in case of untrapped errors, etc., but for timing small sections of long scripts, ' the context methods are a bit more succinct. ' Timer scope class. class SlTimerScope Public Context Public ScopeName Public Sub Enter(ScopeNameParam, ContextParam) Set Context = ContextParam ScopeName = ScopeNameParam If Not Context Is Nothing Then Context.EnterScope ScopeName End If End Sub Private Sub Class_Terminate() If Not Context Is Nothing Then Context.ExitScope ScopeName End If End Sub end class ' Timer context class. ' Manages a global set of timer scopes. class SlTimerContext ' Schema: Scope => SlTimerContextItem. Private m_timerScopes Public Sub ResetScopes m_timerScopes.RemoveAll End Sub Public Sub EnterScope(ScopeName) Dim timer_obj If m_timerScopes.Exists(ScopeName) Then Set timer_obj = m_timerScopes(ScopeName) Else Set timer_obj = New SlTimerContextItem timer_obj.ScopeName = ScopeName Set timer_obj.TimerObj = New SlTimer m_timerScopes.Add ScopeName, timer_obj End If timer_obj.EnterScope End Sub Public Sub ExitScope(ScopeName) Dim timer_obj Set timer_obj = m_timerScopes(ScopeName) timer_obj.ExitScope End Sub Public Property Get Scopes Set Scopes = m_timerScopes End Property Private Sub Class_Initialize() Set m_timerScopes = Server.CreateObject("Scripting.Dictionary") End Sub Private Sub Class_Terminate() ResetScopes Set m_timerScopes = Nothing End Sub end class ' Timer context item. This holds information about the scope it represents. class SlTimerContextItem Public ScopeName Public ElapsedMs Public TimerObj Public HitCount Public Sub EnterScope HitCount = HitCount + 1 TimerObj.StartTimer End Sub Public Sub ExitScope TimerObj.StopTimer ElapsedMs = ElapsedMs + TimerObj.ElapsedMs End Sub end class ' Core timer class. Wraps the Softwing.Profiler component providing a nice Start, Stop, ElapsedMs interface. class SlTimer Private m_timer Private m_latestElapsedMs Private Sub Class_Initialize() Set m_timer = CreateObject("Softwing.Profiler") End Sub Public Sub StartTimer() m_timer.ProfileStart End Sub Public Sub StopTimer() m_latestElapsedMs = m_timer.ProfileStop / 10 End Sub Public Property Get ElapsedMs() ElapsedMs = m_latestElapsedMs End Property end class ' Utility function to summarize the scopes. sub SummarizeTiming(timerCtxt) if timerCtxt is nothing then exit sub end if Dim scopes Set scopes = timerCtxt.Scopes %> <h1>SlTiming Info</h1> <table border=2 cellspacing=0> <thead> <tr style="background: #000000; color: #FFFFFF"> <th>Scope</th><th>Total Time (ms)</th><th>Total Hits</th><th>Time Per Hit (ms/hit)</th> </tr> </thead> <tbody> <% Dim cur_scope for each cur_scope in scopes.Items with cur_scope %> <tr> <td align=left><% = Server.HtmlEncode(.ScopeName) %></td> <td align=right><% = FormatNumber(.ElapsedMs) %></td> <td align=right><% = .HitCount %></td> <td align=right><% if .HitCount = 0 then Response.Write "???" else Response.Write FormatNumber(.ElapsedMs / .HitCount) end if %></td> </tr> <% end with next %> </tbody> </table> <% end sub %>