Soporte » Guías – Resolución de problemas » Carga lenta de imágenes en backend

  • Resuelto Mauricio Gelves

    (@mgelves)



    Buenas tardes amigos:

    Tengo una web heredada con más de 30Gb de imágenes.
    Cuando quiero cargar la página de medios en vista “Mosaico” tarda entre 5 y 8 segundos, dificultando muchísimo la carga de contenidos de mis clientes.

    Algunas acciones que he realizado:

    • La versión de WordPress está actualizada
    • He desactivado todos los plugins y sigue solo unos milisegundos menos
    • He revisado la consulta que hace a BBDD y se ejecuta rápidamente
    • Crear un índice extra, tal como lo sugiere este ticket en el TRAC, no solucionó mi problema.

    ¿Se os ocurre alguna prueba más que pueda realizar?

    ¡Gracias!
    Mauricio

Viendo 15 respuestas - 1 de 15 (de 15 total)
  • ATAlgaba

    (@atalgaba)

    Buenas tardes Mauricio,

    ¿Has probado a revisar el tiempo de carga por elementos? La forma más sencilla es usar la pestaña “Network” en las herramientas de desarrollador de Chrome/Firefox.

    Desde ahí podrías comprobar si lo que te está bloqueando la carga es el propio peso de las imágenes o bien de algún script. Aunque si me comentas que tiene 30gb en imágenes sólo… Habría que intentar localizar dónde se produce el bloqueo. Si es a nivel de server, en el cliente, mala optimización de las imagenes, etc.

    Un saludo,
    Antonio

    • Esta respuesta fue modificada hace 3 meses por  ATAlgaba.
    Pablo Moratinos

    (@pablo-moratinos)

    Hola Mauricio,
    He buscado algún caso parecido (yo tengo un problema similar a una escala menor) y aunque no he encontrado una solución efectiva, he descubierto una ñapa que puede mejorar la experiencia de usuario.

    Entiendo que el problema es especialmente incómodo cuando intentas añadir nuevas imágenes a una entrada y al abrir la biblioteca de medios se atasca cargando lentamente.

    El truco en cuestión consiste en que los medios se abran con el filtro “Subido a esta entrada” ya activado, lo que hace que la carga de medios este disponible mucho más rápido porque no consulta las imágenes subidas con anterioridad a este post. Evidentemente si tienes que usar un medio que ya se subió con anterioridad, no soluciona nada, pero si tienes que subirlo nuevo, es una gran avance.

    Te dejo enlace al código para añadir al functions: https://wordpress.stackexchange.com/questions/222583/how-can-i-speed-up-a-slow-loading-media-library

    Iván Expósito

    (@ivanexposito)

    Hola Mauricio.
    Cada caso es un mundo pero yo la última vez que vi algo parecido el problema se debía al tiempo de ejecución que los binarios de tratamiento de imágenes (librería GD, Imagemagik, etc…) consumían a la hora de crear el mosaico.
    Creo recordar que habían contribuido a mejorar la situación dos cosas: por un lado optimizar el tamaño de las imágenes que ya había guardadas (por ejemplo, con EWWW Image Optimizer). Al reducir su tamaño, al server le costaba menos esfuerzo manipularlas.
    Por otro lado, habíamos cambiado a una versión más reciente de PHP. Esto implicaba que las versiones de las librerías de tratamiento de imágenes también eran más nuevas y el proceso se realizaba de una forma más eficiente.
    No recuerdo si se había tomado alguna medida más. Fue un caso bastante antiguo y ahora mismo no me es posible recuperarlo, pero como medidas iniciales no cuesta mucho aplicarlas y en ningún caso van a perjudicar más.

    fpuenteonline

    (@fpuenteonline)

    Buenas tardes Mau.

    El problema no está en lo que ocupan las imágenes en disco, sino en la base de datos y en la vista “Mosaico”.
    Trato de explicarme. La diferencia entre la vista normal de la Librería y la vista Mosaico/Rejilla, es que está última está gestionada mediante peticiones AJAX, en concreto, peticiones a wp_ajax_query-attachments, que internamente son peticiones a la base de datos (ordenar por fecha descendente los attachments cada 40 elementos y paginarlos). Es decir, el tiempo de carga del admin-ajax.php (que podrás comprobar vía Chrome), seguramente sea el que esté tardando varios segundos en devolver la respuesta.
    Mi primera recomendación entonces es sanear en todo lo posible la tabla que contiene los attachments.
    Segunda recomendación es reducir la carga del admin-ajax.php eliminando todo lo posible el heartbeat (poco se va a notar esto)
    Para seguir depurando el problema, puedes hacerte tu propio wp_ajax_query-attachments y poner trazas para confirmar que el cuello de botella es la query. Te pego el código para ponerlo en tu functions o plugin de funcionalidades.

    add_action(‘wp_ajax_query-attachments’, ‘mauricio_wp_ajax_query_attachments’, 1);
    function mauricio_wp_ajax_query_attachments() {
    if ( ! current_user_can( ‘upload_files’ ) )
    wp_send_json_error();

    $query = isset( $_REQUEST[‘query’] ) ? (array) $_REQUEST[‘query’] : array();
    $keys = array(
    ‘s’, ‘order’, ‘orderby’, ‘posts_per_page’, ‘paged’, ‘post_mime_type’,
    ‘post_parent’, ‘post__in’, ‘post__not_in’, ‘year’, ‘monthnum’
    );
    foreach ( get_taxonomies_for_attachments( ‘objects’ ) as $t ) {
    if ( $t->query_var && isset( $query[ $t->query_var ] ) ) {
    $keys[] = $t->query_var;
    }
    }

    $query = array_intersect_key( $query, array_flip( $keys ) );
    $query[‘post_type’] = ‘attachment’;
    if ( MEDIA_TRASH
    && ! empty( $_REQUEST[‘query’][‘post_status’] )
    && ‘trash’ === $_REQUEST[‘query’][‘post_status’] ) {
    $query[‘post_status’] = ‘trash’;
    } else {
    $query[‘post_status’] = ‘inherit’;
    }

    if ( current_user_can( get_post_type_object( ‘attachment’ )->cap->read_private_posts ) )
    $query[‘post_status’] .= ‘,private’;

    // Filter query clauses to include filenames.
    if ( isset( $query[‘s’] ) ) {
    add_filter( ‘posts_clauses’, ‘_filter_query_attachment_filenames’ );
    }

    /**
    * Filters the arguments passed to WP_Query during an Ajax
    * call for querying attachments.
    *
    * @since 3.7.0
    *
    * @see WP_Query::parse_query()
    *
    * @param array $query An array of query variables.
    */
    $query = apply_filters( ‘ajax_query_attachments_args’, $query );
    $query = new WP_Query( $query );

    $posts = array_map( ‘wp_prepare_attachment_for_js’, $query->posts );
    $posts = array_filter( $posts );

    wp_send_json_success( $posts );
    }

    Si el cuello de botella, como supongo, es la WP_Query aunque sea insuficiente la limpieza en la base de datos, se puede establecer una estrategia de caché de esa consulta y guardarla por ejemplo en el transient (paginado), invalidando esa caché con un filtro cada vez que se añada un nuevo objeto a la librería. Esto mejoraría muchísimo a partir de la segunda consulta.

    Espero que las indicaciones te sirvan.

    Abrazo

    Mil gracias Fer, voy a probarlo esta tarde y compartiré los resultados.
    De ser así, lo dejaré escrito en blog para que quede más registro de la solución.

    Lo dicho, he probado en su momento la consulta a base de datos para ver si era necesario algún conjunto extra de índices, pero siempre tuve buenos resultados.

    Pruebo el código para ver si podemos dar con el problemilla.

    ¡¡¡Mil gracias a todos por los aportes!!!
    Mauricio

    Pablo Moratinos

    (@pablo-moratinos)

    Cuando lo escribas en el blog, compártelo aquí también, por favor. Para que quede documentado.

    Moderador erchache2000

    (@erchache2000)

    El problema reside en que el servidor web tira de imagemagick para realizar los thumbnails y lo hace cada vez que recarga la página. Con lo que se satura el servidor.

    Lo suyo es realizar una cache de los thumbnails para que solamente se generen una vez, así reduces la carga del servidor.

    He visto por internet un par de aproximaciones:

    1- Usando una libreria php externa, por ejemplo, http://phpthumb.sourceforge.net/

    2- Configurando el servidor web, pongo este ejemplo con nginx, supongo que será similar para apache. http://charlesleifer.com/blog/nginx-a-caching-thumbnailing-reverse-proxying-image-server-/

    Todo depende del tipo de servidor que uses y las posiblidades que tengas.

    Bueno, si se me ocurre otra cosa lo pongo.

    Suerte =D

    Primero muchas gracias a todos:

    @fpuenteonline: La consulta a BBDD no es el problema. Ya había interceptado el SQL que ejecuta para devolver las 40 filas y la misma tarda 0.0734s

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
    FROM wp_posts 
    WHERE 1=1 AND wp_posts.post_type = 'attachment' AND ((wp_posts.post_status = 'inherit' OR wp_posts.post_status = 'private'))
    ORDER BY wp_posts.post_date DESC
    LIMIT 80, 40

    Showing rows 80 - 119 (40 total, Query took 0.0734 seconds.)

    @erchache2000: ¿Cómo es eso que imagemagick regenera los thumnbnails con cada carga de la página?

    Saludos!
    Mauricio

    fpuenteonline

    (@fpuenteonline)

    ¿Has comprobado en las peticiones de esa página que es el admin-ajax.php el que tarda mucho en responder?

    Moderador erchache2000

    (@erchache2000)

    El código php hay que ejecutarlo cada vez que se carga la página web, por ser un lenguaje interpretado y no compilado.

    Para compilarlo se usa XCache o APC, con lo que aligera la carga de la página porque no tiene que reinterpretar el código el servidor web, sino que lo tiene “cacheado” al compilarlo.

    Pues con las imágenes pasa lo mismo, que hay que regenerar las miniaturas en cada carga.

    Para ello no queda otra que aplicar un sistema de cacheo, esto es, generándolas una vez y guardándolas, para evitar que el servidor web se colapse con cada carga.

    Hay varias maneras de hacerlo, ya las expuse arriba.

    Me explico? 😛

    Algo parecido sufrí yo hace tiempo.

    La biblioteca de medios utiliza el tamaño medio de la imagen para mostrar en pantalla y si el theme no tiene activo generar ese tamaño la biblioteca muestra el tamaño grande y de ahí al tamaño real. Echa un vistazo por ahí.

    Otra cosa que se me ocurre es que el Regenerate Thumbnails, si está instalado, se integra con la biblioteca y puede estár dando algún problema, hay un bug de hace unos meses sobre eso mismo:
    https://wordpress.org/support/topic/access-to-media-library-very-slow-after-update-3/

    ¡Muy buenos días gente!
    Me complace contaros que ya he encontrado la solución al problema.

    Resumen del problema: La petición AJAX coge las últimas 40 imágenes y de cada una de ellas hace X peticiones a la base de datos para devolver todos sus datos metas (X es la cantidad de minitaturas que la web tenga registrada). A su vez, de cada miniatura llama a una función para hacer cálculos de dimensiones (aunque no regenera nuevas imágenes es un proceso lento).

    Solución: Indicar a la función AJAX que solo busque la información del thumbnail (con eso alcanza y sobra para mostrar la galería).

    function mg_fix_select_only_thumbnails() {
    	return array(
    		'thumbnail' => __('Thumbnail'),
    	);
    }
    add_filter( 'image_size_names_choose', 'mg_fix_select_only_thumbnails' );

    Y en segundo lugar, vamos a utilizar un filtro para “acelerar” el proceso del cálculo de tamaño de imágenes que realiza la función “image_downsize()” en el fichero wp-includes/media.php:

    function mg_fix_scaled_image( $downsize, $attachment_id, $size ) {
    
    	// Retrieve the proper thumbnail version
    	remove_filter( 'image_downsize', 'mg_fix_scaled_image', 10 );
    	$result = wp_get_attachment_image_src( $attachment_id, $size );
    	add_filter( 'image_downsize', 'mg_fix_scaled_image', 10, 3 );
    
    	return $result;
    
    }
    add_filter('image_downsize', 'mg_fix_scaled_image', 10, 3);

    Prestad atención a esta función ya que desactivamos el mismo filtro, porque la función “wp_get_attachment_image_src()” lo invoca y entraríamos en un bucle infinito.
    Una vez terminada la función volvemos a setear el filtro.

    Espero que esto pueda ayudar a muchos.

    Un abrazo y mil gracias por vuestros aportes!
    Mauricio

    • Esta respuesta fue modificada hace 2 meses, 1 semana por  Mauricio Gelves.

    Dejo también el enlace al artículo que escribí al respecto: https://maugelves.com/galeria-de-medios-de-wordpress-va-muy-lento/

    Un saludo!
    Mauricio

    • Esta respuesta fue modificada hace 2 meses, 1 semana por  Mauricio Gelves.

    Uau! qué buena. Incluso merecería la pena un plugin con esto ¿no?
    De hecho casi da ganas de meterlo como MU porque es una optimización muy práctica en cualquier caso.

    @pablo-moratinos: No lo veo tan imprescindible.
    El tema es que en webs pequeñas ni se nota el tiempo de carga, es una solución solo para cuando ya la base de datos tiene un tamaño considerable. Caso contrario estarías limitando innecesariamente algunas miniaturas que pueden ser útiles.

    Abrazo!

Viendo 15 respuestas - 1 de 15 (de 15 total)
  • Debes estar registrado para responder a este tema.