2

Update: After debugging why the uploads were so slow, I found out the culript was the plugin WP Smush It. The question and answer bellow is the process of finding that out.

I'm processing thousands of image uploads through a custom Import function I've written. It takes a JSON, create a post out of it, then process the images URLs that are stored as JSON keys and uploads them to WordPress. It works fine, however, it's taking around 5 seconds to upload each image.

The images are stored locally, so WordPress only have to move the file, not download it.

Here's the timings for the upload image function:

  'uploadtimedebug_start' => 0 seconds
  'uploadtimedebug_after_requires' => 0.006 seconds
  'uploadtimedebug_after_tmp_filled' => 0.597 seconds
  'uploadtimedebug_before_media_handle_sideload' => 0.597 seconds
  'uploadtimedebug_after_media_handle_sideload' => 5.370 seconds // Guilty
  'uploadtimedebug_finish' => 5.370 seconds

Here's what media_handle_sideload looks like, and their parameters:

// Actually uploads the image
$id = media_handle_sideload( $file_array, $post_id, $desc);

Here is the parameters for media_handle_sideload:

[
    'file_array' => [
        'name' => 'logo.png',
        'tmp_name' => 'C:\\Users\\Lucas\\AppData\\Local\\Temp/logo-Rg0xrY.tmp'
    ],
    'post_id' => 881,
    'desc' => 'Logo',
];

Going inside media_handle_sideload and debugging it's timings, there's this:

  'timedebug_start' => 0 seconds
  'timedebug_before_wp_handle_sideload' => 0.001 seconds
  'timedebug_after_wp_handle_sideload' => 0.006 seconds
  'timedebug_before_wp_read_image_metadata' => 0.006 seconds
  'timedebug_after_wp_read_image_metadata' => 0.006 seconds
  'timedebug_before_wp_insert_attachment' => 0.006 seconds
  'timedebug_after_wp_insert_attachment' => 0.058 seconds
  'timedebug_before_wp_update_attachment_metadata' => 0.058 seconds
  'timedebug_after_wp_update_attachment_metadata' => 2.635 seconds // Guilty
  'timedebug_finish' => 2.635 seconds

So the slowliness is coming from wp_update_attachment_metadata. Digging into it, there's this:

  'timedebug_start' => 0 seconds
  'timedebug_after_get_post' => 0 seconds
  'timedebug_before_apply_filters_wp_update_attachment_metadata' => 0 seconds
  'timedebug_after_apply_filters_wp_update_attachment_metadata' => 3.082 seconds // Guilty
  'timedebug_before_update_post_meta' => 3.082 seconds
  'timedebug_after_update_post_meta' => 3.104 seconds

So, the great slowliness is coming from this:

/**
 * Filters the updated attachment meta data.
 *
 * @since 2.1.0
 *
 * @param array $data          Array of updated attachment meta data.
 * @param int   $attachment_id Attachment post ID.
 */
if ( $data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID ) )
    return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
else
    return delete_post_meta( $post->ID, '_wp_attachment_metadata' );

I couldn't find what add_filter('wp_update_attachment_metadata', $data, $post->ID) calls to debug it further.

Anyways.

Does anyone have any ideas on how to upload thousands of images to WordPress, while getting their attachment IDs in real time as a return?

PS: I've seen Add from Server plugin, but it doesn't meet what I need, because I have to assign the images by ID to specific custom fields, etc, so I need to process those and have their IDs in real time.

2

I've modified method wp_update_attachment_metadata from wp-includes/post.php (line 5070) to this, just during the Import:

/**
 * Update metadata for an attachment.
 *
 * @since 2.1.0
 *
 * @param int   $attachment_id Attachment post ID.
 * @param array $data          Attachment meta data.
 * @return int|bool False if $post is invalid.
 */
function wp_update_attachment_metadata( $attachment_id, $data ) {
    $attachment_id = (int) $attachment_id;
    if ( ! $post = get_post( $attachment_id ) ) {
        return false;
    }

    /**
     * Filters the updated attachment meta data.
     *
     * @since 2.1.0
     *
     * @param array $data          Array of updated attachment meta data.
     * @param int   $attachment_id Attachment post ID.
     */
     return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
}

Media Upload Before:

  'uploadtimedebug_start' => 0 seconds
  'uploadtimedebug_after_requires' => 0.006 seconds
  'uploadtimedebug_after_tmp_filled' => 0.597 seconds
  'uploadtimedebug_before_media_handle_sideload' => 0.597 seconds
  'uploadtimedebug_after_media_handle_sideload' => 5.370 seconds
  'uploadtimedebug_finish' => 5.370 seconds

Media Upload After:

  'uploadtimedebug_inicio' => 0 seconds
  'uploadtimedebug_after_requires' => 0.007 seconds
  'uploadtimedebug_after_tmp_filled' => 0.620 seconds
  'uploadtimedebug_before_media_handle_sideload' => 0.620 seconds
  'uploadtimedebug_after_media_handle_sideload' => 0.723 seconds
  'uploadtimedebug_finish' => 0.723 seconds

No side effects, everything works just fine. Keep in mind though, that this should be a temporary hack, when you're done uploading your thousand images, revert wp_update_attachment_metadata to it's original code.

Edit - Please ignore everything I said.

The culript was the plugin "Smush It", hooked into the wp_update_attachment_metadata filter. Upon disabling Smush It, the filter took zero seconds.

  • 2
    Are you running any plugins that hook into the wp_update_attachment_metadata filter ? – birgire Apr 20 '18 at 15:20
  • Oh my God, you're right. It was the plugin "Smush It", how did I let this pass?? >.> – Lucas Bustamante Apr 20 '18 at 15:37
  • I'm going to delete this question, it feels useless now – Lucas Bustamante Apr 20 '18 at 15:38
  • @birgire Just let me know when you see this so I can delete the question – Lucas Bustamante Apr 20 '18 at 15:39
  • Glad to hear you found the culprit plugin. I'm sure there are other users out there battling similar, so I don't think the question needs necessarily to be deleted. – birgire Apr 20 '18 at 15:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.