Support

Account

Home Forums General Issues What's faster?

Solved

What's faster?

  • Good evening!

    I’m actually generating my portfolio output.
    It’s basically a loop through all images of a gallery field, and for each images, I’m getting many other custom fields for that image (attachment).

    What’s faster code to execute?
    This? (A)

    $allPostMeta	= get_post_meta($id);
    $item1			= $allPostMeta['item1'][0];
    $item2			= $allPostMeta['item2'][0];
    $item3			= $allPostMeta['item3'][0];
    // […]
    $itemN			= $allPostMeta['itemN'][0];

    Or that? (B)

    $item1 = get_field('item1', $id);
    $item2 = get_field('item2', $id);
    $item3 = get_field('item3', $id);
    // […]
    $itemN = get_field('itemN', $id);

    My guess goes for (A), but the $allPostMeta array could contain a huge number of other meta I’ll never use, while the get_field() get exactly what I need but probably makes much more database requests?

    Thanks in advance.

  • (A) will be faster if you have a significant number of fields to get.

    I actually use a combination of the two.

    
    $allPostMeta	= get_post_meta($id);
    $item1 = get_field('item1', $id);
    $item2 = get_field('item2', $id);
    $item3 = get_field('item3', $id);
    // […]
    $itemN = get_field('itemN', $id);
    

    The reason is that the first statement makes WP get all of the meta values and put them in a cache, from that point on get_field() gets values from the WP cache and the ACF functions are easier for most people to use than trying to navigate a complicate array of meta data, especially if it might contain things like repeaters.

    As for gallery fields, and image fields, If you have many images then returning the image ID and getting specific image information based on the ID with standard WP functions like wp_get_attachment_image_src() https://developer.wordpress.org/reference/functions/wp_get_attachment_image/ will provide better performance than returning an image object/array in ACF.

  • Thanks a lot John!

    About the gallery fields, I’m telling ACF to return an array because I’m using others values than just the url (equivalent to wp_get_attachment_image_src()) like: filename, width, height.

  • Using get_post_meta($id); may not be faster for the gallery and images. A gallery stores an array of image ID and all the extra stuff that ACF returns in the array is not stored. So this will only marginally improve performance.

    When ACF returns the array it does a query to get all of the attachment posts in the array. It then does quite a bit of work to get the values that it returns in the array, including calling several WP functions that do additional queries.

    doing get_post_meta() at this point won’t improve performance because it’s already ACF has already done most of the queries.

    In the case of a gallery field I think something like this would be faster

    
    // the second false returns the unformatted value
    $gallery_array = get_feild('gallery', false, false); // 1 query
    foreach ($gallery_array as $id) {
      get_post_meta($id); // 1 query for each image
    }
    // at this point all meta data for all images 
    // should be stored in the cache.
    // now just use
    $gallery = get_field('gallery');
    

    Although I could be wrong with part of this, I did not follow all of the code all the way through to be sure, I think this would give you your biggest potential for performance gain.

  • Thanks again John, appreciated.

  • Hi again,

    Just to make things clearer for my brain ^^
    We started the topic talking about two differents datas: the gallery one, and the per attachment ones (when I loop through each image of the gallery)

    This is my original code (before speed considerations):

    $portfolioItems		= get_field('gallery'); // Getting the gallery field
    $hiddenMetadata		= get_field('metadata_to_hide');
    $imagesPerPage		= get_field('images_per_page');
    $hiddenCategories	= get_field('categories_to_hide');
    foreach ($portfolioItems as $item) {
    	// Getting current image informations
    	$id					= $item['ID'];
    	$filename			= $item['filename'];
    	$width				= $item['width'];
    	$height				= $item['height'];
    	$url				= $item['url'];
    	$alt				= htmlentities(urldecode($item['alt']), ENT_QUOTES);
    
    	// Getting current image custom attachement fields
    	$itemCustomFields	= get_post_meta($id);
    	$description		= $itemCustomFields['portfolio_description'][0];
    	$versionName		= $itemCustomFields['version_name'][0];
    	$reference			= $itemCustomFields['reference'][0];
    	$maxWidth			= (int)$itemCustomFields['max_available_width'][0];
    	$maxHeight			= (int)$itemCustomFields['max_available_height'][0];
    	$copyright			= $itemCustomFields['copyright'][0];
    	$rating				= $itemCustomFields['rating'][0];
    	// […]
    
    	// Building my output code here
    }

    Would this one be the optimized? (basically, it’s exactly the same, but with your 4 lines added at the beginning.

    $portfolioItemsForCache = get_field('gallery', false, false);
    foreach ($portfolioItemsForCache as $itemID) {
    	get_post_meta($itemID); // 1 query for each image
    } // at this point all meta data for all images should be stored in the cache
    $portfolioItems		= get_field('gallery'); // Getting the gallery field
    $hiddenMetadata		= get_field('metadata_to_hide');
    $imagesPerPage		= get_field('images_per_page');
    $hiddenCategories	= get_field('categories_to_hide');
    foreach ($portfolioItems as $item) {
    	// Getting current image informations
    	$id					= $item['ID'];
    	$filename			= $item['filename'];
    	$width				= $item['width'];
    	$height				= $item['height'];
    	$url				= $item['url'];
    	$alt				= htmlentities(urldecode($item['alt']), ENT_QUOTES);
    
    	// Getting current image custom attachement fields
    	$itemCustomFields	= get_post_meta($id);
    	$description		= $itemCustomFields['portfolio_description'][0];
    	$versionName		= $itemCustomFields['version_name'][0];
    	$reference			= $itemCustomFields['reference'][0];
    	$maxWidth			= (int)$itemCustomFields['max_available_width'][0];
    	$maxHeight			= (int)$itemCustomFields['max_available_height'][0];
    	$copyright			= $itemCustomFields['copyright'][0];
    	$rating				= $itemCustomFields['rating'][0];
    	// […]
    
    	// Building my output code here
    }
    

    Edit: oh, BTW, the last loads 6x slower than the first, so I’ve obviously messed things up ^^

  • Like I said, I could be wrong. If the code you’ve added is slower then I’d remove it. I’m not 100% sure of the entire sequence of events and Elliot has done a pretty good job of optimizing ACF over the years.

    Whenever I’m working on speed optimization I use this function in the footer of the page https://codex.wordpress.org/Function_Reference/get_num_queries. The only real improvements in WP you can make is by reducing the number of queries so if that what you’re trying to do then it’s always a good idea to see how many you’re doing.

  • Hi back,

    Ok, the 6 times slower thingy never happened again, so I’ll not take this in consideration.
    But what’s sure is the following:
    If I replace all $itemCustomFields['itemN'][0] thingy by get_field('itemN', $id), the page loading is about max 30% slower.
    So as you said before, get_post_meta($id) is indeed faster, but dealing with the returned data is way less easier then when using get_field.
    So I’ll decide depending the need.

    Sadly for the get_num_queries, I cannot see any difference since I’m calling my portfolio with Ajax. (or can I?)

  • Well, when dealing with AJAX, you can use the error log. Write anything you want to it and then look in the log.

    http://php.net/manual/en/function.error-log.php

    It’s a quick way to get information.

    With what you say about using get_field() being slower, it could very well be that more queries are being created. While your testing you might want to look at the difference between using get_field with the field name vs. the field key.

    This is all interesting

Viewing 9 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic.