Decimales del número e por Taylor

Tanto Jhon von Neumann como Steve Wozniack hicieron el ejercicio de encontrar miles de decimales del número e, en el ENIAC (uno de los primeros ordenadores de propósito general) y en un Apple II, respectivamente. Si personas de tan elevado tamaño intelectual consideraron oportuno hacerlo, ¿quién soy yo para contrariarlos? Así que, salvando las distancias, me he decidido a hacerlo.

El método empleado han sido las series de Taylor. Para el mismo, se requiere calcular el factorial, la siguiente función recursiva lo calcula para el número recibido como parámetro:

function factorial(a) {
  if (a === 0) {
      return 1;
  }else{
      return a * factorial(a - 1);
  }
}

El siguiente código Javascript calcula, a partir del polinomio de Taylor1 de grado 20 en torno al punto a=0, es decir, e1, unos cuantos decimales:

function factorial(a) {
  if (a === 0) {
      return 1;
  }else{
      return a * factorial(a - 1);
  }
}

var e = 1;

for (i = 1; i <= 19; i++) {
   e = e + 1/factorial(i);
}
console.log(e);

El lector puede copiar el código y ejecutarlo en el mismo navegador con el que está leyendo este artículo, presionando F12 y accediendo a la consola:

Decimales de e en Javascript por Taylor

Decimales de e en Javascript por Taylor. Ejecutado en Firefox.

Por culpa del uso de la coma flotante que hace Javascript (ya incluido en el microprocesador), no podemos sacar más decimales, pues el resultado será redondeado al que vemos en la imagen. Para salvar este inconveniente, en PHP existe la librería BC Math, que nos permite trabajar con números de – casi – cualquier tamaño y precisión. Para que después digan que es un lenguaje de juguete… Éste es el código:

<?php

function factorial($a) {
  if ($a === 0) {
      return 1;
  }else{
      return bcmul($a, factorial($a - 1), 3000);
  }
}

$e = '2';

for ($i = 2; $i <= 1000; $i++) {
   $e = bcadd($e, bcdiv('1', factorial($i), 3000), 3000);
}
echo ($e);

Con el que se obtienen 2572 dígitos correctos:

2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770417189861068739696552126715468895703503540212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508868769664035557071622684471625607988265178713419512466520103059212366771943252786753985589448969709640975459185695638023637016211204774272283648961342251644507818244235294863637214174023889344124796357437026375529444833799801612549227850925778256209262264832627793338656648162772516401910590049164499828931505660472580277863186415519565324425869829469593080191529872117255634754639644791014590409058629849679128740687050489585867174798546677575732056812884592054133405392200011378630094556068816674001698420558040336379537645203040243225661352783695117788386387443966253224985065499588623428189970773327617178392803494650143455889707194258639877275471096295374152111513683506275260232648472870392076431005958411661205452970302364725492966693811513732275364509888903136020572481765851180630364428123149655070475102544650117272115551948668508003685322818315219600373562527944951582841882947876108526398139559900673764829224437528718462457803619298197139914756448826260390338144182326251509748279877799643730899703888677822713836057729788241256119071766394650706330452795466185509666618566470971134447401607046262156807174818778443714369882185596709591025968620023537185887485696522000503117343920732113908032936344797273559552773490717837934216370120500545132638354400018632399149070547977805669785335804896690629511943247309958765523681285904138324116072260299833053537087613893963917795745401613722361878936526053815584158718692553860616477983402543512843961294603529133259

Aquí está el link que ejecuta este código:

https://www.victoriglesias.net/e.php

Al seguir el link, el lector con interés en el tema descubrirá que proporciona más decimales, pero, como dije, sólo los primeros 2572 son correctos, pues el error máximo cometido es:

+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000695151928186513...

Supongamos que sabemos que e está por debajo de 3, pero no podemos concretar más, el error, por el residuo del teorema de Taylor, sería 3/(i + 1)! No por acotar mejor, por ejemplo 2.8, dejaríamos de obtener menos posiciones a 0 hasta obtener los primeros decimales del error, aunque sí ajustaríamos mejor el margen de error.

Si parece insuficiente y se desea mayor precisión, bastará con incrementar el tope de la variable i del bucle a más de 1000. Eso sí, si nos tomamos este cálculo en serio, sería aconsejable optimizar previamente la función recursiva.

En definitiva, aunque me quedé muy lejos del récord mundial ;-), fue entretenido hacerlo y espero que al lector le parezca interesante también o, por lo menos, curioso.


1 Se llama serie de Maclaurin el caso concreto de Taylor a=0

Modificar imágenes desde la línea de comandos con ImageMagick

ImageMagick es un completísimo paquete de programas multiplataforma para el tratamiento de imágenes. A diferencia de programas como Photoshop o Gimp, los programas que lo componen se ejecutan desde la línea de comandos, aunque también dispone de un sencillo entorno para X Window en Linux.

Entorno gráfico de ImageMagick en Linux

Tiene numerosas herramientas que, entre otras cosas, permiten:

  • Convertir entre una gran cantidad de formatos de imágenes.
  • Manipular la paleta de colores de una imagen.
  • Añadir tramados.
  • Crear un gif animado a partir de varias imágenes.
  • Superponer una imagen encima de otra.
  • Añadir texto a una imagen.

En la documentación se puede ver un listado detallado.

En la web es frecuente que el gestor de contenidos cree automáticamente réplicas de diferentes tamaños a partir de una imagen subida por el usuario para su correcta visualización en diferentes páginas. Por lo tanto, sin duda lo más usado para la web es su capacidad de reescalar imágenes, para lo que usa el algoritmo de “liquid rescaling“. Ademas la modificación de tamaño es muy flexible, permitiéndonos lograr la modificación que estemos buscando.

Tal vez algún lector se esté preguntando que habiendo programas con entorno gráfico como los citados más arriba, para qué trabajar en el modo texto de la shell de Linux/Unix. Veamos entonces un caso en que sería conveniente. Resulta fácil que una web acabe teniendo miles de imágenes distribuidas en cientos o miles de directorios, pues, por cada imagen que el administrador del contenido sube se van a crear varias copias con diferentes tamaños. Fácilmente el total de imágenes de un catálogo de productos, por ejemplo, se vuelve inmenso. Imaginemos que un cambio de diseño o la necesidad de hacer la web responsive hace necesario modificar el tamaño de una de las copias que se estaba guardando de cada imagen. En vez de modificarlas una a una con nuestro programa de edición de imágenes favorito, se puede crear un shell script como este:

ls *jpg | while read i
do
f=`basename $i .jpg`
convert $i -resize 200x200 smaller-$f.jpg
done

Lo que hace es buscar todas las imágenes jpg del directorio y gracias al comando convert de ImageMagick crea una copia más pequeña reescalada a 200×200 píxeles cuyo nombre será la cadena “smaller-” concatenada al nombre del fichero original. Fácilmente se podría modificar el script para que recorriera recursivamente todos los subdirectorios.

Todo lo que nos ofrece ImageMagick se puede utilizar desde diferentes lenguajes de programación y no solo porque desde éstos se pueda invocar comandos en la shell* y por lo tanto a ImageMagick, si no que el paquete ha sido portado. Está disponible en Java, .NET, Ruby, Pearl, Python, Php, etc. Aquí hay una lista detallada de todos.

En el caso concreto de PHP existe la extensión nativa IMagick. Sin duda es GD la extensión más extendida, valga la redundancia, en PHP. A pesar de su mayor propagación, y como es tan frecuente en el mundo de la informática, IMagick presenta algunas ventajas sobre GD que la convierten en una mejor extensión para trabajar con imágenes. Aquí un artículo con una comparación entre ambas.


* Como hace Drupal, el extendido CMS en PHP.


Aunque la palabra comando es un calco de inglés y en español es más correcto usar orden o instrucción, uso el término que usamos habitualmente en nuestro trabajo.


 

Clase que permite transacciones anidadas con PDO

PDO, acrónimo de PHP Data Objects es un interfaz para acceder a bases de datos de PHP. A diferencia de las extensiones mysql y mysqli, que son exclusivas para MySQL, PDO puede trabajar con diferentes sistemas gestores de bases de datos, siempre y cuando haya driver para ella.

Las transacciones sirven para garantizar la integridad referencial de los datos. Una transacción está formada por varias órdenes SQL y bien se ejecutan todas las consultas en bloque o si alguna falla se vuelve al estado inicial antes de empezar la transacción, sin ejecutarse ninguna de ellas. Las transacciones deben cumplir con las propiedades ACID: Atomicidad, Consistencia, Isolation (aislamiento) y Durabilidad. (Nada que ver con el subgénero de música electrónica de finales de los 80 🙂 )

Las transacciones se anidan cuando existiendo una transacción en curso, se inicia otra. Esto por ejemplo sucede cuando desde un método donde se ha iniciado una transacción, para reciclar código (una de las virtudes de la programación orientada a objetos) se llama a otro método que inicia otra transacción.

Transacciones anidadas

Todo fue bien hasta el final y se ejecutan en bloque todas las transacciones (COMMIT)

Transacciones anidadas

¡Ups, algo fallo cuando ya casi finalizaba! ¡Déjalo todo como estaba! (ROLLBACK)

Desgraciadamente, desarrollando en LAMP, nada más iniciarse la segunda transacción se producirá un error fatal. MySQL no soporta las transacciones anidadas. En su documentación afirma que después de ejecutarse un BEGIN TRANSACTION ciertas órdenes producirán un COMMIT, entre ellas BEGIN TRANSACTION. Tampoco las soporta PostgreSQL. Una solución parcial que ambos sistemas incorporan son los SAVE POINTS.

A continuación viene el esquema de una clase que mediante los SAVE POINTS y controlando el número de transacciones anidadas mediante la propiedad transactionDepth, consigue algo parecido a anidar transacciones y por lo tanto evita el error fatal antes mencionado.

Si tu clase extiende la clase PDO, el método execute puede ser reemplazado llamando simplemente a $this->exec() Como digo, esta clase es un esquema para entender la idea, no está pensada para funcionar directamente sino que el programador interesado en ella deberá adaptarla.

class Db { 
  static private $instance = null; 
  private $connection = null;
  protected $transactionDepth = 0; 
 
  private function __construct() { 
  }
  
  private function _connect() { 
     if ($this->connection === null) {
         try {
            /* Código para conectarse a la BD */
         } catch (PDOException $e) {
            echo "error pdo: ";
            echo $e->getMessage();
         }
      }

      return $this;
   }
   
   /* Nada que clonar en el patrón de diseño Singleton */
   private function __clone()
   {
     
   }

   static public function getInstance()
   {
      if (is_null(self::$instance)) {
         self::$instance = new self();
      }

      return self::$instance;
   }

   static public function closeConnection()
   {
      if (!self::$instance === null) {
         self::$instance = null;
      }
      if (isset(self::$connection)) {
         unset(self::$connection);
      }
   }

   public function getConnection()
   {
      $this->_connect();

      return $this->connection;
   }

   protected function prepare($query, $params = array())
   {
      $stmt = $this->getConnection()->prepare($query);
      if (is_array($params)) {
         foreach ($params as $param => $value) {
            if (is_bool($value)) {
               $type = PDO::PARAM_BOOL;
            } elseif ($value === null) {
               $type = PDO::PARAM_NULL;
            } elseif (is_integer($value)) {
               $type = PDO::PARAM_INT;
            } else {
               $type = PDO::PARAM_STR;
            }
            $stmt->bindValue(":$param", $value, $type);
         }
      }

      return $stmt;
   }

   public function execute($sql, $params = array())
   {
      $stmt = $this->prepare($sql, $params);
      $stmt->execute();
      $stmt->closeCursor();

      return $stmt->rowCount();
   }

   public function begin()
   {
      if ($this->transactionDepth == 0) {
         $this->getConnection()->beginTransaction();
      }else{
         $this->execute("SAVEPOINT LEVEL{$this->transactionDepth}");
      }
      $this->transactionDepth++;
   }

   public function commit()
   {
      $this->transactionDepth--;
      if ($this->transactionDepth == 0) {
         return $this->getConnection()->commit();
      }else{
         return $this->execute("RELEASE SAVEPOINT LEVEL{$this->transactionDepth}");
      }
   }

   public function rollback()
   {
      if ($this->transactionDepth == 0) {
         throw new PDOException("Ninguna transacción en curso para retroceder");
      }
      $this->transactionDepth--;
      if ($this->transactionDepth == 0) {
         return $this->getConnection()->rollback();
      }else{
         return $this->execute("ROLLBACK TO SAVEPOINT LEVEL{$this->transactionDepth}");
      }
   }
}

En PHP un sistema de plantillas es prescindible

Si bien es cierto que PHP hace muchos años que dejó de ser un sistema de plantillas tampoco me parece que necesite implementar un sistema de plantillas de forma imperiosa. En su origen, PHP era un sencillo lenguaje, cuyo intérprete programó en C Rasmus Lerdorf, destinado a implementar su página personal, de ahí el acrónimo Personal Home Page. Mucho ha llovido desde entonces y hace tiempo que PHP es un lenguaje orientado a objetos bastante potente con muchas librerías a su disposición. A pesar de ello, un motor de plantillas me parece una sobrecarga innecesaria y mucho menos me convence el razonamiento de querer dotar al lenguaje de una especie de aura de seriedad. En casos concretos hace más bien que mal, pero hay 2 razones por las que en muchos casos me parece prescindible.

Primera: Un sistema de templates añade una sobrecarga no despreciable. El entorno más frecuente para PHP son los servidores web compartidos que alojan diversas webs. Los costes de alojamiento son reducidos por la poca carga que supone PHP, tanto en tiempo de CPU como RAM consumida. Poner en esos servidores mastodontes como Symfony tiene su peaje. El patrón MVC es conveniente, la sobrecarga no, y la V de vista no implica usar plantillas. Más sobre esto en mi segunda razón.

Hace ya años que PHP es usado también en grandes aplicaciones web, con miles de usuarios conectados simultáneamente y cuyo alojamiento no alcanza en un sólo servidor sino que se requiere de una server farm. Trabajé en una empresa así y recuerdo que la competencia de dicha empresa había apostado por Java, un lenguaje más “serio” (más empleado a nivel corporativo). El gasto en servidores de esa empresa multiplicaba en varias veces el de la nuestra y cuando se llega a cierto volumen los costes dejan de ser despreciables y empiezan a marcar diferencias. Que PHP, a diferencia de Java, no necesite ingentes recursos para declarar un simple entero es una poderosa razón por la que barrió a Java de la web.

Segunda: Algunos argumentan que PHP es demasiado “parlanchín” para ser empleado en la vista pero no estoy de acuerdo. Puede (o no) que esto:

{foreach $foo as $bar}

Sea mejor que esto:

<?php foreach($foo as $bar){ ?>

Pero es idéntico a los “short tags” que PHP sigue permitiendo. Además, PHP dispone de una sintaxis alternativa para las estructuras de control:

<? foreach($foo as $bar): ?>

Esto también es objeto de crítica:

<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>

¿Por qué no usar esto?

<?=htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>

Para que nadie sufra del síndrome metacarpiano podemos encapsular en algún helper esa función, como hace CakePHP:

<?=h($var) ?>

La función sería algo así:

function h($text)
{
return htmlspecialchars($text, ENT_COMPAT | ENT_HTML5, 'UTF-8');
}

Así mismo se pueden crear fácilmente otras funciones para agilizar la programación de las vistas.

También se argumenta que diseñadores y maquetadores no tienen por qué saber acerca de temas de seguridad como los ataques XSS y CSRF y que para que ellos puedan programar las vistas con seguridad debe implementarse un sistema de plantillas. En estos casos sí sería necesario usarlo y sólo añadiría lo siguiente: he conocido muchos diseñadores y no he visto ninguno interesado en programar en el lado servidor. Iría más lejos: no he conocido ninguno interesado en programar. A lo sumo, sí en aprender Flash en sus años buenos. Frecuentemente, ni tan siquiera Javascript, a pesar de incluir ficheros en sus diseños. Obviamente les interesan las funcionalidades que aporta pero en general no están interesados en saber cómo funciona. En la industria que yo conozco, programar las vistas acaba siendo trabajo también del programador y éste sí conoce (o debería) las implicaciones de seguridad. Si en la empresa los diseñadores sí están por la causa sí sería conveniente usar un sistema de templates.

Otras casos en los que puede ser interesante usarlo es cuando se requiere una sandbox con un susbset de las funciones propias y/o de PHP. Por ejemplo si el usuario desde el back end ha de poder acceder a arrays con datos y a ciertas funciones para transformar y operar esos datos. Para estos casos hay sistemas de templates como Twig que proporcionan una sandbox y sería razonable usarlos en vez de reinventar la rueda programando uno propio.

A pesar de no ser necesario un sistema de plantillas en la mayoría de aplicaciones web, ya consiguen hacer negocio con ellos. ¿Necesidad real o creada?

Exportar datos a Excel con PHP

Cuando queremos que el usuario pueda exportar los datos desde una aplicación web para poder abrirlos como una hoja de cálculo lo más recomendable es hacerlo en formato CSV (Comma-Separted Values) Ahora bien, hay casos en que el cliente insiste en que desea que se le abra inmediatamente su Microsoft Excel al hacer click sobre el link o botón. En estos casos, cuando generamos el fichero “al vuelo”, la cabecera debe ser:

header('Content-Type: application/vnd.ms-excel');

En vez de:

header('Content-Type: text/csv'; charset=utf-8);

Si los datos contienen caracteres más allá de los primeros 128 ASCII, por ejemplo acentos, al abrirse Excel veremos que estos caracteres no se visualizan correctamente. ¿Por qué? Aunque UTF-8 es de lejos la codificación más usada en la web, y lo más probable es que tu aplicación trabajé con ella, Microsoft Excel sorprendentemente no trabaja con este formato. Los de Redmond pueden haber perdido parte de su poder pero no su idiosincrasia. ¿Cómo arreglar este desaguisado? Pasando los datos a UTF-16LE (Lower Endian) e indicando la codificación en la cabecera. Con esta codificación sí trabajan. Para lograrlo PHP dispone de una función para convertir codificaciones: mb_convert_encoding()

El siguiente código de ejemplo deshace el entuerto. En $participations
tenemos los datos a exportar, es un array. En este caso concreto, el código pertenece a una vista y por lo tanto el array ha llegado desde un controlador. El array $header contiene el nombre de cada columna para la hoja de cálculo y $fields contiene los índices de $participations, que coinciden con los nombres de los campos en la base de datos.

<?php

$participations = $render['main']['participations'];
$header = ['NOMBRE1', 'NOMBRE2', 'NOMBRE3', 'NOMBRE4', 'NOMBRE5'];
$fields = ['campo1', 'campo2', 'campo3', 'campo4', 'campo5'];

header("Content-Type: application/vnd.ms-excel; charset=UTF-16LE");
header('Content-Disposition: attachment; filename=participantes_' . makeUrlPhrase($render['main']['bla']['bla']) . '.xls');
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);

$result = implode("\t", $header);
$result .= "\r\n";
if (!empty($participations)):
 foreach ($participations as $part):
  foreach ($fields as $iField):
   $result .= $part[$iField] . "\t";
  endforeach;
  $result .= "\r\n";
 endforeach;
endif;

echo mb_convert_encoding($result, 'UTF-16LE', 'UTF-8');

Como está haciendo servir el tabulador \t para indicar a Excel separación entre campos y el salto de línea \r\n como separación de registros, si creemos que en los datos puede existir alguno de estos caracteres especiales, deberemos escaparlos con la función preg_replace() De lo contrario la hoja no se importará correctamente.

Excel, fuente inagotable de virtudes, tratará campos como fechas, números de teléfono o códigos postales y los procesará para dejarlos inútiles. Por ejemplo, los códigos postales de Barcelona empiezan por cero: 08080. Excel tratará ese dato como un número entero y lo dejará en 8080. Para evitarlo hay que entrecomillar estos datos y una vez más la función preg_replace() acude a nuestro rescate:

if(preg_match("/^0/", $result) || preg_match("/^\+?\d{8,}$/", $result) || preg_match("/^\d{4}.\d{1,2}.\d{1,2}/", $result)) {
  $result = "'$result";
}

Con todo esto conseguiremos que al hacer click el usuario sobre un link, se descargará un fichero que se abrirá automáticamente en Excel y en el que los datos aparecerán correctamente.

Cómo instalar XCache en un servidor compartido

La semana pasada quise instalar en un servidor compartido (Hostmonster para más señas) alguno de los diferentes sistemas de caché que existen para PHP. El único que ofrecen es un paquete de PEAR llamado “Cache” pero necesitaba instalar Apc, Xcache, MemCache o Redis. Me puse en contacto con su departamento técnico para consultar si era posible y la respuesta fue un no. Como cuando instalamos Subversion tampoco fueron ni muy optimistas ni proactivos, no hice demasiado caso a su respuesta y me lancé a intentarlo. Como Apc parecía que iba a ser problemático pues por lo que leí necesitaba ser root, lo intenté con Xcache. En primer lugar, en el directorio “home” de mi usuario en Hostmonster creé los directorios y bajé la versión de xCache para la versión de PHP que corre el servidor:

  1. mkdir modules xcache
  2. wget http://xcache.lighttpd.net/pub/Releases/1.3.2/xcache-1.3.2.tar.gz

Después descomprimí el módulo y lo compilé para la versión de PHP del servidor:

  1. tar -zxf xcache-1.3.2.tar.gz
  2. cd xcache-1.3.2
  3. phpize
  4. ./configure –enable-xcache
  5. make

Compruebo que esté bien:

  1. make test

Y ya sólo queda mover el módulo recién compilado a su directorio de destino:

  1. cd modules
  2. mv xcache.so /home2/usuario/modules

Ahora debemos editar php.ini para que PHP empiece a trabajar con Xcache. Añadí las siguientes líneas:

  1. zend_extension = /home2/usuario/modules/xcache.so
  2. zend_extension_ts = /home2/usuario/modules/xcache.so
  3. xcache.shm_scheme = “mmap”
  4. xcache.size = 32M
  5. xcache.count = 8
  6. xcache.slots = 8K
  7. xcache.ttl = 0
  8. xcache.gc_interval = 0
  9. xcache.var_size = 16M
  10. xcache.var_count = 1
  11. xcache.var_slots = 8K
  12. xcache.var_ttl = 0
  13. xcache.var_maxttl = 0
  14. xcache.var_gc_interval = 300
  15. xcache.test = Off
  16. xcache.readonly_protection = Off
  17. xcache.mmap_path = “/dev/zero”
  18. xcache.coredump_directory = “”
  19. xcache.cacher = On
  20. xcache.stat = On
  21. xcache.optimizer = Off
  22. xcache.coverager = Off
  23. xcache.coveragedump_directory = “”

También le podemos añadir un usuario y contraseña, ésta última debe ir “hashed” con md5 según explica la documentación:

  1. xcache.admin.user = “nombre_del_usuario”
  2. xcache.admin.pass = “4c882dcb24bcb1bc225391a602feca7c”

Para que la configuración tenga efecto deberíamos reiniciar los procesos fcgiphp5 pero eso no es siempre posible en un servidor compartido, así que no me quedó otra que esperar a que ello sucediera. Se pueden ver los procesos de la siguiente forma:

  1. ps aux | grep fcgiphp5

A continuación obtenemos la id del proceso y mediante kill mandamos la señal para matarlo. En todo caso, sea de este modo o bien esperando, en el resultado de phpinfo() deberíamos ver esto si XCache está funcionando correctamente:
XCache correctamente instalado

Configuración XCache

Configuración XCache

Instalarlo es muy fácil, ¿verdad? A continuación me puse otra vez en contacto con ellos para preguntarles si tenían algún inconveniente con la instalación pues mejor prevenir a que deshabiliten la web y su respuesta fue que no veían ningún inconveniente. Como pueden observar, en este tipo de servicios de alojamiento web es mejor ser proactivo y lanzarse a ver si es técnicamente posible.