Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# Ogre::Profiler Class Reference

The profiler allows you to measure the performance of your code. More...

`#include <OgreProfiler.h>`

Inheritance diagram for Ogre::Profiler:

[legend]
List of all members.

## Public Methods

| Profiler ()
| ~Profiler ()
void | setTimer (Timer *t)
| Sets the timer for the profiler.
Timer * | getTimer ()
| Retrieves the timer for the profiler.
void | beginProfile (const String &profileName)
| Begins a profile.
void | endProfile (const String &profileName)
| Ends a profile.
void | setEnabled (bool enabled)
| Sets whether this profiler is enabled.
bool | getEnabled () const
| Gets whether this profiler is enabled.
void | enableProfile (const String &profileName)
| Enables a previously disabled profile.
void | disableProfile (const String &profileName)
| Disables a profile.
bool | watchForMax (const String &profileName)
| Returns true if the specified profile reaches a new frame time maximum.
bool | watchForMin (const String &profileName)
| Returns true if the specified profile reaches a new frame time minimum.
bool | watchForLimit (const String &profileName, Real limit, bool greaterThan=true)
| Returns true if the specified profile goes over or under the given limit frame time.
void | logResults ()
| Outputs current profile statistics to the log.
void | reset ()
| Clears the profiler statistics.
void | setUpdateDisplayFrequency (uint freq)
| Sets the Profiler so the display of results are updated ever n frames.
uint | getUpdateDisplayFrequency () const
| Gets the frequency that the Profiler display is updated.

## Static Public Methods

Profiler & | getSingleton (void)
| Override standard Singleton retrieval.
Profiler * | getSingletonPtr (void)
| Override standard Singleton retrieval.

## Protected Types

typedef std::list< ProfileInstance > | ProfileStack
typedef std::list< ProfileFrame > | ProfileFrameList
typedef std::list< ProfileHistory > | ProfileHistoryList
typedef std::map< String, ProfileHistoryList::iterator > | ProfileHistoryMap
typedef std::map< String, bool > | DisabledProfileMap
typedef std::list< GuiElement * > | ProfileBarList

## Protected Methods

void | initialize ()
| Initializes the profiler's gui elements.
void | displayResults ()
| Prints the profiling results of each frame.
void | processFrameStats ()
| Processes the profiler data after each frame.
void | changeEnableState ()
| Handles a change of the profiler's enabled state.
GuiContainer * | createContainer ()
| An internal function to create the container which will hold our display elements.
GuiElement * | createTextArea (const String &name, Real width, Real height, Real top, Real left, uint fontSize, const String &caption, bool show=true)
| An internal function to create a text area.
GuiElement * | createPanel (const String &name, Real width, Real height, Real top, Real left, const String &materialName, bool show=true)
| An internal function to create a panel.

## Protected Attributes

ProfileStack | mProfiles
| A stack for each individual profile per frame.
ProfileFrameList | mProfileFrame
| Accumulates the results of each profile per frame (since a profile can be called more than once a frame).
ProfileHistoryList | mProfileHistory
| Keeps track of the statistics of each profile.
ProfileHistoryMap | mProfileHistoryMap
| We use this for quick look-ups of profiles in the history list.
DisabledProfileMap | mDisabledProfiles
| Holds the names of disabled profiles.
ProfileBarList | mProfileBars
| Holds the display bars for each profile results.
bool | mInitialized
| Whether the GUI elements have been initialized.
uint | maxProfiles
| The max number of profiles we can display.
Overlay * | mOverlay
| The overlay which contains our profiler results display.
GuiContainer * | mProfileGui
| The window that displays the profiler results.
Real | mBarHeight
| The height of each bar.
Real | mGuiHeight
| The height of the stats window.
Real | mGuiWidth
| The width of the stats window.
Real | mBarIndent
| The size of the indent for each profile display bar.
Real | mGuiBorderWidth
| The width of the border between the profile window and each bar.
Real | mBarLineWidth
| The width of the min, avg, and max lines in a profile display.
uint | mUpdateDisplayFrequency
| The number of frames that must elapse before the current frame display is updated.
uint | mCurrentFrame
| The number of elasped frame, used with mUpdateDisplayFrequency.
Timer * | mTimer
| The timer used for profiling.
ulong | mTotalFrameTime
| The total time each frame takes.
bool | mEnabled
| Whether this profiler is enabled.
bool | mEnableStateChangePending
| Keeps track of whether this profiler has received a request to be enabled/disabled.
bool | mNewEnableState
| Keeps track of the new enabled/disabled state that the user has requested which will be applied after the frame ends.

## Static Protected Attributes

Profiler * | ms_Singleton = 0

## Detailed Description

The profiler allows you to measure the performance of your code.

Remarks:
  Do not create profiles directly from this unless you want a profile to last outside of its scope (ie the main game loop). For most cases, use the macro OgreProfile(name) and braces to limit the scope. You must enable the Profile before you can used it with setEnabled(true). If you want to disable profiling in Ogre, simply set the macro OGRE_PROFILING to 0.

Author:
  Amit Mathew (amitmathew (at) yahoo (dot) com)

Todo:
  resolve artificial cap on number of profiles displayed

  fix display ordering of profiles not called every frame

Definition at line 98 of file OgreProfiler.h.

## Member Typedef Documentation

typedef std::map<String, bool> Ogre::Profiler::DisabledProfileMap`[protected]`

| Definition at line 329 of file OgreProfiler.h.

typedef std::list<GuiElement*> Ogre::Profiler::ProfileBarList`[protected]`

| Definition at line 331 of file OgreProfiler.h.

typedef std::list<ProfileFrame> Ogre::Profiler::ProfileFrameList`[protected]`

| Definition at line 326 of file OgreProfiler.h.

typedef std::list<ProfileHistory> Ogre::Profiler::ProfileHistoryList`[protected]`

| Definition at line 327 of file OgreProfiler.h.

typedef std::map<String, ProfileHistoryList::iterator> Ogre::Profiler::ProfileHistoryMap`[protected]`

| Definition at line 328 of file OgreProfiler.h.

typedef std::list<ProfileInstance> Ogre::Profiler::ProfileStack`[protected]`

| Definition at line 325 of file OgreProfiler.h.

## Constructor & Destructor Documentation

Ogre::Profiler::Profiler | ( |  | ) |

| Definition at line 82 of file OgreProfiler.cpp. References maxProfiles, mCurrentFrame, mEnabled, mEnableStateChangePending, mInitialized, mNewEnableState, mTimer, mTotalFrameTime, and mUpdateDisplayFrequency.

Ogre::Profiler::~Profiler | ( |  | ) |

| Definition at line 99 of file OgreProfiler.cpp. References logResults(), mDisabledProfiles, mProfileBars, mProfileFrame, mProfileHistory, mProfileHistoryMap, and mProfiles.

## Member Function Documentation

void Ogre::Profiler::beginProfile | ( | const String & | profileName | ) |

Begins a profile.

Remarks:
  Use the macro OgreProfileBegin(name) instead of calling this directly so that profiling can be ignored in the release version of your app.
  You only use the macro (or this) if you want a profile to last outside of its scope (ie the main game loop). If you use this function, make sure you use a corresponding OgreProfileEnd(name). Usually you would use the macro OgreProfile(name). This function will be ignored for a profile that has been disabled or if the profiler is disabled.

Parameters:

  profileName | Must be unique and must not be an empty string

Definition at line 281 of file OgreProfiler.cpp.

References Ogre::Profiler::ProfileInstance::accum, Ogre::Profiler::ProfileFrame::calls, Ogre::Profiler::ProfileHistory::currentTime, Ogre::Profiler::ProfileInstance::currTime, Ogre::Profiler::ProfileFrame::frameTime, Ogre::Timer::getMicroseconds(), Ogre::Profiler::ProfileInstance::hierarchicalLvl, Ogre::Profiler::ProfileHistory::hierarchicalLvl, Ogre::Profiler::ProfileFrame::hierarchicalLvl, Ogre::Profiler::ProfileHistory::maxTime, mDisabledProfiles, mEnabled, Ogre::Profiler::ProfileHistory::minTime, mProfileFrame, mProfileHistory, mProfileHistoryMap, mProfiles, mTimer, Ogre::Profiler::ProfileHistory::name, Ogre::Profiler::ProfileFrame::name, Ogre::Profiler::ProfileInstance::name, Ogre::Profiler::ProfileHistory::numCallsThisFrame, Ogre::Profiler::ProfileInstance::parent, Ogre::String, Ogre::Profiler::ProfileHistory::totalCalls, and Ogre::Profiler::ProfileHistory::totalTime.

Referenced by Ogre::Profile::Profile().

void Ogre::Profiler::changeEnableState | ( |  | ) | `[protected]`

| Handles a change of the profiler's enabled state. Definition at line 752 of file OgreProfiler.cpp. References Ogre::Overlay::hide(), mEnabled, mEnableStateChangePending, mNewEnableState, mOverlay, and Ogre::Overlay::show(). Referenced by endProfile().

GuiContainer * Ogre::Profiler::createContainer | ( |  | ) | `[protected]`

An internal function to create the container which will hold our display elements.

Definition at line 769 of file OgreProfiler.cpp.

References Ogre::GMM_PIXELS, mGuiHeight, mGuiWidth, Ogre::GuiElement::setHeight(), Ogre::GuiElement::setLeft(), Ogre::GuiElement::setMaterialName(), Ogre::GuiElement::setMetricsMode(), Ogre::StringInterface::setParameter(), Ogre::GuiElement::setTop(), and Ogre::GuiElement::setWidth().

Referenced by initialize().

GuiElement * Ogre::Profiler::createPanel | ( | const String & | name,
|  | Real | width,
|  | Real | height,
|  | Real | top,
|  | Real | left,
|  | const String & | materialName,
|  | bool | show = true
| ) | `[protected]`

An internal function to create a panel.

Definition at line 820 of file OgreProfiler.cpp.

References Ogre::GMM_PIXELS, Ogre::GuiElement::hide(), Ogre::Real, Ogre::GuiElement::setHeight(), Ogre::GuiElement::setLeft(), Ogre::GuiElement::setMaterialName(), Ogre::GuiElement::setMetricsMode(), Ogre::GuiElement::setTop(), Ogre::GuiElement::setWidth(), Ogre::GuiElement::show(), and Ogre::String.

Referenced by initialize().

GuiElement * Ogre::Profiler::createTextArea | ( | const String & | name,
|  | Real | width,
|  | Real | height,
|  | Real | top,
|  | Real | left,
|  | uint | fontSize,
|  | const String & | caption,
|  | bool | show = true
| ) | `[protected]`

An internal function to create a text area.

Definition at line 793 of file OgreProfiler.cpp.

References Ogre::GMM_PIXELS, Ogre::GuiElement::hide(), Ogre::Real, Ogre::GuiElement::setCaption(), Ogre::GuiElement::setHeight(), Ogre::GuiElement::setLeft(), Ogre::GuiElement::setMetricsMode(), Ogre::StringInterface::setParameter(), Ogre::GuiElement::setTop(), Ogre::GuiElement::setWidth(), Ogre::GuiElement::show(), Ogre::String, and Ogre::uint.

Referenced by initialize().

void Ogre::Profiler::disableProfile | ( | const String & | profileName | ) |

Disables a profile.

Remarks:
  Only disables the profile if this function is not called during the profile it is trying to disable.

Definition at line 232 of file OgreProfiler.cpp.

References mDisabledProfiles, mProfiles, and Ogre::String.

void Ogre::Profiler::displayResults | ( |  | ) | `[protected]`

Prints the profiling results of each frame.

Definition at line 549 of file OgreProfiler.cpp.

References Ogre::GMM_PIXELS, mBarHeight, mBarIndent, mCurrentFrame, mEnabled, mGuiBorderWidth, mGuiHeight, mGuiWidth, mProfileBars, mProfileGui, mProfileHistory, mUpdateDisplayFrequency, Ogre::Real, Ogre::GuiElement::setCaption(), Ogre::GuiElement::setHeight(), Ogre::GuiElement::setLeft(), Ogre::GuiElement::setMetricsMode(), Ogre::GuiElement::setTop(), Ogre::GuiElement::setWidth(), and Ogre::GuiElement::show().

Referenced by endProfile().

void Ogre::Profiler::enableProfile | ( | const String & | profileName | ) |

Enables a previously disabled profile.

Remarks:
  Only enables the profile if this function is not called during the profile it is trying to enable.

Definition at line 256 of file OgreProfiler.cpp.

References mDisabledProfiles, mProfiles, and Ogre::String.

void Ogre::Profiler::endProfile | ( | const String & | profileName | ) |

Ends a profile.

Remarks:
  Use the macro OgreProfileEnd(name) instead of calling this directly so that profiling can be ignored in the release version of your app.
  This function is usually not called directly unless you want a profile to last outside of its scope. In most cases, using the macro OgreProfile(name) which will call this function automatically when it goes out of scope. Make sure the name of this profile matches its corresponding beginProfile name. This function will be ignored for a profile that has been disabled or if the profiler is disabled.

Definition at line 393 of file OgreProfiler.cpp.

References Ogre::Profiler::ProfileInstance::accum, changeEnableState(), Ogre::Profiler::ProfileInstance::currTime, displayResults(), Ogre::Timer::getMicroseconds(), mDisabledProfiles, mEnabled, mProfileFrame, mProfiles, mTimer, mTotalFrameTime, Ogre::Profiler::ProfileInstance::name, Ogre::Profiler::ProfileInstance::parent, processFrameStats(), Ogre::String, and Ogre::ulong.

Referenced by Ogre::Profile::~Profile().

bool Ogre::Profiler::getEnabled | ( |  | ) | const

| Gets whether this profiler is enabled. Definition at line 226 of file OgreProfiler.cpp. References mEnabled.

Profiler & Ogre::Profiler::getSingleton | ( | void |  | ) | `[static]`

Override standard Singleton retrieval.

Remarks:
  Why do we do this? Well, it's because the Singleton implementation is in a .h file, which means it gets compiled into anybody who includes it. This is needed for the Singleton template to work, but we actually only want it compiled into the implementation of the class based on the Singleton, not all of them. If we don't change this, we get link errors when trying to use the Singleton-based class from an outside dll.

  This method just delegates to the template version anyway, but the implementation stays in this single compilation unit, preventing link errors.

Reimplemented from Ogre::Singleton< Profiler >.

Definition at line 58 of file OgreProfiler.cpp.

References Ogre::Singleton< Profiler >::ms_Singleton.

Referenced by Ogre::Profile::Profile(), and Ogre::Profile::~Profile().

Profiler * Ogre::Profiler::getSingletonPtr | ( | void |  | ) | `[static]`

Override standard Singleton retrieval.

Remarks:
  Why do we do this? Well, it's because the Singleton implementation is in a .h file, which means it gets compiled into anybody who includes it. This is needed for the Singleton template to work, but we actually only want it compiled into the implementation of the class based on the Singleton, not all of them. If we don't change this, we get link errors when trying to use the Singleton-based class from an outside dll.

  This method just delegates to the template version anyway, but the implementation stays in this single compilation unit, preventing link errors.

Reimplemented from Ogre::Singleton< Profiler >.

Definition at line 54 of file OgreProfiler.cpp.

References Ogre::Singleton< Profiler >::ms_Singleton.

Timer * Ogre::Profiler::getTimer | ( |  | ) |

| Retrieves the timer for the profiler. Definition at line 199 of file OgreProfiler.cpp. References mTimer.

uint Ogre::Profiler::getUpdateDisplayFrequency | ( |  | ) | const

| Gets the frequency that the Profiler display is updated. Definition at line 746 of file OgreProfiler.cpp. References mUpdateDisplayFrequency, and Ogre::uint.

void Ogre::Profiler::initialize | ( |  | ) | `[protected]`

Initializes the profiler's gui elements.

Definition at line 116 of file OgreProfiler.cpp.

References Ogre::Overlay::add2D(), Ogre::GuiContainer::addChild(), createContainer(), createPanel(), createTextArea(), maxProfiles, mBarHeight, mBarIndent, mBarLineWidth, mGuiBorderWidth, mGuiHeight, mGuiWidth, mOverlay, mProfileBars, mProfileGui, Ogre::Overlay::setZOrder(), Ogre::Overlay::show(), and Ogre::uint.

Referenced by setEnabled().

void Ogre::Profiler::logResults | ( |  | ) |

| Outputs current profile statistics to the log. Definition at line 702 of file OgreProfiler.cpp. References mProfileHistory, Ogre::String, and Ogre::uint. Referenced by ~Profiler().

void Ogre::Profiler::processFrameStats | ( |  | ) | `[protected]`

| Processes the profiler data after each frame. Definition at line 495 of file OgreProfiler.cpp. References mProfileFrame, mProfileHistory, mProfileHistoryMap, mTotalFrameTime, Ogre::Real, Ogre::String, Ogre::uint, and Ogre::ulong. Referenced by endProfile().

void Ogre::Profiler::reset | ( |  | ) |

| Clears the profiler statistics. Definition at line 726 of file OgreProfiler.cpp. References mProfileHistory.

void Ogre::Profiler::setEnabled | ( | bool | enabled | ) |

Sets whether this profiler is enabled.

Only takes effect after the the frame has ended.

Remarks:
  When this is called the first time with the parameter true, it initializes the GUI for the Profiler

Definition at line 206 of file OgreProfiler.cpp.

References initialize(), mEnabled, mEnableStateChangePending, mInitialized, and mNewEnableState.

void Ogre::Profiler::setTimer | ( | Timer * | t | ) |

| Sets the timer for the profiler. Definition at line 193 of file OgreProfiler.cpp. References mTimer.

void Ogre::Profiler::setUpdateDisplayFrequency | ( | uint | freq | ) |

| Sets the Profiler so the display of results are updated ever n frames. Definition at line 740 of file OgreProfiler.cpp. References mUpdateDisplayFrequency, and Ogre::uint.

bool Ogre::Profiler::watchForLimit | ( | const String & | profileName,
|  | Real | limit,
|  | bool | greaterThan = true
| ) |

Returns true if the specified profile goes over or under the given limit frame time.

Remarks:
  If this is called during a frame, it will be reading the results from the previous frame. Therefore, it is best to use this after the frame has ended.

Parameters:

  limit | A number between 0 and 1 representing the percentage of frame time
  greaterThan | If true, this will return whether the limit is exceeded. Otherwise, it will return if the frame time has gone under this limit.

Definition at line 682 of file OgreProfiler.cpp.

References mProfileHistoryMap, Ogre::Real, and Ogre::String.

bool Ogre::Profiler::watchForMax | ( | const String & | profileName | ) |

Returns true if the specified profile reaches a new frame time maximum.

Remarks:
  If this is called during a frame, it will be reading the results from the previous frame. Therefore, it is best to use this after the frame has ended.

Definition at line 648 of file OgreProfiler.cpp.

References mProfileHistoryMap, and Ogre::String.

bool Ogre::Profiler::watchForMin | ( | const String & | profileName | ) |

Returns true if the specified profile reaches a new frame time minimum.

Remarks:
  If this is called during a frame, it will be reading the results from the previous frame. Therefore, it is best to use this after the frame has ended.

Definition at line 665 of file OgreProfiler.cpp.

References mProfileHistoryMap, and Ogre::String.

## Member Data Documentation

uint Ogre::Profiler::maxProfiles`[protected]`

| The max number of profiles we can display. Definition at line 356 of file OgreProfiler.h. Referenced by initialize(), and Profiler().

Real Ogre::Profiler::mBarHeight`[protected]`

| The height of each bar. Definition at line 365 of file OgreProfiler.h. Referenced by displayResults(), and initialize().

Real Ogre::Profiler::mBarIndent`[protected]`

| The size of the indent for each profile display bar. Definition at line 374 of file OgreProfiler.h. Referenced by displayResults(), and initialize().

Real Ogre::Profiler::mBarLineWidth`[protected]`

| The width of the min, avg, and max lines in a profile display. Definition at line 380 of file OgreProfiler.h. Referenced by initialize().

uint Ogre::Profiler::mCurrentFrame`[protected]`

| The number of elasped frame, used with mUpdateDisplayFrequency. Definition at line 387 of file OgreProfiler.h. Referenced by displayResults(), and Profiler().

DisabledProfileMap Ogre::Profiler::mDisabledProfiles`[protected]`

| Holds the names of disabled profiles. Definition at line 347 of file OgreProfiler.h. Referenced by beginProfile(), disableProfile(), enableProfile(), endProfile(), and ~Profiler().

bool Ogre::Profiler::mEnabled`[protected]`

| Whether this profiler is enabled. Definition at line 396 of file OgreProfiler.h. Referenced by beginProfile(), changeEnableState(), displayResults(), endProfile(), getEnabled(), Profiler(), and setEnabled().

bool Ogre::Profiler::mEnableStateChangePending`[protected]`

| Keeps track of whether this profiler has received a request to be enabled/disabled. Definition at line 400 of file OgreProfiler.h. Referenced by changeEnableState(), Profiler(), and setEnabled().

Real Ogre::Profiler::mGuiBorderWidth`[protected]`

| The width of the border between the profile window and each bar. Definition at line 377 of file OgreProfiler.h. Referenced by displayResults(), and initialize().

Real Ogre::Profiler::mGuiHeight`[protected]`

| The height of the stats window. Definition at line 368 of file OgreProfiler.h. Referenced by createContainer(), displayResults(), and initialize().

Real Ogre::Profiler::mGuiWidth`[protected]`

| The width of the stats window. Definition at line 371 of file OgreProfiler.h. Referenced by createContainer(), displayResults(), and initialize().

bool Ogre::Profiler::mInitialized`[protected]`

| Whether the GUI elements have been initialized. Definition at line 353 of file OgreProfiler.h. Referenced by Profiler(), and setEnabled().

bool Ogre::Profiler::mNewEnableState`[protected]`

| Keeps track of the new enabled/disabled state that the user has requested which will be applied after the frame ends. Definition at line 404 of file OgreProfiler.h. Referenced by changeEnableState(), Profiler(), and setEnabled().

Overlay* Ogre::Profiler::mOverlay`[protected]`

| The overlay which contains our profiler results display. Definition at line 359 of file OgreProfiler.h. Referenced by changeEnableState(), and initialize().

ProfileBarList Ogre::Profiler::mProfileBars`[protected]`

| Holds the display bars for each profile results. Definition at line 350 of file OgreProfiler.h. Referenced by displayResults(), initialize(), and ~Profiler().

ProfileFrameList Ogre::Profiler::mProfileFrame`[protected]`

| Accumulates the results of each profile per frame (since a profile can be called more than once a frame). Definition at line 338 of file OgreProfiler.h. Referenced by beginProfile(), endProfile(), processFrameStats(), and ~Profiler().

GuiContainer* Ogre::Profiler::mProfileGui`[protected]`

| The window that displays the profiler results. Definition at line 362 of file OgreProfiler.h. Referenced by displayResults(), and initialize().

ProfileHistoryList Ogre::Profiler::mProfileHistory`[protected]`

| Keeps track of the statistics of each profile. Definition at line 341 of file OgreProfiler.h. Referenced by beginProfile(), displayResults(), logResults(), processFrameStats(), reset(), and ~Profiler().

ProfileHistoryMap Ogre::Profiler::mProfileHistoryMap`[protected]`

| We use this for quick look-ups of profiles in the history list. Definition at line 344 of file OgreProfiler.h. Referenced by beginProfile(), processFrameStats(), watchForLimit(), watchForMax(), watchForMin(), and ~Profiler().

ProfileStack Ogre::Profiler::mProfiles`[protected]`

| A stack for each individual profile per frame. Definition at line 334 of file OgreProfiler.h. Referenced by beginProfile(), disableProfile(), enableProfile(), endProfile(), and ~Profiler().

Profiler * Ogre::Singleton< Profiler >::ms_Singleton = 0`[static, protected, inherited]`

| Definition at line 53 of file OgreProfiler.cpp. Referenced by getSingleton(), and getSingletonPtr().

Timer* Ogre::Profiler::mTimer`[protected]`

| The timer used for profiling. Definition at line 390 of file OgreProfiler.h. Referenced by beginProfile(), endProfile(), getTimer(), Profiler(), and setTimer().

ulong Ogre::Profiler::mTotalFrameTime`[protected]`

| The total time each frame takes. Definition at line 393 of file OgreProfiler.h. Referenced by endProfile(), processFrameStats(), and Profiler().

uint Ogre::Profiler::mUpdateDisplayFrequency`[protected]`

| The number of frames that must elapse before the current frame display is updated. Definition at line 384 of file OgreProfiler.h. Referenced by displayResults(), getUpdateDisplayFrequency(), Profiler(), and setUpdateDisplayFrequency().

The documentation for this class was generated from the following files:

- OgreProfiler.h
- OgreProfiler.cpp

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:51:27 2004