Daniel López Azaña

Tema

Social Media

Blog

GNU/Linux, Open Source, Cloud Computing, DevOps y más...

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, 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:

  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.

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
CPU ImageMagick PHP
Daniel López Azaña

Sobre el autor

Daniel López Azaña

Emprendedor tecnológico y arquitecto cloud con más de 20 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