2016-05-20

Volviendo a C++

En mi laburo necesitan que programe en C++ nuevamente, así que hace unos días estoy mirando y recordando C++. ¡Qué incómodo que es!

Default constructors, copy constructors, asignment operators, que encima en su versión generada por default andan mal. Métodos virtuales, ¿por qué hay otra opción, y encima no es el default? ¿Herencia virtual? ¿Functors o function pointers? ¿Punteros comunes, shared pointers, referencias? ¿Cómo obtengo el shared_pointer de this? ¿Y si hay herencia? ¿Templates? Encima los templates son simultáneamente complicadísimos y sumamente limitados. Por ejemplo, ¿cómo hacés un template que cambie el nombre de los métodos generados en función de algún parámetro? Creo que no se puede (si sabés cómo hacerlo sin usar #define decime). Escribir todo varias veces, forward declarations, declaraciones en el .h e implementaciones, con la signatura repetida, en el .cpp.

Y ni hablar de los quilombos asociados, sobre todo en Windows, que no son del lenguaje, pero que te complican la vida. Cambiás de compilador y linkea mal y, en el caso de Visual Studio también genera binarios incompatibles según el runtime que elegís. De regalo el Visual Studio que estoy usando no se da cuenta cuándo recompilar y genera mierda desactualizada.

Pero eso no es lo peor de C++. Para mi lo peor de C++ es que no te deja pensar. Tenés que esquivar tanta complejidad accidental que el código fuente no reflejo de las ideas subyacentes. Eso nos devalúa como programadores.

2016-05-01

Mejorando pingmon.py

En mi post anterior puse un scriptcito en python para monitorear una conexión con ping. Después de eso lo mejoré un toquecito, y ahora toma los últimos 10, 100 y 1000 probes y calcula el porcentaje que tienen respuesta. La ejecución se ve así:
$ pingmon.py 8.8.8.8
(1) 10:N/A 100:N/A 1000:N/A
(2) 10:N/A 100:N/A 1000:N/A
(3) 10:N/A 100:N/A 1000:N/A
(4) 10:N/A 100:N/A 1000:N/A
(5) 10:N/A 100:N/A 1000:N/A
(6) 10:N/A 100:N/A 1000:N/A
(7) 10:N/A 100:N/A 1000:N/A
(8) 10:N/A 100:N/A 1000:N/A
(9) 10:N/A 100:N/A 1000:N/A
(10) 10:N/A 100:N/A 1000:N/A
(11) 10:100.00% 100:N/A 1000:N/A
(12) 10:100.00% 100:N/A 1000:N/A
(13) 10:100.00% 100:N/A 1000:N/A


Y el código del script creció un poquito, pero sigue entrando en un post.
#!/usr/bin/env python

import subprocess
import sys
import re

SEQ_NUMBER_RE = re.compile(".*icmp_seq=(\d+) ttl.*")

def pct_str(probes, count):
  if len(probes) < (count + 1):
    return "N/A"
  return "%.2f%%" % ( 100 * sum(probes[-count-1:-1]) / count )

def monitor(ip):
  probes = []
  ping = subprocess.Popen(["ping", ip], stdout=subprocess.PIPE)
  stdout = ping.stdout

  stdout.readline() # Ignore first line
  line_count = 0
  last_seq_number = 0
  while True:
    line_count +=1
    seq_number = int( SEQ_NUMBER_RE.match(stdout.readline()).group(1))
    probes.extend([0] * (seq_number - last_seq_number - 1))
    probes.append(1)
    print "(%s) 10:%s 100:%s 1000:%s" % (
      line_count, pct_str(probes, 10), pct_str(probes, 100), pct_str(probes, 1000)
    )

    probes = probes[-1000:] # Keep memory usage bounded
    last_seq_number = seq_number

def main(argv):
  monitor(argv[1])


Siéntase a gusto de hackear este script si quieren algún monitoreo distinto (cambiar la salida y/o la forma de monitorear).

Espero que les sea útil,
Aureliano.