Changeset 1372

Show
Ignore:
Timestamp:
02/14/08 22:31:01 (7 months ago)
Author:
bchoate
Message:

Initial work for performance logging.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-30/build/mt-dists/default.mk

    r1333 r1372  
    11PRODUCT_NAME = Movable Type Core 
    22 
    3 PRODUCT_VERSION = 4.1 
     3PRODUCT_VERSION = 4.11 
    44SCHEMA_VERSION = 4.0037 
    5 API_VERSION = 4.1 
     5API_VERSION = 4.11 
    66 
    77# BUILD_LANGUAGE = en_US 
  • branches/release-30/lib/MT.pm.pre

    r1308 r1372  
    856856    } 
    857857 
     858    if ($cfg->ProcessMemoryCommand) { 
     859        $mt->log_times(); 
     860    } 
     861 
    858862    $mt->set_language( $cfg->DefaultLanguage ); 
    859863 
     
    866870 
    867871    1; 
     872} 
     873 
     874{ 
     875my ($memory_start); 
     876sub log_times { 
     877    my $pkg = shift; 
     878 
     879    my $timer = $pkg->get_timer; 
     880    return unless $timer; 
     881 
     882    my $memory; 
     883    my $cmd = $pkg->config->ProcessMemoryCommand; 
     884    if ($cmd) { 
     885        my $re; 
     886        if (ref($cmd) eq 'HASH') { 
     887            $re = $cmd->{regex}; 
     888            $cmd = $cmd->{command}; 
     889        } 
     890        $cmd =~ s/\$\$/$$/g; 
     891        $memory = `$cmd`; 
     892        if ($re) { 
     893            if ($memory =~ m/$re/) { 
     894                $memory = $1; 
     895                $memory =~ s/\D//g; 
     896            } 
     897        } else { 
     898            $memory =~ s/\s+//gs; 
     899        } 
     900    } 
     901 
     902    # Called at the start of the process; so we're only recording 
     903    # the memory usage at the start of the app right now. 
     904    unless ($timer->{elapsed}) { 
     905        $memory_start = $memory; 
     906        return; 
     907    } 
     908 
     909    my $log_file; 
     910 
     911    # Log filename calcluation; changes daily, so we don't cache this 
     912    require File::Spec; 
     913    my $dir = File::Spec->catdir( MT->instance->static_file_path, 
     914        'support', 'logs'); 
     915    if (! -d $dir) { 
     916        require File::Path; 
     917        eval { File::Path::mkpath([$dir], 0, 0777) }; 
     918        if ($@) { 
     919            $log_file = 0; 
     920            return; 
     921        } 
     922    } 
     923    my @time = localtime(time); 
     924    my $file = sprintf("pl-%04d%02d%02d.log", $time[5] + 1900, $time[4]+1, $time[3]); 
     925    $log_file = File::Spec->catfile( $dir, $file ); 
     926 
     927    my $first_write = ! -f $log_file; 
     928 
     929    local *PERFLOG; 
     930    open PERFLOG, ">>$log_file"; 
     931    require Fcntl; 
     932    flock(PERFLOG, Fcntl::LOCK_EX()); 
     933 
     934    if ($first_write) { 
     935        require Config; 
     936        my ($osname, $osvers) = ($Config::Config{osname}, $Config::Config{osvers}); 
     937        print PERFLOG "# Operating System: $osname/$osvers\n"; 
     938        print PERFLOG "# Platform: $^O\n"; 
     939        my $ver = ref($^V) eq 'version' ? $^V->normal : ( $^V ? join('.', unpack 'C*', $^V) : $] ); 
     940        print PERFLOG "# Perl Version: $ver\n"; 
     941        print PERFLOG "# Web Server: $ENV{SERVER_SOFTWARE}\n"; 
     942        require MT::Object; 
     943        my $driver = MT::Object->driver; 
     944        if ($driver) { 
     945            my $dbh = $driver->r_handle; 
     946            if ($dbh) { 
     947                my $dbname = $dbh->get_info( 17 ); # SQL_DBMS_NAME 
     948                my $dbver = $dbh->get_info( 18 ); # SQL_DBMS_VER 
     949                if ($dbname && $dbver) { 
     950                    print PERFLOG "# Database: $dbname/$dbver\n"; 
     951                } 
     952            } 
     953        } 
     954        my ($drname, $drh) = each %DBI::installed_drh; 
     955        print PERFLOG "# Database Library: DBI/" . $DBI::VERSION . "; DBD/" . $drh->{Version} . "\n"; 
     956        if ($ENV{MOD_PERL}) { 
     957            print PERFLOG "# App Mode: mod_perl\n"; 
     958        } 
     959        elsif ($ENV{FAST_CGI}) { 
     960            print PERFLOG "# App Mode: FastCGI\n"; 
     961        } 
     962        else { 
     963            print PERFLOG "# App Mode: CGI\n"; 
     964        } 
     965    } 
     966 
     967    if ($memory) { 
     968        print PERFLOG $timer->dump_line("mem_start=$memory_start", "mem_end=$memory"); 
     969    } else { 
     970        print PERFLOG $timer->dump_line(); 
     971    } 
     972 
     973    close PERFLOG; 
     974} 
     975} 
     976 
     977sub get_timer { 
     978    my $mt = shift; 
     979    $mt = MT->instance unless ref $mt; 
     980    my $timer = $mt->request('timer'); 
     981    unless ($timer) { 
     982        my $uri; 
     983        if ($mt->isa('MT::App')) { 
     984            $uri = $mt->uri( args => { $mt->param_hash } ); 
     985        } 
     986        require MT::Util::ReqTimer; 
     987        $timer = MT::Util::ReqTimer->new( $uri ); 
     988        $mt->request('timer', $timer); 
     989    } 
     990    return $timer; 
     991} 
     992 
     993sub time_this { 
     994    my $mt = shift; 
     995    my ($str, $code) = @_; 
     996    my $timer = $mt->get_timer(); 
     997    my $ret; 
     998    if ($timer) { 
     999        $timer->pause_partial(); 
     1000        $ret = $code->(); 
     1001        $timer->mark($str); 
     1002    } else { 
     1003        $ret = $code->(); 
     1004    } 
     1005    return $ret; 
    8681006} 
    8691007 
     
    10771215    my $mt = shift; 
    10781216    my ($PluginSwitch, $use_plugins, $PluginPaths) = @_; 
     1217 
     1218    my $timer; 
     1219    if ($mt->config->PerformanceLogging) { 
     1220        $timer = $mt->get_timer(); 
     1221    } 
    10791222 
    10801223    foreach my $PluginPath (@$PluginPaths) { 
     
    11081251                    return 0 if exists $Plugins{$plugin_sig}; 
    11091252                    $Plugins{$plugin_sig}{full_path} = $plugin_full_path; 
     1253                    $timer->pause_partial if $timer; 
    11101254                    eval { require $plugin }; 
     1255                    $timer->mark("Loaded plugin " . $sig) if $timer; 
    11111256                    if ($@) { 
    11121257                        $Plugins{$plugin_sig}{error} = $@; 
     
    18672012    return $mt->error( 
    18682013        $mt->translate("Loading template '[_1]' failed.", $file)) unless $tmpl; 
    1869     $tmpl->{__file} = $file if $type eq 'filename'; 
    18702014    $mt->set_default_tmpl_params($tmpl); 
    18712015    $tmpl->param($param) if $param; 
  • branches/release-30/lib/MT/App.pm

    r1371 r1372  
    20492049    my $q = $app->param; 
    20502050 
     2051    my $timer; 
     2052    if ($app->config->PerformanceLogging) { 
     2053        $timer = $app->get_timer(); 
     2054        $timer->pause_partial(); 
     2055    } 
     2056 
    20512057    my($body); 
    20522058    eval { 
     
    22522258        } 
    22532259    } 
     2260 
     2261    if ($timer) { 
     2262        $timer->mark(ref($app) . '::run'); 
     2263    } 
     2264 
    22542265    $app->takedown(); 
    22552266} 
     
    23142325    require MT::Auth; 
    23152326    MT::Auth->release; 
     2327 
     2328    if ($app->config->PerformanceLogging) { 
     2329        $app->log_times(); 
     2330    } 
    23162331 
    23172332    $app->request->finish; 
  • branches/release-30/lib/MT/Builder.pm

    r1174 r1372  
    283283    #print STDERR syntree2str($tokens,0) unless $count++ == 1; 
    284284 
     285    my $timer; 
     286    if ($MT::DebugMode & 8) { 
     287        $timer = MT->get_timer(); 
     288    } 
     289 
    285290    if ($cond) { 
    286291        my %lcond; 
     
    331336            my($h, $type) = $ctx->handler_for($t->[0]); 
    332337            if ($h) { 
    333                 my $start; 
    334                 if ($MT::DebugMode & 8) { 
    335                     require Time::HiRes; 
    336                     $start = [ Time::HiRes::gettimeofday() ]; 
    337                 } 
     338                $timer->pause_partial if $timer; 
    338339                local($ctx->{__stash}{tag}) = $t->[0]; 
    339340                local($ctx->{__stash}{tokens}) = ref($tokens) ? bless $tokens, 'MT::Template::Tokens' : undef; 
     
    382383                    my $err = $ctx->errstr; 
    383384                    if (defined $err) { 
    384                         return $build->error(MT->translate("Error in <mt:[_1]> tag: [_2]", $t->[0], $ctx->errstr)); 
     385                        return $build->error(MT->translate("Error in <mt[_1]> tag: [_2]", $t->[0], $ctx->errstr)); 
    385386                    } 
    386387                    else { 
     
    402403                $res .= $out 
    403404                    if defined $out; 
    404                 if ($MT::DebugMode & 8) { 
    405                     my $elapsed = Time::HiRes::tv_interval($start); 
    406                     print STDERR "Builder: Tag [" . $t->[0] . "] - $elapsed seconds\n" if $elapsed > 0.25; 
     405 
     406                if ($timer) { 
     407                    $timer->mark("tag_" 
     408                        . lc($t->[0]) . args_to_string(\%args)); 
    407409                } 
    408410            } else { 
     
    417419} 
    418420 
     421sub args_to_string { 
     422    my ($args) = @_; 
     423    my $str = ''; 
     424    foreach my $a (keys %$args) { 
     425        next if $a eq '@'; 
     426        next unless defined $args->{$a}; 
     427        next if $args->{$a} eq ''; 
     428        $str .= ';' . $a . ':'; 
     429        if (ref $args->{$a} eq 'ARRAY') { 
     430            foreach my $aa (@{ $args->{$a} }) { 
     431                $aa = '...' if $aa =~ m/ /; 
     432                $str .= $aa . ';'; 
     433            } 
     434            chop($str); 
     435        } else { 
     436            $str .= $args->{$a} =~ m/ / ? '...' : $args->{$a}; 
     437        } 
     438    } 
     439    my $more_args = $args->{'@'}; 
     440    if ($more_args && @$more_args) { 
     441        foreach my $a (@$more_args) { 
     442            if (ref $a->[1] eq 'ARRAY') { 
     443                $str .= ' ' . $a->[0] . '='; 
     444                foreach my $aa (@{ $a->[1] }) { 
     445                    $aa = '...' if $aa =~ m/ /; 
     446                    $str .= $aa . ';'; 
     447                } 
     448                chop($str); 
     449            } else { 
     450                next if exists $args->{$a->[0]} 
     451                    && ($args->{$a->[0]} eq $a->[1]); 
     452                next unless defined $args->[1]; 
     453                next if $args->[1] eq ''; 
     454                $str .= ';' . $a->[0] . ':'; 
     455                $str .= $a->[1]; 
     456            } 
     457        } 
     458    } 
     459    return $str ne '' ? '[' . substr($str,1) . ']' : ''; 
     460} 
    4194611; 
    420462__END__ 
  • branches/release-30/lib/MT/Core.pm

    r1369 r1372  
    499499            # Basename settings 
    500500            'AuthorBansenameLimit' => { default => 30 }, 
     501            'PerformanceLogging' => { default => 0 }, 
     502            'PerformanceLoggingThreshold' => { default => 0.1 }, 
     503            'ProcessMemoryCommand' => { handler => \&ProcessMemoryCommand }, 
    501504        }, 
    502505        upgrade_functions => \&load_upgrade_fns, 
     
    801804} 
    802805 
     806sub ProcessMemoryCommand { 
     807    my $cfg = shift; 
     808    $cfg->set_internal( 'ProcessMemoryCommand', @_ ) if @_; 
     809    my $cmd = $cfg->get_internal('ProcessMemoryCommand'); 
     810    unless ($cmd) { 
     811        my $os = $^O; 
     812        if ($os eq 'darwin') { 
     813            $cmd = 'ps $$ -o rss='; 
     814        } 
     815        elsif ($os eq 'linux') { 
     816            $cmd = 'ps -p $$ -o rss='; 
     817        } 
     818        elsif ($os eq 'MSWin32') { 
     819            $cmd = { command => q{tasklist /FI "PID eq $$" /FO TABLE /NH}, 
     820                regex => qr/([\d,]+) K/ }; 
     821        } 
     822    } 
     823    return $cmd; 
     824} 
     825 
    803826sub SecretToken { 
    804827    my $cfg = shift; 
  • branches/release-30/lib/MT/Entry.pm

    r1174 r1372  
    222222sub __load_category_data { 
    223223    my $entry = shift; 
     224    my $t = MT->get_timer; 
     225    $t->pause_partial if $t; 
    224226    my $cache = MT::Memcached->instance; 
    225227    my $memkey = $entry->cache_key('categories'); 
     
    231233        $cache->set($memkey, $rows, CATEGORY_CACHE_TIME); 
    232234    } 
     235    $t->mark('MT::Entry::__load_category_data') if $t; 
    233236    return $rows; 
    234237} 
  • branches/release-30/lib/MT/Tag.pm

    r1208 r1372  
    325325sub __load_tags { 
    326326    my $obj = shift; 
     327    my $t = MT->get_timer; 
     328    $t->pause_partial if $t; 
     329 
    327330    if (!$obj->id) { 
    328331        $obj->{__tags} = []; 
     
    347350    } 
    348351    $obj->{__tags} = [ map { $_->name } @tags ]; 
     352    $t->mark('MT::Tag::__load_tags') if $t; 
    349353    $obj->{__tag_objects} = \@tags; 
    350354} 
     
    375379    my @tags = @{ $obj->{__tags} }; 
    376380    return 1 unless @tags; 
     381 
     382    my $t = MT->get_timer; 
     383    $t->pause_partial if $t; 
     384 
    377385    $obj->{__tag_objects} = []; 
    378386    my $blog_id = $obj->has_column('blog_id') ? $obj->blog_id : 0; 
     
    427435        MT::Memcached->instance->delete( $obj->tag_cache_key ); 
    428436    } 
     437    $t->mark('MT::Tag::save_tags') if $t; 
    429438    1; 
    430439} 
  • branches/release-30/lib/MT/Template.pm

    r1369 r1372  
    9191    $tmpl->{include_path} = $param{path}; 
    9292    $tmpl->{include_filter} = $param{filter}; 
     93    $tmpl->{__file} = $file; 
    9394    my $contents = $tmpl->load_file($file); 
    9495    if (defined $contents) { 
     
    211212    $ctx ||= $tmpl->context; 
    212213 
     214    my ($timer, $start); 
     215    if (MT->config->PerformanceLogging) { 
     216        $timer = MT->get_timer(); 
     217    } 
     218    local $timer->{elapsed} = 0 if $timer; 
     219 
    213220    local $ctx->{__stash}{template} = $tmpl; 
    214221    my $tokens = $tmpl->tokens 
     
    243250        $ctx->var( 'page_columns', $columns ) if $columns; 
    244251    } 
    245     defined(my $res = $build->build($ctx, $tokens, $cond)) or 
     252 
     253    $timer->pause_partial if $timer; 
     254 
     255    my $res = $build->build($ctx, $tokens, $cond); 
     256 
     257    if ($timer) { 
     258        $timer->mark("MT::Template::build[" . ($tmpl->name || $tmpl->{__file}).']'); 
     259    } 
     260 
     261    unless (defined($res)) { 
    246262        return $tmpl->error(MT->translate( 
    247263            "Publish error in template '[_1]': [_2]", 
    248264            $tmpl->name || $tmpl->{__file}, $build->errstr)); 
     265    } 
    249266    $res =~ s/^\s*//; 
    250267    return $res; 
  • branches/release-30/lib/MT/WeblogPublisher.pm

    r1365 r1372  
    12101210    my ( $blog, $root_path, $map, $at, $ctx, $cond, $build_static, %specifier ) 
    12111211      = @_; 
     1212 
    12121213    my $finfo; 
    12131214    my $archiver = $mt->archiver($at); 
     
    14081409    return 1 if ( $tmpl->build_dynamic ); 
    14091410    return 1 if ( $entry && $entry->status != MT::Entry::RELEASE() ); 
     1411 
     1412    my $timer = MT->get_timer; 
     1413    if ($timer) { 
     1414        $timer->pause_partial; 
     1415    } 
     1416    local $timer->{elapsed} = 0 if $timer; 
    14101417 
    14111418    if ( 
     
    14511458 
    14521459        $html = $tmpl->build( $ctx, $cond ); 
    1453         defined($html) 
    1454           or return $mt->error( 
     1460        unless (defined($html)) { 
     1461            $timer->unpause if $timer; 
     1462            return $mt->error( 
    14551463            ( 
    14561464                $category ? MT->translate( 
     
    14731481            ) 
    14741482          ); 
     1483        } 
    14751484        my $orig_html = $html; 
    14761485        MT->run_callbacks( 
     
    15061515        ## changed. If not, we won't update the published 
    15071516        ## file, so as not to modify the mtime. 
    1508         return 1 unless $fmgr->content_is_updated( $file, \$html ); 
     1517        unless ($fmgr->content_is_updated( $file, \$html )) { 
     1518            $timer->unpause if $timer; 
     1519            return 1; 
     1520        } 
    15091521 
    15101522        ## Determine if we need to build directory structure, 
     
    15161528          unless $path eq '/'; ## OS X doesn't like / at the end in mkdir(). 
    15171529        unless ( $fmgr->exists($path) ) { 
    1518             $fmgr->mkpath($path) 
    1519               or return $mt->trans_error( "Error making path '[_1]': [_2]", 
    1520                 $path, $fmgr->errstr ); 
     1530            if (!$fmgr->mkpath($path)) { 
     1531                $timer->unpause if $timer; 
     1532                return $mt->trans_error( "Error making path '[_1]': [_2]", 
     1533                    $path, $fmgr->errstr ); 
     1534            } 
    15211535        } 
    15221536 
     
    15281542        my $use_temp_files = !$mt->{NoTempFiles}; 
    15291543        my $temp_file = $use_temp_files ? "$file.new" : $file; 
    1530         defined( $fmgr->put_data( $html, $temp_file ) ) 
    1531           or return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
    1532             $temp_file, $fmgr->errstr ); 
     1544        unless ( defined $fmgr->put_data( $html, $temp_file ) ) { 
     1545            $timer->unpause if $timer; 
     1546            return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
     1547                $temp_file, $fmgr->errstr ); 
     1548        } 
    15331549        if ($use_temp_files) { 
    1534             $fmgr->rename( $temp_file, $file ) 
    1535               or return $mt->trans_error( 
    1536                 "Renaming tempfile '[_1]' failed: [_2]", 
    1537                 $temp_file, $fmgr->errstr ); 
     1550            if (!$fmgr->rename( $temp_file, $file )) { 
     1551                $timer->unpause if $timer; 
     1552                return $mt->trans_error( 
     1553                    "Renaming tempfile '[_1]' failed: [_2]", 
     1554                    $temp_file, $fmgr->errstr ); 
     1555            } 
    15381556        } 
    15391557        MT->run_callbacks( 
     
    15681586 
    15691587    } 
     1588    $timer->mark("total:rebuild_file[template_id:" . $tmpl->id . "]") 
     1589        if $timer; 
    15701590    1; 
    15711591} 
     
    16891709            $finfo->save(); 
    16901710        } 
     1711 
     1712        my $timer = MT->get_timer; 
     1713        if ($timer) { 
     1714            $timer->pause_partial; 
     1715        } 
     1716        local $timer->{elapsed} = 0 if $timer; 
    16911717 
    16921718        my $ctx = MT::Template::Context->new; 
     
    17151741 
    17161742        my $html = $tmpl->build($ctx); 
    1717         return $mt->error( $tmpl->errstr ) unless defined $html; 
     1743        unless (defined $html) { 
     1744            $timer->unpause if $timer; 
     1745            return $mt->error( $tmpl->errstr ); 
     1746        } 
    17181747 
    17191748        my $orig_html = $html; 
     
    17521781          unless $path eq '/';    ## OS X doesn't like / at the end in mkdir(). 
    17531782        unless ( $fmgr->exists($path) ) { 
    1754             $fmgr->mkpath($path) 
    1755               or return $mt->trans_error( "Error making path '[_1]': [_2]", 
    1756                 $path, $fmgr->errstr ); 
     1783            if (! $fmgr->mkpath($path) ) { 
     1784                $timer->unpause if $timer; 
     1785                return $mt->trans_error( "Error making path '[_1]': [_2]", 
     1786                    $path, $fmgr->errstr ); 
     1787            } 
    17571788        } 
    17581789 
     
    17601791        my $use_temp_files = !$mt->{NoTempFiles}; 
    17611792        my $temp_file = $use_temp_files ? "$file.new" : $file; 
    1762         defined( $fmgr->put_data( $html, $temp_file ) ) 
    1763           or return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
    1764             $temp_file, $fmgr->errstr ); 
     1793        unless (defined( $fmgr->put_data( $html, $temp_file ) )) { 
     1794            $timer->unpause if $timer; 
     1795            return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
     1796                $temp_file, $fmgr->errstr ); 
     1797        } 
    17651798        if ($use_temp_files) { 
    1766             $fmgr->rename( $temp_file, $file ) 
    1767               or 
    1768               return $mt->trans_error( "Renaming tempfile '[_1]' failed: [_2]", 
    1769                 $temp_file, $fmgr->errstr ); 
     1799            if (!$fmgr->rename( $temp_file, $file )) { 
     1800                $timer->unpause if $timer; 
     1801                return $mt->trans_error( "Renaming tempfile '[_1]' failed: [_2]", 
     1802                    $temp_file, $fmgr->errstr ); 
     1803            } 
    17701804        } 
    17711805        MT->run_callbacks( 
     
    17901824            file         => $file 
    17911825        ); 
     1826 
     1827        $timer->mark("total:rebuild_indexes[template_id:" . $tmpl->id . ";file:$file]") 
     1828            if $timer; 
    17921829    } 
    17931830    1;