chore: initial snapshot of 2meet-data-optimizer-hivepress-addon v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* HivePress hot-path benchmark — minimal before/after timing wrapper.
|
||||
*
|
||||
* Runs each provided sample query N times against a baseline (postmeta) and
|
||||
* a target (hot zone / shadow table) and returns elapsed times + ratio. No
|
||||
* fancy statistics — just `microtime(true)` deltas, mean, ratio.
|
||||
*
|
||||
* The CLI command (Sprint 4) will pass real production-like queries; for
|
||||
* unit tests we exercise the timing harness with synthetic callables that
|
||||
* sleep deterministically.
|
||||
*
|
||||
* Per Karpathy guideline: a stopwatch, not a profiler. Detailed trace
|
||||
* exists in `wpdo_benchmarks` table when callers want history.
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'TMDO_HivePress_Benchmark' ) ) {
|
||||
|
||||
/**
|
||||
* Minimal benchmark harness.
|
||||
*/
|
||||
final class TMDO_HivePress_Benchmark {
|
||||
|
||||
/** Default iteration count per sample. */
|
||||
public const DEFAULT_ITERATIONS = 50;
|
||||
|
||||
/**
|
||||
* Run a single sample comparison.
|
||||
*
|
||||
* Each callable is invoked $iterations times. Returns mean ms for
|
||||
* baseline, mean ms for target, and the speedup ratio (baseline/target).
|
||||
*
|
||||
* @param string $name Sample name (e.g. 'listing_search_5_filters').
|
||||
* @param callable $baseline Callable representing the postmeta path.
|
||||
* @param callable $target Callable representing the hot-zone path.
|
||||
* @param int $iterations Iteration count (default 50).
|
||||
*
|
||||
* @return array{name:string, baseline_ms:float, target_ms:float, ratio:float, iterations:int}
|
||||
*/
|
||||
public static function compare( string $name, callable $baseline, callable $target, int $iterations = self::DEFAULT_ITERATIONS ): array {
|
||||
$iterations = max( 1, $iterations );
|
||||
$baseline_ms = self::run( $baseline, $iterations );
|
||||
$target_ms = self::run( $target, $iterations );
|
||||
|
||||
return array(
|
||||
'name' => $name,
|
||||
'baseline_ms' => $baseline_ms,
|
||||
'target_ms' => $target_ms,
|
||||
'ratio' => $target_ms > 0.0 ? round( $baseline_ms / $target_ms, 2 ) : 0.0,
|
||||
'iterations' => $iterations,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a callable N times, return mean elapsed milliseconds.
|
||||
*
|
||||
* @param callable $callback Callable under test.
|
||||
* @param int $iterations Iteration count.
|
||||
*/
|
||||
public static function run( callable $callback, int $iterations ): float {
|
||||
$total = 0.0;
|
||||
for ( $i = 0; $i < $iterations; $i++ ) {
|
||||
$start = microtime( true );
|
||||
$callback();
|
||||
$total += ( microtime( true ) - $start ) * 1000.0;
|
||||
}
|
||||
return round( $total / $iterations, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a sequence of comparisons and produce a summary report.
|
||||
*
|
||||
* @param array<int,array{name:string, baseline:callable, target:callable, iterations?:int}> $samples Sample list.
|
||||
*
|
||||
* @return array{samples:array<int,array<string,mixed>>, geomean_ratio:float, sample_count:int}
|
||||
*/
|
||||
public static function run_suite( array $samples ): array {
|
||||
$results = array();
|
||||
$ratios = array();
|
||||
foreach ( $samples as $sample ) {
|
||||
if ( ! isset( $sample['name'], $sample['baseline'], $sample['target'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$result = self::compare(
|
||||
(string) $sample['name'],
|
||||
$sample['baseline'],
|
||||
$sample['target'],
|
||||
(int) ( $sample['iterations'] ?? self::DEFAULT_ITERATIONS )
|
||||
);
|
||||
$results[] = $result;
|
||||
if ( $result['ratio'] > 0.0 ) {
|
||||
$ratios[] = $result['ratio'];
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'samples' => $results,
|
||||
'geomean_ratio' => self::geometric_mean( $ratios ),
|
||||
'sample_count' => count( $results ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometric mean — preferred summary statistic for ratios because it
|
||||
* doesn't bias toward outliers like arithmetic mean does.
|
||||
*
|
||||
* @param array<int,float> $values Ratios.
|
||||
*/
|
||||
public static function geometric_mean( array $values ): float {
|
||||
if ( empty( $values ) ) {
|
||||
return 0.0;
|
||||
}
|
||||
$product = 1.0;
|
||||
foreach ( $values as $v ) {
|
||||
$product *= max( 0.0001, (float) $v );
|
||||
}
|
||||
return round( pow( $product, 1.0 / count( $values ) ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
} // end if ( ! class_exists )
|
||||
Reference in New Issue
Block a user