Un actor útil y eficiente en Go

Etiquetas

, ,

Este es un truco en Go muy útil y eficiente para hacer tareas de «mantenimiento» en estructuras de forma concurrente (y seguramente paralela).

Supongamos que tenéis una lista de elementos, a esta lista se agregan u obtienen elementos pero hay que mantener solamente los últimos N, donde N puede estar basado en una límite temporal.

Las operaciones sobre la lista deben responder muy rápidamente por lo que no es posible llamar a la función que elimina los más antiguos porque tiene un coste computacional (O(n) o O(log n) en el mejor de los casos) que retrasaría la respuesta.

Hay dos técnicas muy habituales en Go:

  1. Lanzar al principio una goroutine que periódicamente se ejecute después de una espera con time.Sleep() o usar el time.Ticker que ya hace ambas cosas. El problema con esta solución es que se ejecuta y consume CPU aunque no haya actividad.
  2. Lanzar la goroutine cada vez que hay actividad, por ejemplo al agregar u obtener elementos de la lista. El problema, además del pequeño overhead de lanzar la goroutine, es que si hay muchas operaciones se creará un número idénticos de goroutines y seguramente cada una de ellas tendrá que esperar que la otra acabe (se necesitan mutex, la estructura es compartida entre varios hilos de ejecución) y el trabajo se estará haciendo trabajo de más sin ninguna utilidad.

Una tercera forma muy eficiente, algunos le llaman actor (por el modelo de actores). Como en el caso 1 anterior, se lanza una goroutine -el actor– cuando se crea la estructura (o la interfaz), esta rutina sólo espera recibir un mensaje de un canal específico para ella. Cuando recibe un mensaje hace su trabajo y vuelve a esperar por uno nuevo.

Sigue leyendo

Cuidado con las «clever solutions» de concurrencia

Etiquetas

,

Ayer a última hora me encontré con este código:

Ci61so_WgAEKHf_.jpg

Quité algunas líneas para que no se pudiese deducir la empresa, que no es importante. Tampoco el programador que lo hizo, no es mi intención criticar a nadie en particular sino a una mala práctica de solucionar problemas de concurrencia con «ideas geniales» que no lo son tanta.

El código anterior recibe consultas B2B, graba los resultados en un fichero (por requerimientos de negocio) y luego lee desde esos mismos ficheros para enviar la respuesta a la agencia que hizo la consulta.

Es un software que factura millones de euros al año y pasó semanas de tests y QA. No se descubrió el problema hasta que una de los clientes optimizó sus consultas enviando varias en paralelo. Allí descubrieron que obtenían resultados erróneos: eran duplicados (con un riesgo financiero bastante importante).

Moraleja 1: Los errores de concurrencia son difíciles de encontrar y cuando aparecen suelen ser difíciles de debuguear, ten mucho cuidado antes de implementar soluciones ad-hoc.

El código intenta resolver el problema de concurrencia de varios procesos que podrían escribir en el mismo fichero verificando primero si el fichero existe, si es así incrementa el contador -que forma parte del nombre- hasta que encuentra uno que no coincida.

Además de detalles de eficiencia tiene un problema grave, las operaciones de verificación (file_exists) y creación del fichero (fopen) no son atómicas. Eso significa que varios procesos concurrentes (con una o varias CPUs) verifican, les da falso a todos y luego todos escriben en el mismo fichero. Una race condition de libro.

Moraleja 2: Si has tardado en encontrar el problema o no entiendes la importancia de operaciones atómicas ya deberías estar aprendiendo más de concurrencia.

Afortunadamente entre los tres que estábamos analizando el código en plan «emergencia» y por vídeoconferencia (la captura es del chat de Skype de Linux) desde países diferentes nos dimos cuenta enseguida del bug y de una solución simple: agregar el PID del proceso al nombre del fichero. Como el PID es único en el sistema y cada proceso individual es secuencial no hay riesgos de que sobreescriban en el mismo fichero.

No es la solución más eficiente (ya lo corregiremos estos días con más tranquilidad) pero es una solución segura y que podía implementarse en pocos minutos y sin efectos colaterales que podrían afectar a la lógica del programa.

Además, el bug podría haber sido menos perjudicial si en vez de escribir los resultados en el fichero y luego leerlos para responder se hubiese enviado directamente la respuesta ya almacenada en el proceso local.

Moraleja 3: Si no te has dado cuenta de la diferencia entre datos locales y compartidos y los problemas que pueden generar estos últimos, ponte ya a aprender de concurrencia.

Moraleja 4: Los problemas de concurrencia son muchos más habituales de los que crees y las soluciones no son tan obvias como parecen a primera vista.

Obviamente tengo que recomendar el libro que ya sabéis (y aparece a la izquierda 😉 ) pero ni aún así se puede asegurar que no cometerás errores, se requiere práctica y ser muy cuidadoso.

 

 

 

Cuando el periodismo cede el control de su producto

Etiquetas

, ,

Al principio no quisieron tener versión móvil porque el número de impresiones se reduciría. Así tenías que hacer malabarismos con el zoom después que se hayan bajado varios megabytes de anuncios.

Poco a poco fueron cediendo y hoy la mayoría de los medios tienen versión móvil. Entonces empezamos a descubrir todas los trucos.

Lo primero que vimos fueron los intersticiales de pantalla completa, muchos de ellos de adware que no se cerraban o te forzaban a instalar apps y falsos antivirus.

Luego empezamos a notar que mientras intentabas leer el artículo el texto no dejaba de moverse. Se debía a que con javascript se insertaban anuncios y menús completamente inútiles que forzaban la reestructuración del texto.

Cuando empezabas a acostumbrarte a leer textos animados te pusieron un vídeo que al hacer scroll y aparecer este completamente en pantalla empezaba a reproducir automáticamente el vídeo, con el audio habilitado.

Por si el agravio fuese insuficiente, ahora te ponen un anuncio en el medio del texto que te ocupa todo el ancho y tienes que hacer bastante scroll -incluso con pantallas grandes- para leer el texto que está a continuación.

Todo es sensible de empeorar, después de cargarte varios de esos anuncios -no llores demasiado si vas por 4G- te dicen que el artículo es sólo para suscriptores o que has superado el número máximo de lecturas en el mes.

Todos los periódicos digitales cayeron en estas prácticas.

Desde los más tradicionales a los más modernos, de izquierda a derecha, de arriba a abajo. Sin excepción. Incluso ninguno de ellos se apartó (aunque seguro que hay excepciones que no conozco o recuerdo) de esas prácticas ni hizo una crítica clara a lo que es una molestia -rozando la estafa- a los lectores.

Por supuesto, dichas prácticas están arruinando completamente la experiencia de los usuarios con sus móviles, generando gastos innecesarios en las conexiones de datos y haciendo que muchos busquen formas de evitar tanto abuso. De allí que hasta empresas tan «Big Corp» como Apple se planteen desarrollar bloqueadores de anuncios. O que Facebook les haga poner los contenidos en su sitio para «mejorar la experiencia de usuario» (imaginad una razón).

En sus múltiples saraos de congresos y entregas de premios hablarán de la crisis de la prensa, de las presiones, de la economía, de los malos que son los de su competencia, de que son los gurús de la transformación digital (yup, todavía, 20 años después). Pero nadie se plantará y dirá:

Estamos jodiendo y abusando de nuestros lectores. Paremos ya.

Pero no me malinterpretéis, no creo que sea malicia o codicia intencional. Creo que los periodistas simplemente han perdido el control de sus productos, los que lo tienen son sus comerciales.

Quizás me equivoco, ni siquiera lo controlan sus comerciales sino los de las agencias de anuncios. Estos no están preocupados del futuro de los medios digitales, sólo del de su agencia.

Esto de ceder su producto tampoco es nuevo pero es la primera vez que se basa en maltratar tanto al lector. Los informáticos decimos que tenemos que comer nuestra propia comida para perros.

Quizás es hora de que los periodistas lean sus medios como lo harían sus lectores. Tal vez se sorprendan.

 

El mejor consejo que puedo dar a un joven ingeniero

Etiquetas

,

En unos meses cumplo 25 años desde que presenté mi proyecto final de carrera de Ingeniería en Informática («la tesis» le llamaban en mi universidad) y algo más de 15 desde que leí mi tesis doctoral. Llevo años pensando en escribir sobre cuál fue el mayor error de mi carrera profesional y curiosamente -o no- me parece el mejor consejo -doble- que puedo dar, no hacer lo mismo:

No te adelantes, no te dejes seducir por puestos de dirección, gestión o representación. Durante los primeros 20 años de carrera sólo preocúpate de aprender y practicar para ser un experto de élite en el área en que estás trabajando. Cuando la domines creerás que lo sabes todo pero en realidad no sabes nada, aprende una nueva y repite el proceso: ganarás tanta humildad como conocimiento.

Ya llegará el momento -si lo deseas- de ocupar cargos de dirección o gestión, cuando seas un profesional reconocido: tendrás ya mucha experiencia en proyectos, sabrás bastante de la psicología y sus problemas sociales, tomarás mejores decisiones y serás de ayuda -que no un gestor molesto- y la gente a tu cargo te respetará y confiará desde el primer día. Afortunadamente con el dominio del software en tantas áreas se puede vivir bien como un buen ingeniero con experiencia. Además -desafortunadamente- es muy difícil encontrar ingenieros de alta calidad y con conocimientos en diferentes áreas.

No puedo dejar de poner otros que aprendí con errores que ahora intento no volver a cometer:

  1. Cuando trabajes en grupo, sobre todo si estáis intentando solucionar un problema, no eches la culpa de nada a tus compañeros, déjales que se equivoquen -es parte de la búsqueda-, colabora y asume las responsabilidades aunque no hayan sido tuyas.
  2. Por el contrario, si alguien nunca asume una responsabilidad o error, o culpabiliza a otros hasta de que no le dejan hacer nada, intenta que quede fuera del equipo. O que al menos no moleste.
  3. Participarás en proyectos interesantes y en otros que son marrones. En realidad todos pueden ser interesantes, depende de la actitud con que los encares: siempre hay cosas que mejorar y aplicar ideas creativas. Tengo el ejemplo reciente de un compañero que le tocó uno de esos proyectos marrones hasta que se dio cuenta que podía reducir los tiempos de ejecución de batches con threads concurrentes, se lo pasó pipa aprendiendo y practicando. No sólo le quedó un programa mucho más rápido y eficiente,  ahora él es un profesional mucho más formado y capaz que hace un par de meses.
  4. Puedes ser un doctor o un graduado en el MIT, pero a la hora de verdad tu compañero autodidacta y tú ejercéis de ingenieros. Trátalo como tal, los títulos formales solo sirven como carné de autoridad para la universidad ;), entre colegas no cuentan, solo lo que has demostrado saber hacer.
  5. Lee mucho código de terceros, fundamentalmente de las librerías, módulos y programas que usas habitualmente. Es una de las mejores formas de aprender.
  6. No dejes de leer, no solo de libros técnicos específicos, también de historia de la informática y ciencia, un poco de filosofía y psicología, álgebra, estadística y algo de cálculo.
  7. No te contentes con dominar una herramienta o lenguaje, aprende cómo funciona toda la pila que lo sustenta: el hardware, el sistema operativo, la máquina virtual o compilador, el API, las librerías, etc. Aprende C o ensamblador, son clarificadores de cómo funcionan las máquinas y todo lo que hay por encima.
  8. Domina al menos tres lenguajes diferentes que cubran: compilados, dinámicos, y funcionales.
  9. Tus programas nunca serán perfectos ni lo suficientemente buenos. Con el paso de los años te avergonzarás de tu propio código. Esto es bueno, has mejorado.
  10. Cuando programes piensa en los lectores de ese programa: escribe y comenta en inglés, que el código sea elegante, si el código te parece espagueti o ilegible descártalo y empieza de nuevo, no dejes de refactorizar mientras programas. No tengas miedo de descartar programas, no es tiempo perdido. Programar es como escribir un libro pero más complejo, si hasta los mejores autores siempre descartan capítulos o textos completos, ¿por qué tú habrías de acertar a la primera?
  11. No empieces a programar como un mono, pasa horas pensando, camina, conversa con colegas, pregunta, haz un prototipo, descártalo y vuelve a empezar hasta que esas primeras líneas no te den asco ni te generen desasosiego por lo que se viene: todo lo contrario, deberían entusiasmarte a seguir programando.
  12. De todas las ideas o propuestas, elige siempre la opción más sencilla (el KISS). Si no hay ninguna que sea claramente sencilla es porque falta pensar más. Si durante el desarrollo te das cuenta que hay soluciones más simples para hacer lo mismo (es muy habitual), descarta y comienza de nuevo.
  13. No hagas optimizaciones prematuras ni tampoco diseño de lo desconocido. Lo primero genera código más difícil de verificar y lo segundo complica el sistema con funcionalidades que nunca se usarán.
  14. Si cuando sale una nueva tecnología eres capaz de darte cuenta en qué podría servirte pero te ríes del hype y buzzwords es señal de que estás madurando como profesional.
  15. Si además de acabar tus proyectos en tiempos razonables y con programas fiables, los haces con buen humor, te acaban ilusionando hasta los más coñazos y festejas como un crío cuando pudiste solucionar una tontería que te tomó horas, ya eres un buen profesional. O al menos no un coñazo de profesional. Que es casi lo mismo.

PS: Ahora veo que me falta algo fundamental, siempre explica a tus colegas por qué haces algo o tomas una decisión. En el código o tomando un café.

 

Más de CUP, el mal uso de probabilidades y un bayesiano

Llevamos casi dos días y todavía hay gente que sostiene –contrario a lo que expliqué– que la probabilidad de empate en las votaciones de la CUP era 1/3030. Voy a explicar ahora por qué está mal, muy mal, ese razonamiento.

Al asumir que la probabilidad es 1/3030 están asumiendo que la probabilidad de un 0-3030 a favor del no (o viceversa) tiene la misma probabilidad que un 30-3000 o 1515-1515.

Asumieron que los resultados de la votación siguen una distribución uniforme en vez de binomial, es un error enorme, monumental, de estadísticas básicas (y luego buscan fórmulas complicadísimas, argumentos retorcidos y hasta realidades inexistentes para justificarlo).

Intentaré explicarlo con una analogía sencilla.

Sigue leyendo

Las probabilidades del empate de la CUP

Etiquetas

, ,

Actualización: un segundo artículo donde respondo a las cuestiones y errores más frecuentes sobre este tema: Más de CUP, el mal uso de probabilidades y un bayesiano.

En Twitter preguntan cuál era la probabilidad de empate:

Dado que había ya respuestas erróneas respondí, luego expliqué cuál es la forma de calcular la probabilidad de que 3030 personas cuyos votos son independientes (se supone) y que tienen dos opciones (no contamos abstenciones, varía poco). Pero no hubo caso, seguían insistiendo que estaba mal. Unos con fórmulas equivocadas, otros asegurando que hubo tongo y conspiraciones varias. Y otros que si hubiese sido impar el nḿero de votantes el empate es imposible (¡gran observación! :roll:).

Por supuesto que cuando calculas probabilidades te ciñes a unos supuestos, en este caso son muy simples:

  • Son 3030 votos contabilizados, cada uno puede ser sí o no (o 0 y 1).
  • Un empate se da cuando hay igual número de síes (1) que de noes (0).

Sigue leyendo

Los cretinos clasistas de cada cita electoral

Etiquetas

,

Hace tiempo que estoy bastante indignado con el trato de idiotas a los que votan diferente, última y especialmente por lo de los votos de los viejos. Por ejemplo (enlace al artículo):

Estoy molesto de verdad, por eso dedico este breve texto:

Sigue leyendo

Cuidado con las matemáticas de Hollywood… y los matemáticos

Etiquetas

,

Aprovecho esta tontería que me hizo gracia, por la contradicción de la pifia del crítico de pifias, para reactivar mi blog después de la paliza que me di escribiendo el libro (y que me quitó las ganas de escribir hasta ahora mismo).

Iba en el coche desde el Parc Bit a casa y pongo La Ser, eran más o menos las 18:40 hs. Justo comenzaba una sección de matemáticas y estaba un invitado (¿José María?) que también era matemático y había escrito un libro sobre las pifias matemáticas en el cine de Hollywood.

Comenzaron comentando el desconocimiento general de matemáticas de la población y que no hay que hacer caso a alguien que suelta cálculos acrobáticos (sic), que hay que pensar y hacer los cálculos uno mismo. Porque además los que mienten con los cálculos lo hacen con mucho aplomo (sic).

El primer ejemplo que muestran  de cine es sobre esta escena de Superman II:

 

El niño empieza a caer por las cataratas del Niágara y Superman lo rescata antes que llegue al agua unos 28 segundos después. Aunque se podría decir que la extensión de la escena no corresponde con el tiempo real sí es una exageración. El Niágara tiene una caída máxima de sólo 50 metros, no varios centenares.

Pues bien, el matemático especialista en las pifias comenta que es imposible que lo haya podido rescatar pasado esos 28 segundos, que aplicando la fórmula bla bla bla (supongo que dijo la de 1/2 * at², no alcancé a registrarla bien) en ese tiempo habría recorrido más de 4 km.

Por supuesto le hice caso y un rápido cálculo mental me dijo que era imposible. Sobre todo porque el matemático se había olvidado de la velocidad terminal: la velocidad máxima que puede alcanzar en un fluido un cuerpo acelerado por la gravedad. En particular la del cuerpo humano en horizontal es cercano a los 55 m/seg.

Un cálculo mental rápido me indicaba que aún en caso que hubiese partido con esa velocidad en 28 segundos hace unos 1 500 metros (1 540 calculadora en mano) no más de 4 000.

Afinando más los cálculos, para que un cuerpo humano alcance esa velocidad terminal se toma más de 6 segundos. Sin rozamiento ni velocidad terminal tardaría exactamente 55 m/seg / 9.8 m/seg², 5.6 segundos.

En esos primeros 6 segundos habrá recorrido una distancia aproximada a 1/2 * 6 * 55 m/seg, o sea ~ 165 metros.

Los restantes 22 segundos lo habría recorrido a 55 m/seg, una distancia de 1 210 metros.

En total, 1 375 metros. Tres veces menos que la «corrección» del especialista.

Ya, un apunte de smartass, pero es que me hizo gracia que el matemático ignorase reglas físicas tan básicas. Pero tiene razón, era imposible que pudiese rescatarle y nunca te fíes de los que hacen malabarismos de cálculos en los medios, revísalos cuidadosamente 🙂

PS: Por otro lado está claro que era una licencia necesaria, caso contrario a Superman no le da ni para sacarse la chaqueta que llevaba.

 

Versión impresa de «Principios y algoritmos de concurrencia»

Etiquetas

,

Ya se puede comprar el libro en versión en papel. Está disponible en Amazon (también en .COM y todos los Amazon europeos) y en CreateSpace. En los próximos días y semanas estará disponible en otros canales de distribución, también para universidades e instituciones académicas.

Si adquirís la versión impresa en Amazon luego se puede comprar la versión Kindle por menos de 1 € ($ 0.99). Si tenéis algún problema o si queréis la versión para otro lector avisadme por email (gallir en gmail).

En breve haré una presentación conjuntamente con APSL en el Parc Bit en Palma. En octubre está planificado en Madrid, organizado por Open Innovation de BBA. Iré avisando.

Breve historia

No pensaba sacar, al menos en plazo tan breve, la versión impresa. El libro fue diseñado para un ebook por lo que tenía que solucionar dos problemas:

  1. Conversión adecuada a PDF.
  2. Editar y modificar porque el código completo no podía ser incluido en el papel. Serían al menos unas doscientas páginas más y tampoco se cuenta con la facilidad de hiperenlace directo a la página del código.

Pero gente de Create Space se puso en contacto conmigo para que lo saque en papel, les expliqué el problema y el trabajo adicional que me costaría la conversión. Consultaron a sus técnicos para ver si podrían convertir desde asciidoc (el formato original en el que escribí) o DocBook (el formato intermedio que usa) pero respondieron que no sabían cómo hacerlo.

Siguieron insistiendo en que haga el esfuerzo hasta que al final me convencieron (gracias Yasmin y Alessandro). El conversor más moderno, asciidoctor-pdf, no funciona correctamente todavía. Era imposible usarlo por lo que tuve que usar el «tradicional» Apache-FO. No es nada simple usarlo, de hecho es muy complicado para hacer funcionar todo el toolchain.

Una solución la dan los scripts de aciidoctor-fopub, al que tuve que hacer algunas modificaciones para que incluya el separador de sílabas. Luego aprender el formato y esquema de las hojas de estilo en XSLT que usa el Apache-FO para poder darle el formato adecuado (tamaño, páginas, fuentes, colores, cabeceras y pie de páginas, etc.).

Una vez solucionado la conversión a PDF el trabajo consistió en eliminar los apéndices y modificar las referencias para indicar los ficheros en el repositorio de Github.

Pero lo que más trabajo me llevó, diría que más de 40 horas, fue solucionar lo de la conversión a PDF que expliqué antes. Luego todo fue más sencillo, y la verdad es que en papel ha quedado muy bien. Bueno, IMHO 🙂

Principios y algoritmos de concurrencia: Fe de erratas

Etiquetas

,

Estas son las fe de erratas (disculpas) de las diferentes versiones del libro Principios y algoritmos de concurrencia. Cuando las hago actualizo inmediatamente las versiones de Amazon y Google Play. Pero si la habéis comprado antes no las recibís a menos que notifique que es un error importante, en cuyo caso recibiréis una versión actualizada.

El número de versión y fecha sale al principio, en la página de créditos:

Principios y algoritmos de concurrencia
© Ricardo Galli Granada
Diseño de portada: Damián Vila
Ilustraciones: Juan Ramón Mora «JRMora»
Foto: Spaghetti Worlds, Carl Milner (Flickr)
Corrección: Marilín Gonzalo y Juan Sosa
Versión: 1.0.7, 2015-06-20
Palma de Mallorca, 2015
ISBN: 978-84-606-8761-0
Licencia: CC BY-NC-ND 4.0

Sigue leyendo