Eficiencia versus capacidad

Iniciado por Usuario887, 20 Noviembre 2020, 17:15 PM

0 Miembros y 1 Visitante están viendo este tema.

Usuario887

Hola, tengo un pequeño dilema... ultimamente la mayoria de programas que hago se encargan de "gestionar" grandes cantidades de datos y me esta surgiendo un problema: el tiempo. No era problema cuando mis programas se tardaban de 5 a 10 segundos en procesar la informacion, pero ahora que ese numero ha llegado a de 30 a 45 minutos, comienza a preocuparme. Evidentemente las computadoras tienen un limite, no pretendo superarlo, solo planteare la forma en que funcionan mis programas, mis ideas, y espero sus opiniones sobre ellas y las suyas.

Bueno, para empezar, se que los datos de la RAM son considerablemente mas rapidamente accesibles que los datos en disco, eso no lo discuto... pero tomando en cuenta que se aplican mecanismos de memoria virtual cuando los datos son "bastantes" crei que acceder al disco "en porciones" seria mas ideal, para asi gestionar el swap memoria-disco yo mismo y adaptarlo a las necesidades de mi programa. Sin embargo comienzo a poner en duda la validez de mis metodos.

Por si alguien cree necesitar que sea mas especifico: el programa carga cierta cantidad de datos en un buffer peque¿o, hace algo con ellos, luego carga otra cantidad peque¿a, hasta que encuentra una coincidencia, la compara, la carga, carga una porcion mas grande, la procesa...

Mi pregunta, en resumen y siento ser engorroso, es: ¿que es mas eficiente, cargar 1 GB de datos en memoria RAM y procesarlos, tomando en cuenta que existe la memoria virtual, o acceder a un dato a la vez en el disco (digamos, buferes de 256 a 512 bytes)? Con eficiente quiero decir rapido, valoro cada segundo...

La respuesta puede ser obvia pero realmente no se en la practica que tanto afecte el rendimiento de la memoria RAM la memoria virtual.

Gracias y espero sus respuestas. Saludos!.

ThunderCls

Respondiendo a tu pregunta inicial, el acceso (lectura/escritura) a disco es mas costoso y posee mas latencia que el acceso a la DRAM, por lo que el manejo de datos sera mas rapido en RAM directamente que en un HDD/SSD. La respuesta obvia entonces seria que debes entonces cargar todo el fichero en memoria en lugar de leer "chunks" del disco?. Pues eso dependera de varios factores. Depende del tamaño del fichero que deseas manipular o de la eficiencia del uso de memoria que persigas o simplemente del diseño en particular que desees con tu software. Quizas puedes hacer como dices y leer todo el fichero en segmentos cada vez. Podrias tambien mapear el fichero en memoria y dejar que el SO maneje las paginas de memoria por ti, lo que podria llegar a ser mas rapido pero tambien puede tener sus dolores de cabeza.

Habiendo dicho lo anterior, creo que no estaria de mas hacerte algunas preguntas extras como:
- Que tan eficiente es tu diseño?. Cuan escalable? Podrias usar algun engine de bases de datos en lugar de "ficheros"?
- Estas seguro que la degradacion en rendimiento viene dada por esta situacion en particular? Haz usado algun "profiling tool" en tu codigo y confirmado lo anterior?
- Tu software usa o puede usar algun tipo de trabajo concurrente, procesamiento en paralelo? Multihilos?
- Podrias usar alguna libreria creada justamente con el fin de obtener el maximo rendimiento al leer grandes cantidades de datos en lugar de reinventar la rueda?
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

Usuario887

#2
Gracias por tu respuesta, ThunderCls.

Citar- Que tan eficiente es tu diseño?. Cuan escalable? Podrias usar algun engine de bases de datos en lugar de "ficheros"?

Es escalable. Sin embargo el DBMS y el formato de la base de datos tambien los programe yo, por necesitar ser especifico y por tanto esto tambien depende de mi.

Citar- Estas seguro que la degradacion en rendimiento viene dada por esta situacion en particular? Haz usado algun "profiling tool" en tu codigo y confirmado lo anterior?

No estoy segundo de que es una profiling tool. Sin embargo hasta ahora ha sido solo mi intuicion; cuando el programa se encuentra cargando los datos desde el disco, se tarda muchisimo mas (18 segundos) que cuando las procesa en memoria (1-3 segundos)

Citar- Tu software usa o puede usar algun tipo de trabajo concurrente, procesamiento en paralelo? Multihilos?

No. La ejecucion debe ser completamente secuencial.

Citar- Podrias usar alguna libreria creada justamente con el fin de obtener el maximo rendimiento al leer grandes cantidades de datos en lugar de reinventar la rueda?

Sinceramente no conozco ninguna... tampoco sabian que existian tal tipo de librerias...

Saludos!.




Edito: Ya cambie el programa. Es 100 veces mas rapido  :-\ ;-) (se tardaba 5 segundos en cargar un dato, y lo que se traduce a hacer lo mismo con el dato esta vez en RAM tarda alrededor de 0.05 segundos). Me impresiono que de hecho fuesen cambios menores... pense que seria mas complicado. Gracias.

Serapis

Tu buffer nunca precisa ser menor que el tamaño de un sector del disco.

Es decir crear un buffer de 256 o 512 bytes es practicamente ridículo ( a estas alturas, en los 80s sería bastante conforme).
Mínimo 4Kb. y preferentemente 64Kb. pero salvo que tengas una memoria muy reducida, mi recomendación es que apuntes a buffer de tamaño 1-8 mb.
En cualquier caso, usa siempre un valor de base binaria, no de valores arbitrarios.

La unidad del S.O. tiene un tamaño de sector que el propio S.O. elige, pero en las otras unidades cuando tu formateas conviene que le des el tamaño que mejor convenga conforme al tipo de ficheros que va a alojar... por ejemplo si una unidad va a contener películas y otros vídeos, un tamaño de sector de 32 o 64kb. es lo mas acertado... y si vas a tener chorrocientosmil ficheritos minúsculos, es preferible un tamaño de 4kb. como tamaño de sector.

La lectura de 1Gb. según el disco duro (doy por hecho que se trata de un HDD y no de un SSD), no debería demorar mas del rango 1-20sg (dependiendo del disco). De hecho sería conveniente hacer pruebas de rendimiento... crea un programa que lea 3-4 ficheros (distintos) de 1gb. empezando con un buffer de 4kb. y terminando (por ejemplo) con un búffer de 64Mb.
Lee primero el fichero-A con  el tamaño elegido y notas el tiempo al término, luego con el fichero-B, luego el fichero-C, etc... antes de saltar a otro tamaño (el objetivo es que no dejes usar la caché del disco duro, el primero opera con su tiempo y el resto se beneficien de dicha caché y por tanto falsifique el rendimiento real... saltando a distintos ficheros, prácticamente se imposibilita dicha situación).

Por último un rendimiento lento del disco se obtiene en algunas situaciones (así al vuelo se me vienen estas causas).
- Poco espacio libre en la unidad (se nota sobretodo al escribir, pero también al leer).
- Unidad muy fragmentada. Supone reposicionar el cabezal de lectura para leer cada sector, si el tamaño del sector es excesivamente pequeño, supone más reposicionamientos y por tanto más lentitud con ficheros muy grandes.
- El ingenioso hidalgo don virus de la Mancha... se emperra en mancharte tu rendimiento con cada lectura escritura.
- Alguna tarea programaa de monitoreo demasiada exhaustiva.
- Algún virus, u otro programa que se emperra en monitorear determinados procesos. Imagina un intruso minando bitcoin en tu equipo, por ejemplo...
- Disco siendo constantemente accedido por otros procesos en marcha.
- Demasiados procesos consumiendo recursos: memoria, CPU, etc...
- ...hay más factores, pero estos son los más habituales...