Windows reduce velocidad de ejecucion.

Iniciado por Usuario887, 20 Octubre 2021, 11:01 AM

0 Miembros y 2 Visitantes están viendo este tema.

Usuario887

 Hola,

Me he dado cuenta de que cuando un programa tarda mucho en un ciclo (haciendo algo util o no) Windows reduce la velocidad de ejecucion del programa (imagino que para evitar denegaciones del servicio). Quisiera saber como hacer excepciones de esto para algunos programas ya que se esta tardando literalmente cuarenta y un minutos en cargar veinte megabytes de un archivo  :huh: lo cual me parece descomunalmente demasiado. Me da igual que se realentice el sistema.

Gracias, un saludo.

Serapis

Es 'raro' eso de que cargue 20 mb. de tamaño de un fichero en memoria en más de 40 minutos, debería ser inmediato (hoy día 20 mb. es poca cosa).

Puede suceder una de las siguientes cosas (así, sin más detalles).
- No queda memoria libre suficiente, o está muy fragmentada. Tu mismo podrás comprobar si es el caso y de ser necesario activa la escritura de RAM a disco (si no se cambió por defecto el S.O. suele ootorgarle algo así como un mínimo de 512Mb.). Por su parte cuando hay mucha memoria en el sistema, e spreferible desactivarlo, porque su uso ralentiza al S.O. que a pesar de la gran cantidad de mmemoria en el equipo, pueda empeñarse en tirar de páginas a disco.
Otra opción más sencilla si se entiende que ya está configurado adecuadamente, es cerrar aplicaciones que no se precisan, para liberar memoria.

- Que haya algún sector dañado en el disco duro. Puede abortar la operación o puede intentr 'rumiar' intentando leer el contenido y avanzar muy lentamente.
en tal caso o ante la duda conviene hacer un chequeo dle disco completo (buscando por secotres dañados y que queden marcados como tal y que recupere los que no estén dañados).

- Adicionalmente la presencia de algún virus podría tener suspendido algún proceso... o manipulado algún driver.

- Algo mucho menos frecuente  (depende del S.O. de tu equipo), es que dado ciertas fallas (generalmente por daños en disco), es que le haya cambiado el modo de tranferencia (de DMA a PIO). Esto podía ser frencuente a finales de los 90 y comienzos de siglo, pero no he escuchado desde entonces que esto siga sucediendo hoy (por eso digo que depende dle S.O. con el que estés haciendo tus pruebas).

Y sin más detalles no se me courren más razones...

Usuario887

#2
Gracias por responder, Serapis.

Ya se que es raro.

Perdon por no plantear la duda tan exactamente pero no es que se tarde en mover la informacion del disco a la memoria. Sere mas preciso respecto a la estructura del programa:

El programa carga el archivo completo en memoria (20 mb) y en esto se tarda unos 700 ms.

En lo que se demora es en lo siguiente:

Una vez el contenido del archivo en memoria, que es simplemente un conjunto de estructuras anidadas pero eso da igual... El problema es que yo estoy midiendo constantemente el rendimiento del programa, que supongase que es algo asi:


for(i=0;i<tamanyo del archivo;i++)
{

fread((struct __loquesea *) &estructura, sizeof(__loquesea), 1, hArchivo);

//...
}


Como decia, estoy midiento el rendimineto del programa y resulta que los primeros 2 segundos el programa carga mas de cien mil de estas estructuras, luego en los siguientes dos segundos carga cincuenta mil, luego veinte mil... hasta llegar a unas diez mil estructuras por segundo.

Las estructuras que necesito cargar son 11.352.960.000 en total, y podras deducir que cuando el programa falla estoy horas depurandolo lo cual me parece una tonteria...

El punto: No entiendo por que el programa carga muchas por segundo al principio y a medida que avanza la ejecucion del programa Windows ejecuta el programa mas lentamente, como previniendo que un bucle infinito inutil este denegando el servicio o evitando la ejecucion a otros programas. No entiendo por que hace esto

Serapis

Si estás leyendo 100.000 estructuras en principio, a pocos bytes que tenga esa estructura, habrás consumido los 20Mb. en un parpadeo. Entonces me pregunto si estás obteniendo y consultando el retorno de fread, si no devuelve la misma cantidad de bytes que se intenta leer, o se llegó al final de fichero o hay un error.

Cuando hay un error se genera un reporte, como estás en un bucle y no lo tratas (es un a dedución a falta de un código más explícito), básicamente estás generando reportes de error, constantemente que por sí mismo podrían explicar la caída del rendimiento.

Si no es esto, deberías poner aunque sea un ejemplo práctico que reproduzca el error, no necesariamente todo tu código, basta simplificado para que pueda reproducirs el error e investigarlo un poco más a fondo.

Eternal Idol

No hay suficiente informacion como para que lo adivine pero deberias minimamente comprobar el uso de CPU y RAM en el Administrador de tareas de Windows (y el Monitor de recursos tampoco vendria mal) para detectar el cuello de botella. Si tu programa tiene un solo hilo lo mas normal es que no pueda usar mas que un procesador/nucleo del total y dudo que cambie porcentaje de uso de CPU con el tiempo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Usuario887

#5
Esta bien. Esta es la funcion en la que el programa demora los 41 minutos ejecutando:


int LoadNextQuoteIntoQuotesmem (struct __csvheader *csvheader, struct __quotesmem *bQuotesmem)
{
   char c;
   int i, k;

   char szBuffer[MTFMT_MEM_QUOTEMAX];

   //fsetpos(csvheader->hFile, &(csvheader->fpos));

   for (i=0;i<MTFMT_CSV_QUOTEN;i++)
   {
       c=0;
       for(k=0;c!=','&&c!='\r'&&c!='\n';k++)
       {
           c=csvheader->bBuffer[csvheader->fpos];
           csvheader->fpos++;
           if(c==0/*EOF*/)
           {
               return MTERR_CSV_EOF;
           }
           szBuffer[k]=c;
       }

       szBuffer[k-1]=0;

       switch(i)
       {
       case 0:

           strcpy (bQuotesmem->data0, szBuffer);
           break;

       case 1:

           strcpy (bQuotesmem->data1, szBuffer);
           break;

       case 2:


           bQuotesmem->data2=atof(szBuffer);
           break;

       case 3:

           bQuotesmem->data3=atof(szBuffer);
           break;

       case 4:

           bQuotesmem->data4=atof(szBuffer);
           break;

       case 5:

           bQuotesmem->data5=atof(szBuffer);
           break;

       case 6:

           bQuotesmem->data6=atof(szBuffer);
           break;
       }
   }

   if (i<MTFMT_CSV_QUOTEN)
   {
       return MTERR_QUOTEN_DOESNT_MATCH;
   }

   //fgetpos(csvheader->hFile, &(csvheader->fpos));

   return 0;
}



Por lo que podran deducir el archivo en cuestion es un CSV con nueve columnas (Y en este caso el archivo tiene 11.352.960.000 filas).

La estructura __quotesmem es simplemente una estructura en RAM en la que ordeno los datos para poder manejarlos luego.

Cabe mencionar que:

La estructura es una lista enlazada, por lo que por cada fila nueva llama a malloc. ¿Es malloc una funcion lenta? Porque de ser asi puede estar ahi el problema la verdad...

La funcion es llamada cuantas veces sea necesario hasta que retorne final del archivo MTERR_CSV_EOF.

Importante tomar en cuenta: Para cuando se llama esta funcion el contenido del archivo ya esta en memoria RAM. Se encuentra todo en csvheader->bBuffer.

Nota: Hay cadenas comentadas porque solia usar esta funcion accediendo a cada caracter individual del archivo, lo cual.... jajajaja... eso si se tardaba un buen rato. Cuarenta minutos es muy poco en comparacion. Aun asi me parece mejorable por eso hago este tema, porque ni siquiera creo que este calculando algo innecesariamente aqui. Insisto en que tal vez sean las tantas llamadas a malloc...

Eternal Idol, el programa usa siempre el mismo porcentaje de la CPU. Lo que cambia es el acceso a memoria. Si pongo en el codigo un printf("%d/%d\r", csvheader->fpos, csvheader->fsize); Puedo ver como los primeros cientos de miles de bytes se cargan rapidamente, y luego va disminuyendo la velocidad de carga. El porcentaje de uso del procesador esta siempre igual (en torno a un 15%). Lo que va disminuyendo es la velocidad de acceso a la memoria RAM.

Usuario887

Otra cosa importante que olvide mencionar es que se que el rendimiento podria ser mejorado mucho porque puedo abrir cuatro instancias del mismo, al mismo tiempo y los cuatro se tardan los mismos 41 minutos ejecutandose.

MinusFour

¿Ese archivo entonces pesa por lo menos unos 80GiB? Tienes 10.57 "gibifilas"... Si cada fila solo tuviera un byte, estarías hablando de 10GiB. Ese archivo debe ser un monstruo para que tengas tantas filas...

Yo creo que a finales de cuenta, el comportamiento en el cual se reduce el rendimiento a medida que sigue progresando se puede explicar por una cache. Puede ser quizás la cache del sistema operativo, cache de CPU (L1, L2, L3) o cache del dispositivo de almacenamiento (o de varios de estas).

De los cuales, solo puedo ofrecer una explicación para los SSDs (aunque me imagino que esto también vale para HDDs híbridos). Los SSDs pueden hacer uso de memoria para conservar un mapa de la información almacenada, así acelerando la respuesta del SSD. Llega un punto donde la memoria se satura y aquí el rendimiento empieza a degradar. Los SSDs PCIe gen 4 pueden por ejemplo alcanzar lecturas desde hasta 7.7GB/s... por un periodo de tiempo... En promedio puedes obtener alrededor de 1.5GB/s si mal no recuerdo...

CitarPuedo ver como los primeros cientos de miles de bytes se cargan rapidamente, y luego va disminuyendo la velocidad de carga. El porcentaje de uso del procesador esta siempre igual (en torno a un 15%).

¿Revisaste que no tuvieras un hilo/cpu al tope?

Necesitas poder verlo así:


Usuario887

Me equivoque de calculo  ;D

En total son 31.536.000 estructuras mas o menos...

Adjunto capturas del rendimiento:




Esto en tiempo de ejecucion.


Insisto, si no es malloc esto se tiene que deber a algun sistema de seguridad que proteja al OS de ataques de denegacion de servicio por parte de programas...

Usuario887

#9
Ha de ser que nunca habia cargado tantas entradas en una lista enlazada... Siempre las habia hecho por practicar con unas doscientas como maximo. ¿Son tan lentas en realidad? ¿Si es asi como es que programas como GTA V que cargan 2 GB en memoria lo hacen en menos de dos minutos? Mi programa esta cargando 20 MB   :huh:

Obviamente se debera a las habilidades de programacion. Supongo que intentare algo que no sean listas o que implique reservar memoria del heap...