Changeset 1361

Show
Ignore:
Timestamp:
02/13/08 02:24:59 (22 months ago)
Author:
bchoate
Message:

Initial work for performance logging.

Location:
branches/mt4.11
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • branches/mt4.11/build/mt-dists/default.mk

    r1194 r1361  
    11PRODUCT_NAME = Movable Type Core 
    22 
    3 PRODUCT_VERSION = 4.1 
     3PRODUCT_VERSION = 4.11 
    44SCHEMA_VERSION = 4.0036 
    5 API_VERSION = 4.1 
     5API_VERSION = 4.11 
    66 
    77# BUILD_LANGUAGE = en_US 
  • branches/mt4.11/lib/MT.pm.pre

    r1275 r1361  
    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/mt4.11/lib/MT/App.pm

    r1174 r1361  
    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 { 
     
    22512257        } 
    22522258    } 
     2259 
     2260    if ($timer) { 
     2261        $timer->mark(ref($app) . '::run'); 
     2262    } 
     2263 
    22532264    $app->takedown(); 
    22542265} 
     
    23132324    require MT::Auth; 
    23142325    MT::Auth->release; 
     2326 
     2327    if ($app->config->PerformanceLogging) { 
     2328        $app->log_times(); 
     2329    } 
    23152330 
    23162331    $app->request->finish; 
  • branches/mt4.11/lib/MT/Builder.pm

    r1174 r1361  
    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/mt4.11/lib/MT/Core.pm

    r1242 r1361  
    496496            'UserpicMaxUpload' => { default => 0 }, 
    497497            'UserpicThumbnailSize' => { default => 100 }, 
     498 
     499            'PerformanceLogging' => { default => 0 }, 
     500            'PerformanceLoggingThreshold' => { default => 0.1 }, 
     501            'ProcessMemoryCommand' => { handler => \&ProcessMemoryCommand }, 
    498502        }, 
    499503        upgrade_functions => \&load_upgrade_fns, 
     
    795799} 
    796800 
     801sub ProcessMemoryCommand { 
     802    my $cfg = shift; 
     803    $cfg->set_internal( 'ProcessMemoryCommand', @_ ) if @_; 
     804    my $cmd = $cfg->get_internal('ProcessMemoryCommand'); 
     805    unless ($cmd) { 
     806        my $os = $^O; 
     807        if ($os eq 'darwin') { 
     808            $cmd = '/usr/bin/ps $$ -o rss='; 
     809        } 
     810        elsif ($os eq 'linux') { 
     811            $cmd = '/usr/bin/ps -p $$ -o rss='; 
     812        } 
     813        elsif ($os eq 'MSWin32') { 
     814            $cmd = { command => q{tasklist /FI "PID eq $$" /FO TABLE /NH}, 
     815                regex => qr/([\d,]+) K/ }; 
     816        } 
     817    } 
     818    return $cmd; 
     819} 
     820 
    797821sub SecretToken { 
    798822    my $cfg = shift; 
  • branches/mt4.11/lib/MT/Entry.pm

    r1174 r1361  
    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/mt4.11/lib/MT/Tag.pm

    r1208 r1361  
    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/mt4.11/lib/MT/Template.pm

    r1191 r1361  
    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        # $start = Time::HiRes::time(); 
     218    } else { 
     219        $timer = {}; 
     220    } 
     221    local $timer->{elapsed} = 0; 
     222 
    213223    local $ctx->{__stash}{template} = $tmpl; 
    214224    my $tokens = $tmpl->tokens 
     
    243253        $ctx->var( 'page_columns', $columns ) if $columns; 
    244254    } 
    245     defined(my $res = $build->build($ctx, $tokens, $cond)) or 
     255 
     256    $timer->pause_partial if $timer; 
     257 
     258    my $res = $build->build($ctx, $tokens, $cond); 
     259 
     260    if ($timer) { 
     261        # $timer->{prev} = $start; 
     262        $timer->mark("MT::Template::build[" . ($tmpl->name || $tmpl->{__file}).']'); 
     263    } 
     264 
     265    unless (defined($res)) { 
    246266        return $tmpl->error(MT->translate( 
    247267            "Publish error in template '[_1]': [_2]", 
    248268            $tmpl->name || $tmpl->{__file}, $build->errstr)); 
     269    } 
    249270    $res =~ s/^\s*//; 
    250271    return $res; 
  • branches/mt4.11/lib/MT/WeblogPublisher.pm

    r1254 r1361  
    11951195    my ( $blog, $root_path, $map, $at, $ctx, $cond, $build_static, %specifier ) 
    11961196      = @_; 
     1197 
    11971198    my $finfo; 
    11981199    my $archiver = $mt->archiver($at); 
     
    13931394    return 1 if ( $tmpl->build_dynamic ); 
    13941395    return 1 if ( $entry && $entry->status != MT::Entry::RELEASE() ); 
     1396 
     1397    my $timer = MT->get_timer; 
     1398    if ($timer) { 
     1399        $timer->pause_partial; 
     1400    } else { 
     1401        $timer = {}; 
     1402    } 
     1403    local $timer->{elapsed} = 0; 
    13951404 
    13961405    if ( 
     
    14361445 
    14371446        $html = $tmpl->build( $ctx, $cond ); 
    1438         defined($html) 
    1439           or return $mt->error( 
     1447        unless (defined($html)) { 
     1448            $timer->unpause if $timer; 
     1449            return $mt->error( 
    14401450            ( 
    14411451                $category ? MT->translate( 
     
    14581468            ) 
    14591469          ); 
     1470        } 
    14601471        my $orig_html = $html; 
    14611472        MT->run_callbacks( 
     
    14911502        ## changed. If not, we won't update the published 
    14921503        ## file, so as not to modify the mtime. 
    1493         return 1 unless $fmgr->content_is_updated( $file, \$html ); 
     1504        unless ($fmgr->content_is_updated( $file, \$html )) { 
     1505            $timer->unpause if $timer; 
     1506            return 1; 
     1507        } 
    14941508 
    14951509        ## Determine if we need to build directory structure, 
     
    15011515          unless $path eq '/'; ## OS X doesn't like / at the end in mkdir(). 
    15021516        unless ( $fmgr->exists($path) ) { 
    1503             $fmgr->mkpath($path) 
    1504               or return $mt->trans_error( "Error making path '[_1]': [_2]", 
    1505                 $path, $fmgr->errstr ); 
     1517            if (!$fmgr->mkpath($path)) { 
     1518                $timer->unpause if $timer; 
     1519                return $mt->trans_error( "Error making path '[_1]': [_2]", 
     1520                    $path, $fmgr->errstr ); 
     1521            } 
    15061522        } 
    15071523 
     
    15131529        my $use_temp_files = !$mt->{NoTempFiles}; 
    15141530        my $temp_file = $use_temp_files ? "$file.new" : $file; 
    1515         defined( $fmgr->put_data( $html, $temp_file ) ) 
    1516           or return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
    1517             $temp_file, $fmgr->errstr ); 
     1531        unless ( defined $fmgr->put_data( $html, $temp_file ) ) { 
     1532            $timer->unpause if $timer; 
     1533            return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
     1534                $temp_file, $fmgr->errstr ); 
     1535        } 
    15181536        if ($use_temp_files) { 
    1519             $fmgr->rename( $temp_file, $file ) 
    1520               or return $mt->trans_error( 
    1521                 "Renaming tempfile '[_1]' failed: [_2]", 
    1522                 $temp_file, $fmgr->errstr ); 
     1537            if (!$fmgr->rename( $temp_file, $file )) { 
     1538                $timer->unpause if $timer; 
     1539                return $mt->trans_error( 
     1540                    "Renaming tempfile '[_1]' failed: [_2]", 
     1541                    $temp_file, $fmgr->errstr ); 
     1542            } 
    15231543        } 
    15241544        MT->run_callbacks( 
     
    15531573 
    15541574    } 
     1575    $timer->mark("total:rebuild_file[template_id:" . $tmpl->id . "]") 
     1576        if $timer; 
    15551577    1; 
    15561578} 
     
    16741696            $finfo->save(); 
    16751697        } 
     1698 
     1699        my $timer = MT->get_timer; 
     1700        if ($timer) { 
     1701            $timer->pause_partial; 
     1702        } else { 
     1703            $timer = {}; 
     1704        } 
     1705        local $timer->{elapsed} = 0; 
    16761706 
    16771707        my $ctx = MT::Template::Context->new; 
     
    17001730 
    17011731        my $html = $tmpl->build($ctx); 
    1702         return $mt->error( $tmpl->errstr ) unless defined $html; 
     1732        unless (defined $html) { 
     1733            $timer->unpause if $timer; 
     1734            return $mt->error( $tmpl->errstr ); 
     1735        } 
    17031736 
    17041737        my $orig_html = $html; 
     
    17371770          unless $path eq '/';    ## OS X doesn't like / at the end in mkdir(). 
    17381771        unless ( $fmgr->exists($path) ) { 
    1739             $fmgr->mkpath($path) 
    1740               or return $mt->trans_error( "Error making path '[_1]': [_2]", 
    1741                 $path, $fmgr->errstr ); 
     1772            if (! $fmgr->mkpath($path) ) { 
     1773                $timer->unpause if $timer; 
     1774                return $mt->trans_error( "Error making path '[_1]': [_2]", 
     1775                    $path, $fmgr->errstr ); 
     1776            } 
    17421777        } 
    17431778 
     
    17451780        my $use_temp_files = !$mt->{NoTempFiles}; 
    17461781        my $temp_file = $use_temp_files ? "$file.new" : $file; 
    1747         defined( $fmgr->put_data( $html, $temp_file ) ) 
    1748           or return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
    1749             $temp_file, $fmgr->errstr ); 
     1782        unless (defined( $fmgr->put_data( $html, $temp_file ) )) { 
     1783            $timer->unpause if $timer; 
     1784            return $mt->trans_error( "Writing to '[_1]' failed: [_2]", 
     1785                $temp_file, $fmgr->errstr ); 
     1786        } 
    17501787        if ($use_temp_files) { 
    1751             $fmgr->rename( $temp_file, $file ) 
    1752               or 
    1753               return $mt->trans_error( "Renaming tempfile '[_1]' failed: [_2]", 
    1754                 $temp_file, $fmgr->errstr ); 
     1788            if (!$fmgr->rename( $temp_file, $file )) { 
     1789                $timer->unpause if $timer; 
     1790                return $mt->trans_error( "Renaming tempfile '[_1]' failed: [_2]", 
     1791                    $temp_file, $fmgr->errstr ); 
     1792            } 
    17551793        } 
    17561794        MT->run_callbacks( 
     
    17751813            file         => $file 
    17761814        ); 
     1815 
     1816        $timer->mark("total:rebuild_indexes[template_id:" . $tmpl->id . ";file:$file]") 
     1817            if $timer; 
    17771818    } 
    17781819    1;