Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
|
|
@ -0,0 +1,340 @@
|
|||
<?php
|
||||
/**
|
||||
* Simple Speed Test Class
|
||||
*
|
||||
* Just runs queries and times them. No complexity.
|
||||
*
|
||||
* @package MaplePress_SearchSpeedTest
|
||||
*/
|
||||
|
||||
class MPSS_SpeedTest_Simple {
|
||||
|
||||
/**
|
||||
* Run speed test with specified number of queries.
|
||||
*
|
||||
* @param int $query_count Number of queries to run.
|
||||
* @param string $execution_mode Execution mode: 'serial' or 'parallel'.
|
||||
* @return array Results with timing data.
|
||||
*/
|
||||
public function run( $query_count = 10, $execution_mode = 'serial' ) {
|
||||
$start_time = microtime( true );
|
||||
|
||||
// Debug logging
|
||||
error_log( 'MPSS_SpeedTest_Simple::run() called with mode: ' . $execution_mode );
|
||||
|
||||
// Generate search queries
|
||||
$queries = $this->generate_queries( $query_count );
|
||||
|
||||
// Execute based on mode
|
||||
if ( $execution_mode === 'parallel' ) {
|
||||
error_log( 'MPSS: Executing in PARALLEL mode' );
|
||||
$results = $this->run_parallel( $queries );
|
||||
} else {
|
||||
error_log( 'MPSS: Executing in SERIAL mode' );
|
||||
$results = $this->run_serial( $queries );
|
||||
}
|
||||
|
||||
$end_time = microtime( true );
|
||||
$total_time = $end_time - $start_time;
|
||||
|
||||
// Calculate statistics
|
||||
$times = array_column( $results, 'duration_ms' );
|
||||
$avg_ms = array_sum( $times ) / count( $times );
|
||||
$min_ms = min( $times );
|
||||
$max_ms = max( $times );
|
||||
|
||||
return array(
|
||||
'results' => $results,
|
||||
'total_time' => round( $total_time, 2 ),
|
||||
'total_queries' => count( $results ),
|
||||
'avg_ms' => round( $avg_ms, 2 ),
|
||||
'min_ms' => round( $min_ms, 2 ),
|
||||
'max_ms' => round( $max_ms, 2 ),
|
||||
'mode' => $execution_mode,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run queries in serial mode (one at a time).
|
||||
*
|
||||
* @param array $queries Array of search query strings.
|
||||
* @return array Results array.
|
||||
*/
|
||||
private function run_serial( $queries ) {
|
||||
$results = array();
|
||||
|
||||
foreach ( $queries as $query ) {
|
||||
$query_start = microtime( true );
|
||||
|
||||
// Make HTTP request to search URL to properly trigger MaplePress hooks
|
||||
$search_url = home_url( '/?s=' . urlencode( $query ) );
|
||||
$response = wp_remote_get(
|
||||
$search_url,
|
||||
array(
|
||||
'timeout' => 30,
|
||||
'headers' => array(
|
||||
'X-MaplePress-Test' => '1',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$query_end = microtime( true );
|
||||
$duration_ms = ( $query_end - $query_start ) * 1000;
|
||||
|
||||
// Extract result count from response - try multiple patterns
|
||||
$result_count = 0;
|
||||
if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
|
||||
$body = wp_remote_retrieve_body( $response );
|
||||
|
||||
// Try various patterns to find result count
|
||||
$patterns = array(
|
||||
'/(\d+)\s+results?/i', // "5 results" or "1 result"
|
||||
'/found\s+(\d+)/i', // "Found 5"
|
||||
'/showing\s+(\d+)/i', // "Showing 5"
|
||||
'/<article/i', // Count article tags
|
||||
'/<div[^>]*class="[^"]*post[^"]*"/i', // Count post divs
|
||||
);
|
||||
|
||||
foreach ( $patterns as $pattern ) {
|
||||
if ( $pattern === '/<article/i' || strpos( $pattern, '<div' ) === 0 ) {
|
||||
// Count HTML elements
|
||||
$count = preg_match_all( $pattern, $body );
|
||||
if ( $count > 0 ) {
|
||||
$result_count = $count;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Extract number from text
|
||||
if ( preg_match( $pattern, $body, $matches ) ) {
|
||||
$result_count = intval( $matches[1] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results[] = array(
|
||||
'query' => $query,
|
||||
'duration_ms' => round( $duration_ms, 2 ),
|
||||
'result_count' => $result_count,
|
||||
);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run queries in parallel mode (multiple concurrent requests).
|
||||
*
|
||||
* @param array $queries Array of search query strings.
|
||||
* @return array Results array.
|
||||
*/
|
||||
private function run_parallel( $queries ) {
|
||||
error_log( 'MPSS: run_parallel called with ' . count( $queries ) . ' queries' );
|
||||
|
||||
$results = array();
|
||||
|
||||
// Build search URLs
|
||||
$search_urls = array();
|
||||
foreach ( $queries as $query ) {
|
||||
$search_urls[] = array(
|
||||
'url' => home_url( '/?s=' . urlencode( $query ) ),
|
||||
'query' => $query,
|
||||
);
|
||||
}
|
||||
|
||||
error_log( 'MPSS: Built ' . count( $search_urls ) . ' search URLs' );
|
||||
|
||||
// Initialize cURL multi handle
|
||||
$mh = curl_multi_init();
|
||||
$curl_handles = array();
|
||||
$request_info = array();
|
||||
|
||||
// Add all requests to multi handle
|
||||
foreach ( $search_urls as $index => $search_data ) {
|
||||
$ch = curl_init();
|
||||
curl_setopt( $ch, CURLOPT_URL, $search_data['url'] );
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
||||
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
|
||||
curl_setopt( $ch, CURLOPT_TIMEOUT, 30 );
|
||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
|
||||
'X-MaplePress-Test: 1',
|
||||
) );
|
||||
|
||||
curl_multi_add_handle( $mh, $ch );
|
||||
$ch_id = (int) $ch;
|
||||
$curl_handles[ $ch_id ] = $ch;
|
||||
$request_info[ $ch_id ] = array(
|
||||
'query' => $search_data['query'],
|
||||
'index' => $index,
|
||||
'start_time' => null,
|
||||
'end_time' => null,
|
||||
);
|
||||
}
|
||||
|
||||
error_log( 'MPSS: Added ' . count( $curl_handles ) . ' handles, request_info has ' . count( $request_info ) . ' entries' );
|
||||
|
||||
// Execute all queries simultaneously and track start/end times
|
||||
$running = null;
|
||||
|
||||
// Record start time for ALL requests (they all start together)
|
||||
$batch_start = microtime( true );
|
||||
foreach ( $request_info as $ch_id => $info ) {
|
||||
$request_info[ $ch_id ]['start_time'] = $batch_start;
|
||||
}
|
||||
|
||||
// Start executing - all requests run concurrently
|
||||
do {
|
||||
curl_multi_exec( $mh, $running );
|
||||
|
||||
// Check for completed requests and record their end time
|
||||
while ( $done = curl_multi_info_read( $mh ) ) {
|
||||
if ( $done['msg'] == CURLMSG_DONE ) {
|
||||
$ch_id = (int) $done['handle'];
|
||||
// Record when THIS specific request finished
|
||||
if ( ! isset( $request_info[ $ch_id ]['end_time'] ) ) {
|
||||
$request_info[ $ch_id ]['end_time'] = microtime( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $running > 0 ) {
|
||||
curl_multi_select( $mh );
|
||||
}
|
||||
} while ( $running > 0 );
|
||||
|
||||
$batch_end = microtime( true );
|
||||
$batch_duration_ms = ( $batch_end - $batch_start ) * 1000;
|
||||
|
||||
error_log( 'MPSS: Batch completed in ' . round( $batch_duration_ms, 2 ) . 'ms, processing ' . count( $request_info ) . ' results' );
|
||||
|
||||
// Collect results - calculate duration from start/end times
|
||||
foreach ( $request_info as $ch_id => $info ) {
|
||||
$ch = $curl_handles[ $ch_id ];
|
||||
|
||||
// Calculate duration from start to end time
|
||||
if ( isset( $info['start_time'] ) && isset( $info['end_time'] ) ) {
|
||||
$duration_seconds = $info['end_time'] - $info['start_time'];
|
||||
$duration_ms = $duration_seconds * 1000;
|
||||
|
||||
// Debug: log a few samples
|
||||
static $debug_count = 0;
|
||||
if ( $debug_count < 3 ) {
|
||||
error_log( sprintf(
|
||||
'MPSS: Sample #%d - start=%.6f, end=%.6f, duration_sec=%.6f, duration_ms=%.2f',
|
||||
$debug_count,
|
||||
$info['start_time'],
|
||||
$info['end_time'],
|
||||
$duration_seconds,
|
||||
$duration_ms
|
||||
) );
|
||||
$debug_count++;
|
||||
}
|
||||
} else {
|
||||
// Fallback - shouldn't happen
|
||||
$duration_ms = 0;
|
||||
}
|
||||
|
||||
$curl_info = curl_getinfo( $ch );
|
||||
$response = curl_multi_getcontent( $ch );
|
||||
$http_code = $curl_info['http_code'];
|
||||
|
||||
// Extract result count using multiple patterns
|
||||
$result_count = 0;
|
||||
if ( $http_code === 200 && ! empty( $response ) ) {
|
||||
$patterns = array(
|
||||
'/(\d+)\s+results?/i',
|
||||
'/found\s+(\d+)/i',
|
||||
'/showing\s+(\d+)/i',
|
||||
'/<article/i',
|
||||
'/<div[^>]*class="[^"]*post[^"]*"/i',
|
||||
);
|
||||
|
||||
foreach ( $patterns as $pattern ) {
|
||||
if ( $pattern === '/<article/i' || strpos( $pattern, '<div' ) === 0 ) {
|
||||
$count = preg_match_all( $pattern, $response );
|
||||
if ( $count > 0 ) {
|
||||
$result_count = $count;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ( preg_match( $pattern, $response, $matches ) ) {
|
||||
$result_count = intval( $matches[1] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results[ $info['index'] ] = array(
|
||||
'query' => $info['query'],
|
||||
'duration_ms' => round( $duration_ms, 2 ),
|
||||
'result_count' => $result_count,
|
||||
);
|
||||
|
||||
curl_multi_remove_handle( $mh, $ch );
|
||||
curl_close( $ch );
|
||||
}
|
||||
|
||||
curl_multi_close( $mh );
|
||||
|
||||
// Sort results by original index to maintain query order
|
||||
ksort( $results );
|
||||
|
||||
return array_values( $results );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random search queries from existing content.
|
||||
*
|
||||
* @param int $count Number of queries to generate.
|
||||
* @return array Array of search query strings.
|
||||
*/
|
||||
private function generate_queries( $count ) {
|
||||
error_log( 'MPSS: generate_queries called with count=' . $count );
|
||||
|
||||
$posts = get_posts(
|
||||
array(
|
||||
'post_type' => array( 'post', 'page' ),
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $count * 3,
|
||||
'orderby' => 'rand',
|
||||
)
|
||||
);
|
||||
|
||||
error_log( 'MPSS: get_posts returned ' . count( $posts ) . ' posts' );
|
||||
|
||||
$queries = array();
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
if ( count( $queries ) >= $count ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Get words from title
|
||||
$words = array_filter( explode( ' ', $post->post_title ) );
|
||||
|
||||
if ( empty( $words ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 50% single word, 50% two words
|
||||
if ( mt_rand( 1, 2 ) === 1 || count( $words ) === 1 ) {
|
||||
$queries[] = $words[ array_rand( $words ) ];
|
||||
} else {
|
||||
$start = mt_rand( 0, count( $words ) - 2 );
|
||||
$queries[] = $words[ $start ] . ' ' . $words[ $start + 1 ];
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have enough, pad with generic searches
|
||||
while ( count( $queries ) < $count ) {
|
||||
$queries[] = 'test';
|
||||
}
|
||||
|
||||
$final_queries = array_slice( $queries, 0, $count );
|
||||
error_log( 'MPSS: generate_queries returning ' . count( $final_queries ) . ' queries' );
|
||||
|
||||
return $final_queries;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue