How can a Delphi TForm / TPersistent object calculate its own construction and deserialization time?
For performance tests I need a way to measure the time needed for a form to load its definition from the DFM. All existing forms inherit a custom form class.
To capture the 开发者_JAVA百科current time, this base class needs overriden methods as "extension points":
- start of the deserialization process
- after the deserialization (can be implemented by overriding the
Loaded
procedure) - the moment just before the execution of the
OnFormCreate
event
So the log for TMyForm.Create(nil)
could look like:
- 00.000 instance created
- 00.010 before deserialization
- 01.823 after deserialization
- 02.340 before OnFormCreate
Which TObject (or TComponent) methods are best suited? Maybe there are other extension points in the form creation process, please feel free to make suggestions.
Background: for some of our app forms which have a very basic structure (with some PageControls and QuantumGrids) I realized that it is not database access and other stuff in OnFormShow but the construction which took most of the time (around 2 seconds) which makes me wonder where this time is spent. As a reference object I will also build a mock form which has a similar structure but no code or datamodule connections and measure its creation time.
The best place for "instance created" is TObject.NewInstance.
In Delphi 2009 the best place for "before deserialization" is TCustomForm.InitializeNewForm. If that isn't available override TCustomForm.CreateNew and grab the time immediately before it returns.
You're correct that the best place for "after deserialization" is TComponent.Loaded.
For "before OnFormCreate" override TObject.AfterConstructor and get the time immediately before calling the inherited method. If you want the total construction time, grab the final time after that inherited call returns. That will include both the OnFormCreate and any initial activation time. Alternatively, you could just override TForm.DoCreate, if you're not overriding that anywhere else.
Let's assume that the loading of the form's DFM is the main time part of the construction of the form, we could add a constructor to the form like:
constructor TMyForm.Create( AOwner: TComponent );
var
S, E: Int64;
begin
QueryPerformanceCounter( S );
inherited Create( AOwner ); // here is the dfm loading
QueryPerformanceCounter( E );
// Log using the classname and the time in QPC ticks.
LogQPCTime( ClassName, E - S );
end;
精彩评论