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. 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)!, es decir:

+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000744805637342692...

Por cierto, no por acotar mejor e, por ejemplo 2’8, dejaríamos de obtener menos posiciones a 0 hasta obtener los primeros decimales del error. 2’8/(i + 1)! es:

+-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000695151928186513...

Por lo tanto, aunque acotemos con más precisión e, la fórmula del residuo nos sigue asegurando que hemos calculado correctamente la misma cantidad de decimales.

Si parecen insuficientes 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

¿Por qué lo llaman logaritmo neperiano cuando quieren decir natural?

Normalmente denominamos “neperiano” al logaritmo de base e, pero viendo un vídeo en inglés escuché que se referían al mismo como “natural”, entonces me puse a indagar cual de las dos formas es correcta. El resultado fue que “natural” sería más correcto, pero entonces, ¿por qué lo llamamos neperiano? Voy a explicar en esta breve entrada lo que averigüé.

Leyenda de un libro de matemáticas de 3º de BUP

Leyenda de mi libro (I de II) de matemáticas de 3º de BUP

John Napier, un matemático escocés que vivió entre 1550 y 1617, fue el primero en definir los logaritmos. Su trabajo, como era lo usual en la época, lo publicó en latín, y fue otro matemático quien, tiempo después, traduciría la obra al inglés. En una de las ediciones, se incluyó un apéndice con una tabla de logaritmos, y en la misma aparecen algunos valores que se obtienen usando la base 2.718, pero sin hacer ninguna mención en especial a la misma. Esta base, por cierto, no aparece en la obra original de Napier.

Logarithmorum, de John Napier

Las largas noches de invierno en el norte de Europa dan para mucho.

No obstante, en aquel entonces, el número e todavía no había sido formalmente definido. Probablemente, el autor de esta tabla, que se cree que fue William Oughtred, tuvo nociones acerca de e, al igual que otros matemáticos de la época, pero al descubrimiento y su formalización todavía le faltaba entorno a un siglo. En todo caso, si bien a John Napier se le reconoce el mérito del logaritmo como su gran aportación a las matemáticas, no sería justo otorgarle el mérito de uno de los números más importantes.

En definitiva, parece que los anglosajones están más acertados que nosotros a la hora de llamar “natural” al logaritmo en base e y que somos nosotros quienes andamos algo equivocados al otorgarle a John Napier más méritos de los que le corresponden.

Uso avanzado de Find y Grep

Durante todos mis años de desarrollado LAMP, han habido una serie de comandos UNIX que me han sido muy útiles. En este artículo voy a compartir unos ejemplos de su uso que van más allá de su empleo básico, con el objetivo de que sirva de ayuda para otros desarrolladores. En esta ocasión voy a centrarme en find y grep, más adelante me gustaría ampliar este artículo con otros comandos que facilitan la vida al programador y al usuario de Unix / Linux en general.

Entrada, salida y su redireccionamiento

Antes de empezar, no estaría de más, para una mayor claridad de los ejemplos, explicar que en Unix el standard output (salida) e input (entrada) es la consola. Debemos tenerlo en cuenta para redireccionar tanto la salida como la entrada de datos de las órdenes mediante pipelines ( < > | )

find y grep

Grep es una poderosa herramienta que nos permite encontrar coincidencias dentro de un fichero o de un conjunto de ellos, gran parte de sus “superpoderes” emanan de las expresiones regulares. A continuación, veamos unos ejemplos de su uso para búsquedas no muy elementales:

– En primer lugar, con grep hay que escapar los caracteres especiales:

grep "regex|regex not" borrame.txt  => grep "regex\|regex not" borrame.txt

– Si no se quiere escaparlos para que no los entienda como parte de la cadena buscada, debemos usar la opcion -E o bien egrep:

grep -E "regex|regex not" borrame.txt

egrep "regex|regex not" borrame.txt

– Para buscar una cadena de texto en ficheros filtrados recursivamente:

grep -r --include="*.php" "yorkshiresConfig.ini" * > resultados.txt

Esta orden buscaría recursivamente, a través de todos los subdirectorios, la cadena “yorkshiresConfig.ini” en todos los ficheros con extensión php.

El nombre de la orden find ya nos dice todo acerca de su función. Se vuelve realmente poderosa cuando se combina con otras órdenes. He aquí algunos ejemplos:

– Para borrar ficheros resultantes de una búsqueda de cierto tipo de ficheros, con los subdirectorios incluidos:

find -name '*.po' -exec rm -i {} \;

– Para borrar todos los ficheros que tengan más de 50 días:

find /compartido/backups/pro/auto/bd/* -mtime +50 -exec rm {} \;

Como fácilmente podemos acabar borrando lo que no deseábamos, con la opción -i el programa rm pedirá confirmación por cada fichero.

– Para moverlos a otro directorio:

find -name '*.po' -exec mv {} ./poBackups \;

– También podemos renombrar masivamente ficheros, el siguiente comando busca recursivamente todos los ficheros “.po” y los renombra a “.po.bak”:

find -name '*.po' | sed 's/\(.*\).po$/mv "&" "\1.po.bak"/' | sh

Si en vez de “find -name ‘*.po”‘ usáramos “ls -d *.po” serían sólo los directorios del directorio actual.

Busca en el directorio acutal y en los subdirectorios todos los ficheros con la extensión php que contengan la cadena “Possible reason: your host may have disabled the mail“:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \;

Cuando el listado de resultados es demasiado grande como para manejarlo cómodamente en el terminal, podemos redireccionar el resultado con una pipe desde el standard output a un fichero:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \; > results.txt

Si de cada fichero encontrado queremos saber su ruta exacta, debemos añadir “-print” al final:

find -name '*.php' -exec grep 'Possible reason: your host may have disabled the mail' {} \; -print

La orden find también nos permite buscar por fechas:

– Encontrar ficheros modificados en el último día:

find -ctime -1 -type f

– Para directorios:

find -ctime -1 -type d

– Encontrar ficheros más recientes que main.css:

find -newer main.css

Contar el número de ficheros de un directorio y subdirectorios:

find . -type f | wc -l

ls y mv al rescate

A veces, las herramientas más básicas son las adecuadas. Esto es especialmente cierto en UNIX, pues en su tradición está la filosofía de disponer de muchas pequeñas herramientas para tareas muy concretas, permitiendo al usuario combinarlas para conseguir objetivos más complejos.

–  Para contar los elementos del directorio actual podemos usar la orden wc (Word Count), en combinación con ls. El parámetro -l indica que cuente líneas en vez de palabras, por lo tanto, contará el número de líneas que devuelve ls:

ls -1 | wc -l

– Listar sólo los directorios, sin los ficheros, del directorio actual:

ls -d */

– Listar sólo los directorios de un subdirectorio:

ls -d Proyectos/*/

– Mover sólo los ficheros ocultos de un directorio (origen) a otro (dest):

mv origen/{*,.*} dest/

El futuro es de Javascript

El gran ruido de la invasión en el lado servidor de Javascript empezó en el año 2009 con Node.js: no era el primer proyecto que lo intentaba pero sí el primero que lo lograba, y su logro aportó más que poder disponer del mismo lenguaje en el cliente y en el servidor. Por otro lado, sobre las posibilidades que ofrece actualmente Javascript en el navegador gracias a los compiladores JIT, ya he hablado en otro artículo.

Aunque el creador de Node.js, Ryan Dahl, abandonara su proyecto hace ya años, dejando de lado la web para pasar a proyectos más interesantes de Machine Learning, afirmando que Go es una mejor herramienta para servidores web con gran volumen de carga, creo que la inercia que tiene Javascript a día de hoy, le garantiza el dominio en los próximos años.

Desde luego que Javascript dista de ser un gran lenguaje de programación, pero la historia de la informática está plagada de casos en los que no se impuso lo que técnicamente era mejor, pues pesaron más factores relacionados con el mundo de los negocios. En mi opinión, el impulso que está cogiendo Javascript en los últimos años, hará que la palabra de moda en el personal de recursos humanos sea “Javascript”. Si trabajas en la industria deberías tenerlo en cuenta.

Encuesta stackoverflow 2018

Tecnologías más populares en la encuesta de Stackoverflow del presente año.

Por supuesto, los programadores en lenguajes “tradicionales” del lado servidor, como PHP, Java o Python, van a seguir teniendo trabajo los próximos años, aunque sólo sea, en el peor de los casos, por los millones de líneas de código en producción que alguien va a tener que seguir manteniendo; aunque a día de hoy no creo que se llegue a ese extremo; seguro que -todavía- se desarrollarán proyectos nuevos en estos lenguajes.


Editado el 18/4/2018:

Google Brain ha llevado a Javascript su librería de TensorFlow: TensorFlow.js Es decir, llega a los navegadores, y por lo tanto a los ordenadores, móviles y tablets, el machine learning y las redes neuronales.

Cómo comentar el código

En la lista de libros frecuentemente citados y raramente leídos, probablemente encontraríamos desde “El fin de la historia y el último hombre”, de Francis Fukuyama, hasta “Code Complete”, de Steve McConnell. Este último es el que voy a citar aquí, sin haberlo leído para seguir la tradición, concretamente su muy extendida afirmación de que los comentarios no tan solo no son necesarios sino que pueden conseguir el efecto contrario: un código complejo que el programador no trabaja para simplificarlo por tener a su disposición el camino, inicialmente más breve, de los comentarios.

En mi humilde opinión, aunque estoy de acuerdo en gran parte con la opinión de McConnell y otros, los comentarios sí son necesarios. Estos deben describir el porqué o describir qué se está haciendo, no el cómo, pues es el cómo lo único que puede delegarse a un código claro y descriptivo. Cuando el proyecto carece de documentación o no se mantiene actualizada, los comentarios que explican el porqué son aun más necesarios.

A continuación, veamos algunos ejemplos prácticos para ilustrar mi opinión:

class Model_Session
{

   /**
    * Sigue el patrón singleton para encapsular la sesión.
    * No extiende Model_Signia_Abstract porque debe definir construct privado.  
    */
   private $calledClass;

   protected function __construct($options)
   {
      $this->calledClass = explode('_', get_called_class())[1];
   }

   final static function getInstance($options = null)
   {
      static $instances = array();

      $calledClass = get_called_class();

      if (!isset($instances[$calledClass])) {
         $instances[$calledClass] = new $calledClass($options);
      }

      return $instances[$calledClass];
   }

   public function __clone()
   {
      trigger_error("An instance of the class " . __CLASS__ . " already exists.", E_USER_ERROR);
   }

   protected function set($value)
   {
      $_SESSION[$this->calledClass] = $value;
   }

   public function get($value)
   {
      if (isset($_SESSION[$this->calledClass][$value])) {
         return $_SESSION[$this->calledClass][$value];
      } else {
         return false;
      }
   }

   public function isLogged()
   {
      return isset($_SESSION[$this->calledClass]);
   }
   
   public function delete($key)
   {
      unset($_SESSION[$this->calledClass][$key]);
   }
   
   public function logout()
   {
      unset($_SESSION[$this->calledClass]);  
   }
   .
   .
   .
}

Algunos consideran que singleton es un antipatrón de diseño, pero este código está ahora mismo solucionando necesidades reales de empresas y soy de la opinión de que la teoría existe para ayudarnos, no para interferir en aquello por lo que nos pagan. En la misma línea, aunque trigger_error debería evitarse, en los métodos mágicos prefiero lanzar un error a lanzar una excepción. Aclarado esto, regresemos al tema que ocupa este artículo. Con la primera línea del comentario explico por qué y para qué uso el patrón:

Sigue el patrón singleton para encapsular la sesión.

La segunda línea está pensada para responder tanto el porqué que me pueda plantear yo cuando revise el código tiempo después y no recuerde por qué lo programé así, como el que se pueda plantear otro programador que vea esta clase por primera vez:

No extiende Model_Signia_Abstract porque debe definir construct privado.

El resto de la clase no tiene más comentarios y tampoco le hacen falta, pero, ¿qué sucede cuando los nombres de las variables y métodos no son descriptivos? Que nos vemos obligados a crear comentarios que clarifiquen cómo funciona la rutina. Comparemos estos dos métodos:

function permsM($m)
{
      $perms = [];
      
      foreach (['add', 'view', 'edit', 'delete'] as $a) {
         if (isset($this->get('permissions')[$a]) && in_array($m, $this->get('permissions')[$a])) {
            $perms[] = $a;
         }
      }

      return $perms;
}

Probablemente el ejemplo esté un poco forzado, pero sin duda demuestra que, o bien añadimos comentarios por doquier, o bien usamos nombres descriptivos:

public function getPermissionsForModule($sModule)
{
      $aPermissions = [];
      
      foreach (['add', 'view', 'edit', 'delete'] as $action) {
         if (isset($this->get('permissions')[$action]) && in_array($sModule, $this->get('permissions')[$action])) {
            $aPermissions[] = $action;
         }
      }

      return $aPermissions;
}

Cuando tenía unos 9 años hice mi primer “programa”, lo sufrió un Zx Spectrum 128, su cantidad de memoria estaba contenida en su nombre, en Kilobytes. Con semejante restricción, entiendo que en la época tenía lógica optimizar el consumo de memoria incluso recortando el nombre de las funciones y variables, pero a día de hoy eso no tiene ningún sentido. Además, tanto los IDE como sencillos editores (por ejemplo Notepad++), disponen de la funcionalidad de autocompletar texto, que nos ayuda a recordar y escribir correctamente los nombres de variables, funciones, métodos y clases sin importar cuán largos sean. Por lo tanto, a día de hoy no hay excusas para no usar nombres descriptivos.

En este sentido, las constantes ayudan enormemente:

if ($file['error'] === 0 { //¿Mande? ¿Fue bien o mal?

if ($file['error'] === UPLOAD_ERR_OK {

Podemos llegar a ser más papistas que el Papa con el código que se explica a si mismo:

if ($file['size'] > 5242880) { // 5 MB

if ($file['size'] > 5*1024*1024) {

Otros comentarios necesarios

– Cuando, por falta de tiempo, se ha tenido que programar de forma poco óptima, indicarlo ayudará más adelante, cuando el proyecto haya sido entregado, a reconocer las partes que necesitan refactoring más urgentemente.

– Existen expresiones que son complejas y no hay azúcar sintáctico que las simplifique, como por ejemplo las expresiones regulares; en estos casos, comentar qué se está buscando aumentará la productividad de todo el equipo.

– Finalmente, cuando hemos copiado un código con licencia que lo permita, es de caballeros citar el autor y la fuente (si es que no estamos obligados directamente por la misma).

En definitiva, si cada vez que escribimos un comentario nos preguntamos si es realmente necesario o, si por el contrario, está encubriendo un código poco legible, conseguiremos elaborar software más fácil de mantener, tanto para nosotros como para quienes vengan después. Si describe cómo procesa, lo más probable es que nos estemos haciendo trampas.

MySQL Cannot Add Foreign Key Constraint

Cuando estamos alterando la estructura de un tabla en MySQL, nos podemos encontrar con el siguiente error al añadir una llave foránea:

MySQL Cannot Add Foreign Key Constraint

Estos errores con poca información son más molestos de lo habitual. Como las posibles razones por las que el motor de la base de datos no ha podido crearla son diversas, sería ventajoso evitar tener que estudiarlas una por una. Esto lo podemos lograr con la siguiente orden:

SHOW ENGINE INNODB STATUS;

En la sección “LATEST FOREIGN KEY ERROR” encontraremos una descripción del error más completa.

| InnoDB | |
=====================================
2018-02-20 11:22:34 0x7f075c175700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 25 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 12622 srv_active, 0 srv_shutdown, 5333759 srv_idle
srv_master_thread log flush and writes: 5344820
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 19660
OS WAIT ARRAY INFO: signal count 17755
RW-shared spins 0, rounds 11780, OS waits 6140
RW-excl spins 0, rounds 17899, OS waits 382
RW-sx spins 738, rounds 11751, OS waits 121
Spin rounds per wait: 11780.00 RW-shared, 17899.00 RW-excl, 15.92 RW-sx
------------------------
LATEST FOREIGN KEY ERROR

------------------------

2018-02-19 09:36:53 0x7f075c208700 Cannot drop table `serca`.`promo_landing`
because it is referenced by `serca`.`promo_landing_i18n`
------------
TRANSACTIONS
------------
Trx id counter 1864352
Purge done for trx's n:o < 1864352 undo n:o < 0 state: running but idle
History list length 808
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421144897607520, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
310347 OS file reads, 83964 OS file writes, 23539 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.92 writes/s, 0.52 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 7 merges
merged operations:
insert 4, delete mark 3, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 34673, node heap has 2 buffer(s)
Hash table size 34673, node heap has 14 buffer(s)
Hash table size 34673, node heap has 3 buffer(s)
Hash table size 34673, node heap has 35 buffer(s)
Hash table size 34673, node heap has 8 buffer(s)
Hash table size 34673, node heap has 9 buffer(s)
Hash table size 34673, node heap has 4 buffer(s)
Hash table size 34673, node heap has 2 buffer(s)
11.56 hash searches/s, 1.68 non-hash searches/s
---
LOG
---
Log sequence number 567281250
Log flushed up to 567281250
Pages flushed up to 567281250
Last checkpoint at 567281241
0 pending log flushes, 0 pending chkp writes
15014 log i/o's done, 0.28 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 42107376
Buffer pool size 8191
Free buffers 1024
Database pages 7090
Old database pages 2597
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 150106, not young 4595614
0.16 youngs/s, 0.00 non-youngs/s
Pages read 308306, created 2548, written 65550
0.00 reads/s, 0.00 creates/s, 0.60 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 7090, unzip_LRU len: 0
I/O sum[18]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=1022, Main thread ID=139669620905728, state: sleeping
Number of rows inserted 12470971, updated 1849, deleted 367, read 104405344
0.24 inserts/s, 0.00 updates/s, 0.00 deletes/s, 2852.41 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

Como excusa para probar Simple Screen Recorder en mi portátil, he hecho el siguiente vídeo en el que explico lo mismo: