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, he 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:
- Actualizando a una nueva versión de ImageMagick o a una anterior suficientemente estable que no presente el bug causante del problema.
- Recompilando ImageMagick con la opción –disable-openmp para que no se haga uso de la característica de multiprocesador.
- 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.
Me estoy 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


Comentarios
Enviar comentario