Tema

Blog

Arquitectura cloud y AWS, Linux, DevOps, seguridad y desarrollo de software. Artículos técnicos escritos a partir de proyectos reales.

Uso excesivo de CPU al convertir imágenes con ImageMagick

Imagemagick-logo

En ciertas versiones de ImageMagick se da el problema (seguramente debido a un bug) de que cuando se intenta convertir o manipular una imagen, ya sea desde la línea de comandos (comando convert) o a través de una de las numerosas API’s existentes (por ejemplo PHP), el uso de CPU se dispara más allá del 100% (debido a que este problema se da en sistemas multiprocesador) haciendo que nuestro sistema se vuelva tremendamente lento. Aparte de este uso excesivo de CPU , el proceso de conversión se queda bloqueado, no alcanzando a terminar nunca. Esto ocurre incluso con imágenes pequeñas con un tamaño de pocos kilobytes.

Tras investigar el problema, hemos llegado a la conclusión de que efectivamente se trata de un bug en las versiones de ImageMagick compiladas con la opción –enable-openmp en máquinas con varios procesadores o varios cores.

Por tanto, lo primero que debemos hacer para saber si la solución de este artículo nos servirá, es comprobar si la máquina dispone de varios procesadores o de varios núcleos: Cómo saber cuántos procesadores y núcleos tiene una máquina Linux.

A continuación comprobaremos si nuestra versión de ImageMagick tiene activada la característica OpenMP.

~# convert --version
Version: ImageMagick 6.5.7-8 2010-12-02 Q16 https://www.imagemagick.org
Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC
Features: OpenMP

Si el comando anterior muestra la línea «Features: OpenMP» , entonces todo encaja y nuestro problema de carga excesiva de CPU puede solucionarse de tres formas distintas:

  1. Actualizando a una nueva versión de ImageMagick o a una anterior suficientemente estable que no presente el bug causante del problema.
  2. Recompilando ImageMagick con la opción –disable-openmp para que no se haga uso de la característica de multiprocesador.
  3. Forzando a ImageMagick a utilizar sólo uno de los núcleos disponibles en el sistema para realizar la conversión.

Esta última es quizás la mejor solución a nuestro problema, pues probablemente ya habremos probado a actualizar ImageMagick a otra versión, y en muchos casos lo habremos instalado como un paquete de alguna de las distribuciones Linux disponibles, por lo que no nos resultará viable volver a compilar. Hay que destacar que el procedimiento que se mostrará a continuación realmente no soluciona el problema, sino que se trata de un workaround , un «truco» que nos permitirá utilizar ImageMagick sin que se reproduzca el mal uso de los recursos del sistema.

Limitar el número de núcleos utilizado con MAGICK_THREAD_LIMIT

La forma de obligar a ImageMagick a utilizar un sólo núcleo o procesador a la hora de realizar una conversión de una imagen es utilizando la variable de entorno MAGICK_THREAD_LIMIT. Esta variable debe tener el valor 1 y estar disponible en el entorno de ejecución del comando convert. Para ello editaremos el fichero añadiremos al fichero /etc/environment la línea MAGICK_THREAD_LIMIT=1:

~# cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
LANG="es_ES.UTF-8"
LANGUAGE="es_ES.UTF-8"
MAGICK_THREAD_LIMIT=1

A continuación abriremos una nueva shell de comandos, ya que la actual no cargará dicha variable de entorno hasta que volvamos a iniciar sesión en el sistema.

Cómo establecer la variable MAGICK_THREAD_LIMIT en PHP

Si en lugar de utilizar ImageMagick desde la línea de comandos lo hacemos a través de las librerías disponibles para distintos lenguajes de programación como PHP , la solución anterior no funcionará y tendremos que cargar la variable MAGICK_THREAD_LIMIT=1 en el entorno de ejecución del intérprete PHP.

Nos estamos refiriendo siempre al caso de utilizar las funciones nativas que utilizaremos en nuestro código, como «$im = new Imagick(«file.png»);» o «$im- >readImageBlob($svgin);», ya que si realizamos la conversión a través del comando «system(‘convert -resize 800×600 file1.png file2.png’);» estaremos llamando al comando convert del mismo modo que en el apartado anterior, en cuyo caso la solución sí es válida.

PHP desde la línea de comandos

env MAGICK_THREAD_LIMIT=1 php test.php

PHP ejecutado desde módulo mod_fcgid de Apache

En este caso cargaríamos la variable MAGICK_THREAD_LIMIT del comando /usr/bin/php5-cgi , que normalmente es ejecutado por un script intermedio correspondiente a un virtualhost concreto de Apache, el llamado FCGIWrapper que podremos encontrar en el fichero vhosts.conf correspondiente:

<Files ~ (\.php)>
   SetHandler fcgid-script
   FCGIWrapper /var/www/cgi-bin/cgi_wrapper/cgi_wrapper .php
   Options +ExecCGI
   allow from all
</Files>

~# cat /var/www/cgi-bin/cgi_wrapper/cgi_wrapper
#! /bin/sh
export MAGICK_THREAD_LIMIT=1
exec /usr/bin/php5-cgi
CPU ImageMagick PHP
Daniel López Azaña

Sobre el autor

Daniel López Azaña

+25 años de experiencia Certificado AWS & GCP Especialista IA/LLM

Emprendedor tecnológico y arquitecto cloud con más de 25 años de experiencia transformando infraestructuras y automatizando procesos. Especialista en integración de IA/LLM, desarrollo con Rust y Python, y arquitectura AWS & GCP. Mente inquieta, generador de ideas y apasionado por la innovación tecnológica y la IA.

Artículos relacionados

Xorg icon

Cómo evitar que el fichero .xsession-errors alcance un tamaño enorme

El fichero .xsession-errors es un fichero de log que utiliza el sistema de ventanas X para registrar todos los errores que se producen en el entorno gráfico de Linux. Dado que todos los entornos de escritorio, ya sea Gnome, KDE, Cinnamon, XFCE, LXDE, etc., y todos los gestores de ventanas más livianos que no llegan a constituir un entorno de escritorio como FVWM, IceWM o Window Maker utilizan el sistema de ventanas X, al final cualquier aplicación gráfica que ejecutemos en nuestro ordenador puede provocar que se escriban mensajes de error en el fichero .xsession-errors, por lo que éste puede crecer de forma descontrolada hasta alcanzar fácilmente un tamaño muy grande de decenas de GB o incluso cientos si la capacidad de nuestro disco lo permite.

25 de junio de 2017
Ctrl+S

Desbloquear la línea de comandos de Linux tras pulsar Ctrl+s en Bash

Dado que la combinación de teclas Control+s es muy utilizada como atajo para la opción de Guardar ficheros en aplicaciones gráficas como editores de texto, editores de imágenes, navegadores web, etc. a veces nos traiciona el subconsciente cuando estamos trabajando desde la línea de comandos de Linux y utilizamos esa misma combinación de teclas cuando estamos por ejemplo editando un documento con Vim con la intención de guardarlo. A partir de ese momento observamos que ninguna tecla responde, la shell se ha bloqueado y ya no podemos hacer nada más en ella y nos entra un sudor frío porque no podemos acceder al documento que estábamos editando y no podemos salvar los cambios.

27 de abril de 2017
Wordpress multilingual site

Solucionando problemas de Qtranslate con la traducción del slug

A la hora de crear un sitio web multi-idioma basado en WordPress son básicamente dos las opciones que tenemos. Una implica crear páginas y artículos distintos, cada uno en su idioma, usando plugins del tipo de WPML, Polylang o xili-language. Otra introduce el contenido traducido en todos los idiomas que manejemos en el mismo post, separado por unas meta-etiquetas dentro del propio contenido, y es el propio plugin el que los separa en pestañas distintas dentro del editor de un único post existente.

16 de septiembre de 2014

Comentarios

Sé el primero en comentar

Enviar comentario

Se publicarán tu nombre y tu comentario. Tu correo no se publica y solo sirve para responderte. Detalles en la política de privacidad.