Antes de nada, acabo de publicar la v1.0.4 y pufff cada día me supero a mi mismo
Podemos decir que SPOK gana a maskprocessor en performance. He portado la lógica de buffering y write a C teniendo MUY en cuenta los tamaños de buffer para escritura en disco y caché de CPU.
He eliminado el multi-threading para I/O en fichero ya que eligiendo sabiamente el tamaño de buffer es innecesario, oye no te irás a la cama sin aprender nada nuevo. Al parecer con un tamaño de entre 4KB - 2MB approx. existe un balance entre overhead en syscalls aprovechando cache y bloques de página del disco duro. A parte por cada sub secuencia completa re-calculo el tamaño de buffer, todo al milímetro.
[kub0x@prism maskprocessor-0.73]$ time ./mp64.bin ?l?l?l?l?l?l -o 1.txt
real 0m5.614s
user 0m2.333s
sys 0m2.153s
[kub0x@prism Release]$ time ./spok -g 1.txt -i 6,6
Using default charset.
Total storage needed: 2062.24 MB
All words of length 6,6 have been generated.
real 0m5.470s
user 0m3.351s
sys 0m1.612s
[kub0x@prism Release]$ time ./spok -g 1.txt -c 0123456789ABCDEF -i 8,8
Total storage needed: 36864 MB
All words of length 8,8 have been generated.
real 2m03.121s
user 1m0.428s
sys 0m33.678s
Vamos que ni multi buffer ni gaitas. Escritura síncrona con tamaño de buffer estrictamente basado en hardware
__________________________________________________________________________________________________
@NEBIRE: Buenos benchmarks, supongo que será el tiempo que tarda el algoritmo en generar sin printear, ya que I/O en stdin/out es costoso, ni maskprocessor lo handlea bien (tarda mucho mas que escribir en disco).
Me he animado a hacer el benchmark con tu ejemplo de charset A-Z y length fija de 7:
[kub0x@prism Release]$ time ./spok -g 1.txt -i 7,7
Using default charset.
Total storage needed: 61277.8 MB
All words of length 7,7 have been generated.
real 0m20.817s
user 0m20.764s
sys 0m0.010s
Ojo sin printear ni logear en disco, sólo ver cuanto tarda el método en generar todas las secuencias (unos 401.10^6 / sec). También hay que tener en cuenta la CPU que utilizo. He añadido la opción de printear sin logear en disco, basta con quitar el parametro -g o --generate del input, todo esto siguiendo tu consejo.
Por cierto me ha gustado tu enfoque sobre:
Una particularidad muy interesante en todas estas implementaciónes del algoritmo2, es que cada carácter obtiene su propio alfabeto (de forma indirecta, tal como se explica a continuación)... aunque por defecto uno ponga A-Z, en realidad hay tres parámetros:
Valor minimo, ejemplo: AAAAAA
Valor Máximo, ejemplo: ZZZZZZ
Valor Inicial, ejemplo: GDAXCA
Esto permite que pueda indicar el valor mínimo y máximo de formas distintas, por ejemplo así:
Posiciones: 543210
------------------------------
Valor Minimo: A0ZD9A
Valor Máximo: ZZAK0Z
Entonces, implica que, tiene definido un alfabeto (en estos casos siempre basado en el ASCII)
El carácter '0': A-Z ---> 26 caracteres, incremento
El carácter '1': 9-0 ---> 10 caracteres (numéricos), decremento
El carácter '2': D-K ---> 13 caracteres incremento
El carácter '3': Z-A ---> 26 caracteres decremento
El carácter '4': 0-Z ---> 43 caracteres 0-9, 9-A, A-Z (10+7+26 si no he contado mal)
El carácter '5': A-Z ---> 26 caracteres.
Tengo pensado implementar cositas así tras optimizar todo, siempre me acuesto diciendo ya está optimizado pero cada vez saco algo
Estaría bien que me sugirierás alguna característica más, he pensado en máscaras o combinaciones de múltiples diccionarios. Para ello hay que pensar que contraseñas elige la gente. Me molaría probar tus algoritmos también, sobre todo el algoritmo 3, ya que repito que el mio tiene pinta de algoritmo 2.