📄 profile.pm
字号:
package DBI::Profile;=head1 NAMEDBI::Profile - Performance profiling and benchmarking for the DBI=head1 SYNOPSISThe easiest way to enable DBI profiling is to set the DBI_PROFILEenvironment variable to 2 and then run your code as usual: DBI_PROFILE=2 prog.plThis will profile your program and then output a textual summarygrouped by query. You can also enable profiling by setting theProfile attribute of any DBI handle: $dbh->{Profile} = 2;Other values are possible - see L<"ENABLING A PROFILE"> below.=head1 DESCRIPTIONDBI::Profile is new and experimental and subject to change.The DBI::Profile module provides a simple interface to collect andreport performance and benchmarking data from the DBI.For a more elaborate interface, suitable for larger programs, seeL<DBI::ProfileDumper|DBI::ProfileDumper> and L<dbiprof|dbiprof>.For Apache/mod_perl applications seeL<DBI::ProfileDumper::Apache|DBI::ProfileDumper::Apache>.=head1 OVERVIEWPerformance data collection for the DBI is built around severalconcepts which are important to understand clearly.=over 4=item Method DispatchEvery method call on a DBI handle passes through a single 'dispatch'function which manages all the common aspects of DBI method calls,such as handling the RaiseError attribute.=item Data CollectionIf profiling is enabled for a handle then the dispatch code takesa high-resolution timestamp soon after it is entered. Then, aftercalling the appropriate method and just before returning, it takesanother high-resolution timestamp and calls a function to recordthe information. That function is passed the two timestampsplus the DBI handle and the name of the method that was called.That information about a single DBI method call is called theI<profile sample> data.=item Data FilteringIf the method call was invoked by the DBI or by a driver then thecall is currently ignored for profiling because the time spent willbe accounted for by the original 'outermost' call.For example, the calls that the selectrow_arrayref() method makesto prepare() and execute() etc. are not counted individuallybecause the time spent in those methods is going to be allocatedto the selectrow_arrayref() method when it returns. If this was notdone then it would be very easy to double count time spent insidethe DBI.In future releases it may be possible to alter this behaviour.=item Data Storage TreeThe profile data is stored as 'leaves on a tree'. The 'path' throughthe branches of the tree to the particular leaf that will store theprofile sample data for a profiled call is determined dynamically.This is a powerful feature.For example, if the Path is [ 'foo', 'bar', 'baz' ]then the new profile sample data will be I<merged> into the tree at $h->{Profile}->{Data}->{foo}->{bar}->{baz}It wouldn't be very useful to merge all the call data into one leafnode (except to get an overall 'time spent inside the DBI' total).It's more common to want the Path to include the current statementtext and/or the name of the method called to show what the timespent inside the DBI was for.The Path can contain some 'magic cookie' values that are automaticallyreplaced by corresponding dynamic values when they're used.For example DBIprofile_Statement (exported by DBI::profile) isautomatically replaced by value of the C<Statement> attribute ofthe handle. For example, is the Path was: [ 'foo', DBIprofile_Statement, 'bar' ]and the value of $h->{Statement} was: SELECT * FROM tablenamethen the profile data will be merged into the tree at: $h->{Profile}->{Data}->{foo}->{SELECT * FROM tablename}->{bar}The default Path is just C<[ DBIprofile_Statement ]> and so bydefault the profile data is aggregated per distinct Statement string.For statement handles this is always simply the string that wasgiven to prepare() when the handle was created. For database handlesthis is the statement that was last prepared or executed on thatdatabase handle. That can lead to a little 'fuzzyness' because, forexample, calls to the quote() method to build a new statement willtypically be associated with the previous statement. In practicethis isn't a significant issue and the dynamic Path mechanism canbe used to setup your own rules.=item Profile DataProfile data is stored at the 'leaves' of the tree as referencesto an array of numeric values. For example: [ 106, # count 0.0312958955764771, # total duration 0.000490069389343262, # first duration 0.000176072120666504, # shortest duration 0.00140702724456787, # longest duration 1023115819.83019, # time of first event 1023115819.86576, # time of last event ]=back=head1 ENABLING A PROFILEProfiling is enabled for a handle by assigning to the Profileattribute. For example: $h->{Profile} = DBI::Profile->new();The Profile attribute holds a blessed reference to a hash objectthat contains the profile data and attributes relating to it.The class the Profile object is blessed into is expected toprovide at least a DESTROY method which will dump the profile datato the DBI trace file handle (STDERR by default).All these examples have the same effect as the first: $h->{Profile} = {}; $h->{Profile} = "DBI::Profile"; $h->{Profile} = "2/DBI::Profile"; $h->{Profile} = 2;If a non-blessed hash reference is given then the DBI::Profilemodule is automatically C<require>'d and the reference is blessedinto that class.If a string is given then it is split on 'C</>' characters and thefirst value is used to select the Path to be used (see below).The second value, if present, is used as the name of a module whichwill be loaded and it's C<new> method called. If not present itdefaults to DBI::Profile. Any other values are passed as argumentsto the C<new> method. For example: "C<2/DBIx::OtherProfile/Foo/42>".Various common sequences for Path can be selected by simply assigningan integer value to Profile. The simplest way to explain how thevalues are interpreted is to show the code: push @Path, "DBI" if $path & 0x01; push @Path, DBIprofile_Statement if $path & 0x02; push @Path, DBIprofile_MethodName if $path & 0x04; push @Path, DBIprofile_MethodClass if $path & 0x08;So using the value "C<1>" causes all profile data to be merged intoa single leaf of the tree. That's useful when you just want a total.Using "C<2>" causes profile sample data to be merged grouped bythe corresponding Statement text. This is the most frequently used.Using "C<4>" causes profile sample data to be merged grouped bythe method name ('FETCH', 'prepare' etc.). Using "C<8>" is similarbut gives the fully qualified 'glob name' of the method called. Forexample: '*DBD::Driver::db::prepare', '*DBD::_::st::fetchrow_hashref'.The values can be added together to create deeper paths. The mostuseful being 6 (statement then method name) or 10 (statement thenmethod name with class). Using a negative number will reverse thepath. Thus -6 will group by method name then statement.The spliting and parsing of string values assigned to the Profileattribute may seem a little odd, but there's a good reason for it.Remember that attributes can be embedded in the Data Source Namestring which can be passed in to a script as a parameter. Forexample: dbi:DriverName(RaiseError=>1,Profile=>2):dbnameAnd also, if the C<DBI_PROFILE> environment variable is set thenThe DBI arranges for every driver handle to share the same profileobject. When perl exits a single profile summary will be generatedthat reflects (as nearly as practical) the total use of the DBI bythe application.=head1 THE PROFILE OBJECTThe DBI core expects the Profile attribute value to be a hashreference and if the following values don't exist it will createthem as needed:=head2 DataA reference to a hash containing the collected profile data.=head2 PathThe Path value is used to control where the profile for a methodcall will be merged into the collected profile data. Wheneverprofile data is to be stored the current value for Path is used.The value can be one of:=over 4=item Array ReferenceEach element of the array defines an element of the path to use tostore the profile data into the C<Data> hash.=item Undefined value (the default)Treated the same as C<[ $DBI::Profile::DBIprofile_Statement ]>.=item Subroutine Reference B<NOT YET IMPLEMENTED>The subroutine is passed the DBI method name and the handle it wascalled on. It should return a list of values to uses as the path.If it returns an empty list then the method call is not profiled.=backThe following 'magic cookie' values can be included in the Path and will be=over 4=item DBIprofile_StatementReplaced with the current value of the Statement attribute for thehandle the method was called with. If that value is undefined thenan empty string is used.=item DBIprofile_MethodNameReplaced with the name of the DBI method that the profile samplerelates to.=item DBIprofile_MethodClassReplaced with the fully qualified name of the DBI method, includingthe package, that the profile sample relates to. This shows youwhere the method was implemented. For example: 'DBD::_::db::selectrow_arrayref' => 0.022902s 'DBD::mysql::db::selectrow_arrayref' => 2.244521s / 99 = 0.022445s avg (first 0.022813s, min 0.022051s, max 0.028932s)The "DBD::_::db::selectrow_arrayref" shows that the driver hasinherited the selectrow_arrayref method provided by the DBI.But you'll note that there is only one call toDBD::_::db::selectrow_arrayref but another 99 toDBD::mysql::db::selectrow_arrayref. That's because after the firstcall Perl has cached the method to speed up method calls.You may also see some names begin with an asterix ('C<*>').Both of these effects are subject to change in later releases.=backOther magic cookie values may be added in the future.=head1 REPORTING=head2 Report FormatThe current profile data can be formatted and output using print $h->{Profile}->format;To discard the profile data and start collecting fresh datayou can do: $h->{Profile}->{Data} = undef;The default results format looks like this: DBI::Profile: 0.001015s (5 calls) programname @ YYYY-MM-DD HH:MM:SS '' => 0.000024s / 2 = 0.000012s avg (first 0.000015s, min 0.000009s, max 0.000015s) 'SELECT mode,size,name FROM table' => 0.000991s / 3 = 0.000330s avg (first 0.000678s, min 0.000009s, max 0.000678s)Which shows the total time spent inside the DBI, with a count ofthe total number of method calls and the name of the script beingrun, then a formated version of the profile data tree.If the results are being formated when the perl process is exiting(which is usually the case when the DBI_PROFILE environment variableis used) then the percentage of time the process spent inside theDBI is also shown.In the example above the paths in the tree are only one level deep anduse the Statement text as the value (that's the default behaviour).The merged profile data at the 'leaves' of the tree are presentedas total time spent, count, average time spent (which is simply totaltime divided by the count), then the time spent on the first call,the time spent on the fastest call, and finally the time spent onthe slowest call.The 'avg', 'first', 'min' and 'max' times are not particularlyuseful when the profile data path only contains the statement text.Here's an extract of a more detailed example using both statementtext and method name in the path: 'SELECT mode,size,name FROM table' => 'FETCH' => 0.000076s 'fetchrow_hashref' => 0.036203s / 108 = 0.000335s avg (first 0.000490s, min 0.000152s, max 0.002786s)Here you can see the 'avg', 'first', 'min' and 'max' for the108 calls to fetchrow_hashref() become rather more interesting.Also the data for FETCH just shows a time value because it was onlycalled once.Currently the profile data is output sorted by branch names. Thatmay change in a later version so the leaf nodes are sorted by totaltime per leaf node.=head2 Report DestinationThe default method of reporting is for the DESTROY method of theProfile object to format the results and write them using: DBI->trace_msg($results, 0); # see $ON_DESTROY_DUMP below
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -