|
<?php |
|
namespace AutoSizesBenchmarking; |
|
use WP_HTML_Tag_Processor; |
|
|
|
// Setup. |
|
|
|
$test_images = array( |
|
// Lazy-loaded responsive image which already has auto added. |
|
'<img src="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg" srcset="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg 300w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1024x768.jpg 1024w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-768x576.jpg 768w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1536x1152.jpg 1536w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-2048x1536.jpg 2048w" sizes="auto, (max-width: 650px) 100vw, 650px" loading="lazy">', |
|
// Lazy-loaded responsive image which should get auto added. |
|
'<img src="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg" srcset="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg 300w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1024x768.jpg 1024w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-768x576.jpg 768w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1536x1152.jpg 1536w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-2048x1536.jpg 2048w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">', |
|
// Eager-loaded responsive image with fetchpriority=high that should not get auto added. |
|
'<img src="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg" srcset="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg 300w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1024x768.jpg 1024w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-768x576.jpg 768w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-1536x1152.jpg 1536w, https://pd.w.org/2024/08/36566abfcb2952e20.99062056-2048x1536.jpg 2048w" sizes="(max-width: 650px) 100vw, 650px" fetchpriority="high">', |
|
// Non-responsive image which should not get auto added. |
|
'<img src="https://pd.w.org/2024/08/36566abfcb2952e20.99062056-300x225.jpg">', |
|
); |
|
|
|
global $argv; |
|
if ( isset( $argv[3] ) && is_numeric( $argv[3] ) && $argv[3] > 0 ) { |
|
$iterations = (int) $argv[3]; |
|
} else { |
|
$iterations = 1000; |
|
} |
|
|
|
function auto_sizes_update_content_img_tag_with_regex( $html ): string { |
|
if ( ! is_string( $html ) ) { |
|
$html = ''; |
|
} |
|
|
|
// Bail early if the image is not lazy-loaded. |
|
if ( false === strpos( $html, 'loading="lazy"' ) ) { |
|
return $html; |
|
} |
|
|
|
// Bail early if the image is not responsive. |
|
if ( 1 !== preg_match( '/sizes="([^"]+)"/', $html, $match ) ) { |
|
return $html; |
|
} |
|
|
|
// Don't add 'auto' to the sizes attribute if it already exists. |
|
if ( auto_sizes_attribute_includes_valid_auto( $match[1] ) ) { |
|
return $html; |
|
} |
|
|
|
$html = str_replace( 'sizes="', 'sizes="auto, ', $html ); |
|
|
|
return $html; |
|
} |
|
|
|
function auto_sizes_update_content_img_tag_with_html_tag_processor( $html ): string { |
|
if ( ! is_string( $html ) ) { |
|
$html = ''; |
|
} |
|
|
|
$processor = new WP_HTML_Tag_Processor( $html ); |
|
|
|
// Bail if there is no IMG tag. |
|
if ( ! $processor->next_tag( array( 'tag_name' => 'IMG' ) ) ) { |
|
return $html; |
|
} |
|
|
|
// Bail early if the image is not lazy-loaded. |
|
if ( 'lazy' !== $processor->get_attribute( 'loading' ) ) { |
|
return $html; |
|
} |
|
|
|
$sizes = $processor->get_attribute( 'sizes' ); |
|
|
|
// Bail early if the image is not responsive. |
|
if ( ! is_string( $sizes ) ) { |
|
return $html; |
|
} |
|
|
|
// Don't add 'auto' to the sizes attribute if it already exists. |
|
if ( auto_sizes_attribute_includes_valid_auto( $sizes ) ) { |
|
return $html; |
|
} |
|
|
|
$processor->set_attribute( 'sizes', "AUTO, $sizes" ); // Upper-case AUTO just to make it clear when this version is running. |
|
|
|
return $processor->get_updated_html(); |
|
} |
|
|
|
function auto_sizes_attribute_includes_valid_auto( string $sizes_attr ): bool { |
|
$token = strtok( strtolower( $sizes_attr ), ',' ); |
|
return false !== $token && 'auto' === trim( $token, " \t\f\r\n" ); |
|
} |
|
|
|
// Profiling. |
|
|
|
$regex_times = array(); |
|
$processor_times = array(); |
|
|
|
for ( $repetition = 0; $repetition <= $iterations; $repetition++ ) { |
|
foreach ( $test_images as $test_image ) { |
|
$time_start = hrtime( true ); |
|
auto_sizes_update_content_img_tag_with_regex( $test_image ); |
|
$time_end = hrtime( true ); |
|
$regex_times[] = $time_end - $time_start; |
|
|
|
$time_start = hrtime( true ); |
|
auto_sizes_update_content_img_tag_with_html_tag_processor( $test_image ); |
|
$time_end = hrtime( true ); |
|
$processor_times[] = $time_end - $time_start; |
|
} |
|
} |
|
|
|
$regex_times_avg = array_sum( $regex_times ) / $iterations; |
|
$processor_times_avg = array_sum( $processor_times ) / $iterations; |
|
|
|
echo "Average time spent for $iterations iterations:\n"; |
|
echo " Regex - $regex_times_avg\n"; |
|
echo " TagParser - $processor_times_avg\n"; |
|
printf( "TagParser is slower than Regex by %.2fx\n", $processor_times_avg/$regex_times_avg ); |