Skip to content

Commit 7e534c9

Browse files
authored
feat: expose active no-signal probe timing (#375)
1 parent 125c5d2 commit 7e534c9

2 files changed

Lines changed: 35 additions & 12 deletions

File tree

inc/Workspace/Workspace.php

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6951,6 +6951,7 @@ private function build_active_no_signal_evidence_row( array $row, array &$github
69516951
'default_ref' => null,
69526952
'commits_outside_default' => null,
69536953
'upstream_equivalence' => null,
6954+
'probe_timings_ms' => array(),
69546955
'suggested_action' => 'insufficient_signal',
69556956
'reason' => 'not enough evidence gathered',
69566957
);
@@ -6961,44 +6962,44 @@ private function build_active_no_signal_evidence_row( array $row, array &$github
69616962
return $out;
69626963
}
69636964

6964-
$dirty = $this->probe_worktree_dirty_count( $path, self::CLEANUP_GIT_PROBE_TIMEOUT );
6965+
$dirty = $this->time_worktree_probe( $out['probe_timings_ms'], 'dirty_count', fn() => $this->probe_worktree_dirty_count( $path, self::CLEANUP_GIT_PROBE_TIMEOUT ) );
69656966
if ( is_wp_error( $dirty ) ) {
69666967
$out['dirty_error'] = $dirty->get_error_message();
69676968
} else {
69686969
$out['dirty'] = (int) $dirty;
69696970
}
69706971

6971-
$unpushed = $this->count_unpushed_commits( $path, self::CLEANUP_GIT_PROBE_TIMEOUT );
6972+
$unpushed = $this->time_worktree_probe( $out['probe_timings_ms'], 'unpushed_count', fn() => $this->count_unpushed_commits( $path, self::CLEANUP_GIT_PROBE_TIMEOUT ) );
69726973
if ( is_wp_error( $unpushed ) ) {
69736974
$out['unpushed_error'] = $unpushed->get_error_message();
69746975
} else {
69756976
$out['unpushed'] = (int) $unpushed;
69766977
}
69776978

69786979
$remote_ref = 'refs/remotes/origin/' . $branch;
6979-
$remote = $this->run_git( $primary_path, sprintf( 'rev-parse --verify --quiet %s', escapeshellarg( $remote_ref ) ), self::CLEANUP_GIT_PROBE_TIMEOUT );
6980+
$remote = $this->time_worktree_probe( $out['probe_timings_ms'], 'remote_tracking', fn() => $this->run_git( $primary_path, sprintf( 'rev-parse --verify --quiet %s', escapeshellarg( $remote_ref ) ), self::CLEANUP_GIT_PROBE_TIMEOUT ) );
69806981
$out['remote_tracking'] = ! is_wp_error( $remote ) && ! $this->is_git_timeout_error( $remote );
69816982

6982-
$default_ref = $this->resolve_remote_default_ref( $primary_path, self::CLEANUP_GIT_PROBE_TIMEOUT );
6983+
$default_ref = $this->time_worktree_probe( $out['probe_timings_ms'], 'default_ref', fn() => $this->resolve_remote_default_ref( $primary_path, self::CLEANUP_GIT_PROBE_TIMEOUT ) );
69836984
if ( is_string( $default_ref ) && '' !== $default_ref ) {
69846985
$out['default_ref'] = $default_ref;
6985-
$outside = $this->run_git(
6986+
$outside = $this->time_worktree_probe( $out['probe_timings_ms'], 'commits_outside_default', fn() => $this->run_git(
69866987
$primary_path,
69876988
sprintf( 'rev-list --count %s..%s', escapeshellarg( $default_ref ), escapeshellarg( 'refs/heads/' . $branch ) ),
69886989
self::CLEANUP_GIT_PROBE_TIMEOUT
6989-
);
6990+
) );
69906991
if ( ! is_wp_error( $outside ) && ! $this->is_git_timeout_error( $outside ) ) {
69916992
$out['commits_outside_default'] = (int) trim( (string) ( $outside['output'] ?? '' ) );
69926993
}
69936994

69946995
if ( (int) ( $out['dirty'] ?? 0 ) > 0 || (int) ( $out['unpushed'] ?? 0 ) > 0 ) {
6995-
$out['upstream_equivalence'] = $this->build_dirty_unpushed_upstream_equivalence_evidence( $primary_path, $path, $default_ref );
6996+
$out['upstream_equivalence'] = $this->time_worktree_probe( $out['probe_timings_ms'], 'upstream_equivalence', fn() => $this->build_dirty_unpushed_upstream_equivalence_evidence( $primary_path, $path, $default_ref ) );
69966997
}
69976998
}
69986999

6999-
$slug = $this->resolve_github_slug( $primary_path );
7000+
$slug = $this->time_worktree_probe( $out['probe_timings_ms'], 'github_slug', fn() => $this->resolve_github_slug( $primary_path ) );
70007001
if ( null !== $slug ) {
7001-
$pr = $this->find_pr_for_branch_direct( $slug, $branch, $github_cache, false );
7002+
$pr = $this->time_worktree_probe( $out['probe_timings_ms'], 'github_pr_lookup', fn() => $this->find_pr_for_branch_direct( $slug, $branch, $github_cache, false ) );
70027003
if ( is_wp_error( $pr ) ) {
70037004
$out['pr_error'] = $pr->get_error_message();
70047005
} elseif ( is_array( $pr ) ) {
@@ -7012,6 +7013,21 @@ private function build_active_no_signal_evidence_row( array $row, array &$github
70127013
return $out;
70137014
}
70147015

7016+
/**
7017+
* Time one worktree probe and record elapsed milliseconds by label.
7018+
*
7019+
* @param array<string,int> $timings Timing accumulator.
7020+
* @param string $label Probe label.
7021+
* @param callable $callback Probe callback.
7022+
* @return mixed
7023+
*/
7024+
private function time_worktree_probe( array &$timings, string $label, callable $callback ): mixed {
7025+
$started = microtime( true );
7026+
$result = $callback();
7027+
$timings[ $label ] = (int) round( ( microtime( true ) - $started ) * 1000 );
7028+
return $result;
7029+
}
7030+
70157031
/**
70167032
* Build diagnostic evidence for dirty/unpushed worktrees against remote default.
70177033
*
@@ -7049,9 +7065,10 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
70497065
'unknown' => 0,
70507066
'samples' => array(),
70517067
),
7068+
'probe_timings_ms' => array(),
70527069
);
70537070

7054-
$cherry = $this->run_git( $wt_path, sprintf( 'cherry %s HEAD', escapeshellarg( $default_ref ) ), self::CLEANUP_GIT_PROBE_TIMEOUT );
7071+
$cherry = $this->time_worktree_probe( $evidence['probe_timings_ms'], 'git_cherry', fn() => $this->run_git( $wt_path, sprintf( 'cherry %s HEAD', escapeshellarg( $default_ref ) ), self::CLEANUP_GIT_PROBE_TIMEOUT ) );
70557072
if ( ! is_wp_error( $cherry ) && ! $this->is_git_timeout_error( $cherry ) ) {
70567073
$lines = array_values( array_filter( array_map( 'trim', explode( "\n", (string) ( $cherry['output'] ?? '' ) ) ) ) );
70577074
foreach ( $lines as $line ) {
@@ -7066,13 +7083,13 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
70667083
$evidence['unpushed_patch_equivalent'] = 0 === (int) $evidence['unpushed_cherry']['unmatched'] && 0 === (int) $evidence['unpushed_cherry']['unknown'];
70677084
}
70687085

7069-
$tracked = $this->run_git( $wt_path, 'diff --name-only HEAD', self::CLEANUP_GIT_PROBE_TIMEOUT );
7086+
$tracked = $this->time_worktree_probe( $evidence['probe_timings_ms'], 'tracked_dirty_paths', fn() => $this->run_git( $wt_path, 'diff --name-only HEAD', self::CLEANUP_GIT_PROBE_TIMEOUT ) );
70707087
$paths = array();
70717088
if ( ! is_wp_error( $tracked ) && ! $this->is_git_timeout_error( $tracked ) ) {
70727089
$paths = array_merge( $paths, array_values( array_filter( array_map( 'trim', explode( "\n", (string) ( $tracked['output'] ?? '' ) ) ) ) ) );
70737090
}
70747091

7075-
$untracked = $this->run_git( $wt_path, 'ls-files --others --exclude-standard', self::CLEANUP_GIT_PROBE_TIMEOUT );
7092+
$untracked = $this->time_worktree_probe( $evidence['probe_timings_ms'], 'untracked_paths', fn() => $this->run_git( $wt_path, 'ls-files --others --exclude-standard', self::CLEANUP_GIT_PROBE_TIMEOUT ) );
70767093
if ( ! is_wp_error( $untracked ) && ! $this->is_git_timeout_error( $untracked ) ) {
70777094
foreach ( array_values( array_filter( array_map( 'trim', explode( "\n", (string) ( $untracked['output'] ?? '' ) ) ) ) ) as $path ) {
70787095
$paths[] = $path;
@@ -7086,6 +7103,7 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
70867103
$evidence['dirty_paths']['inspected'] = count( $inspect_paths );
70877104
$evidence['path_inspection_truncated'] = count( $paths ) > count( $inspect_paths );
70887105

7106+
$classification_started = microtime( true );
70897107
foreach ( $inspect_paths as $path ) {
70907108
$classification = $this->classify_dirty_path_against_default( $primary_path, $wt_path, $default_ref, $path );
70917109
$bucket = $classification['bucket'];
@@ -7104,6 +7122,7 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
71047122
$evidence['dirty_paths']['samples'][] = $classification;
71057123
}
71067124
}
7125+
$evidence['probe_timings_ms']['dirty_path_classification'] = (int) round( ( microtime( true ) - $classification_started ) * 1000 );
71077126

71087127
$evidence['effective_status'] = $this->classify_dirty_unpushed_effective_status( $evidence );
71097128

tests/smoke-worktree-metadata-reconcile.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,10 @@ function size_format( $bytes ): string {
522522
$assert( 'equivalent_clean', $active_rows['demo@equivalent-clean']['upstream_equivalence']['effective_status'] ?? '', 'dirty diagnostics classify patch-equivalent clean rows' );
523523
$assert( true, isset( $active_rows['demo@dirty-active']['elapsed_ms'] ), 'active/no-signal rows include elapsed timing' );
524524
$assert( true, isset( $active_report['summary']['slow_rows'][0]['elapsed_ms'] ), 'active/no-signal summary includes slow row timing samples' );
525+
$assert( true, isset( $active_rows['demo@dirty-active']['probe_timings_ms']['dirty_count'] ), 'active/no-signal rows include dirty probe timing' );
526+
$assert( true, isset( $active_rows['demo@dirty-active']['probe_timings_ms']['upstream_equivalence'] ), 'active/no-signal rows include upstream equivalence probe timing' );
527+
$assert( true, isset( $active_rows['demo@dirty-active']['upstream_equivalence']['probe_timings_ms']['git_cherry'] ), 'upstream equivalence includes git cherry probe timing' );
528+
$assert( true, isset( $active_rows['demo@dirty-active']['upstream_equivalence']['probe_timings_ms']['dirty_path_classification'] ), 'upstream equivalence includes dirty path classification timing' );
525529
$budgeted_active_report = $ws->worktree_active_no_signal_report( array( 'limit' => 20, 'offset' => 0, 'internal_budget_label' => '1s', 'internal_budget_seconds' => 1, 'internal_budget_started' => microtime( true ) - 1 ) );
526530
$assert( true, ! is_wp_error( $budgeted_active_report ) && ( $budgeted_active_report['success'] ?? false ), 'budgeted active/no-signal report succeeds' );
527531
$assert( true, (bool) ( $budgeted_active_report['pagination']['partial'] ?? false ), 'budgeted active/no-signal report returns partial pagination' );

0 commit comments

Comments
 (0)