Foros - Stratos

Programadores => Código de la Semana => Mensaje iniciado por: ethernet en 11 de Diciembre de 2002, 08:11:10 PM

Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 11 de Diciembre de 2002, 08:11:10 PM
Puedes bajarte el codigo de:

http://www.stratos-ad.com/codigosemana/cre...clenodepool.zip  




Éste código fue enviado el martes 3 de diciembre del 2002  por Fernando Rodríguez frodrig99@yahoo.com

Si quieres enviar tu propio código hazlo a eth_cotd@lycos.es
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 11 de Diciembre de 2002, 08:19:52 PM
Buen cotw !

Unos detalles:


 assert(usNumNodes < MAX_POOL_SIZE);

 unsigned short usIt = 0;

 for (; usIt < usNumNodes; ++usIt) {

Node* const pNode = new Node;

assert(pNode);

m_FreeNodes.push_back(pNode);

 }


yo lo cambiaria por :


assert(usNumNodes < MAX_POOL_SIZE);

 unsigned short usIt = 0;

 Node* const pNode = new Node[usNumNodes];

 assert(pNode);

 for (; usIt < usNumNodes; ++usIt) {

m_FreeNodes.push_back(pNode + usIt * sizeof(Node) );



 }



de esa manera solo reservas una vez.

Otra cosa q no entiendo es por q pasar un unsigned short con &. Por q unsigned short? por q & y no pasarlo directamente (q acupa menos pila, si eso es lo q te preocupa) ?

Por cierto, creo q en release el assert se deshabilita.
Tb tengo entendido q STL hace algo parecido a lo q haces tu, reserva memoria con antelacion. En la doc de la STL de SGI viene al final explicado.

saludos
Título: ....
Publicado por: Grugnorr en 11 de Diciembre de 2002, 10:16:14 PM
                                Gracias fer :P                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: fiero en 11 de Diciembre de 2002, 10:58:54 PM
                               
Citar
Otra cosa q no entiendo es por q pasar un unsigned short con &. Por q unsigned short? por q & y no pasarlo directamente (q acupa menos pila, si eso es lo q te preocupa) ?

Solo una puntualización, un unsigned short& ocupa lo mismo en la pila que un unsigned short* y que un unsigned short. Las tres formas meten 32 bits en la pila (1 posición), al hacer la llamada. Es que yo he entendido eso, si no te referias a esa "pila" pido perdón  :oops:  :)

un saludo                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: metaxas en 12 de Diciembre de 2002, 02:41:05 PM
                                ¡ Muy buen COTD !, te comento par de cosillas que se me ocurren para tratar de hacerlo más eficiente:

- Cada vez que creas un nodo nuevo para la lista de libres, lo creas en el heap. Dado que el pool tiene un tamaño máximo, puedes crearte un array de Nodes de ese tamaño en la pila (los accesos a variables declaradas en la pila son más rápidos que los accesos al heap), y en vez de crear un Node nuevo y meter su puntero en la lista de libres, meterías el puntero al Node adecuado en el array. Para borrar un node, lo que harías sería resetear el Node del array a sus valores por defecto, en vez de hacerle un delete.
- El std::list que usas para guardar los nodos libres. Cada vez que le haces un push_back te está reservando memoria para almacenar el puntero, pues al contrario que el vector el list no te reserva memoria en segmentos de tamaño fijo, sino individualmente para cada elemento. Lo ideal sería hacerle un resize de MAX_NODES al principio y hacer siempre un push_front y un pop_front, como si fuese una pila vamos, pero eso sí, guardando tu un contador con el tamaño actual en cada momento (pues al hacerle un size() te devolvería siempre MAX_NODES)


Metaxas                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 12 de Diciembre de 2002, 05:58:45 PM
Un unsigned short en mi maquina son 16 bits ... y en mi maquina un unsigned short & y un unsigned short * son 32 bits. y mi maquina trabaja mejor con datos de 32 bits. Y la tuya ? XD

saludos
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: Frodrig en 12 de Diciembre de 2002, 06:37:29 PM
                                Hola chicos, perdonad por no responder antes pero ayer por la noche todo mi equipo se ha ido a hacer gargaras (machacado esta el pobre) en lo relativo a disco duro y ahora estoy con un portatil que no es mio y que tengo que devolver de inmediato.

En primer lugar, con el codigo mostrado he pretendido que fuera didactico, pequeño y, sobre todo, limpio y facil de entender. Asi pues:

1/ Estoy con la mejora apuntada por ethernet acerca de la creacion de los nodos, su propuesta esta mucho mas optimizada y no aporta ninguna dificultad de comprension.

2/ Naturalmente que los assertos no estan en version release (a no ser que te curres tu propio assert y seas tu el que decidas cuando y cuando no estan), pero su utilidad esta mas orientada a lo que es el proceso de creacion de esta clase. En un proyecto real habra que tirar de otros mecanimos de localizacion de errores, como loggers, excepciones, etc. Lo importante de los assertos, ademas de permitir cazar errores, es que nos permiten comprender mucho mejor el codigo y reafirman la logica del mismo a medida que este se va leyendo, sobre todo cuando lo hace otra persona que no es uno de nosotros (los creadores del codigo).

3/El ordenador trabajara mejor con datos de 32 bits, pero esa implementacion estaria mas orientada a crear codigo optimizado, que no es el caso de este codigo, yo he pretendido utilizando unsigned short ceñirme a la realidad; es practicamente imposible que se cubran los 16 bits con nodos en memoria, si esto fuera asi... el volumen de datos distaria de ser manejable, con lo que se contribuye a comprender el funcionamiento de la clase. De hecho, estuve tentado de poner un typedef con un tipo predefinido para utilizar con valor estandar y asi facilitar el cambio.

4/ Uso referencias con const, porque en la vida real, dentro de un motor, lo mas normal sera que se trabaje con variables y recoger estas mediante referencias es mucho mas rapido y seguro que hacerlo utilizando punteros.

5/ No utilice un vector o un array como apunte metaxas por la misma razon que he apuntado mas arriba en cuanto al volumen de nodos manejados, seria un malgasto de memoria anticiparnos a la totalidad de nodos que realmente vamos a utilizar, con el sistema actual estamos preparados para responder al peor de los casos (cuando el numero de nodos sea maximo) pero nunca iremos "mas alla". No se si me explico.
Una excelente forma de aplicar tu idea seria solicitar por template el tamaño maximo del pool y entonces crear ese vector utilizando reserve para el peor y maximo de los casos (el tamaño pasado por template). Como veis, la clase esta muy ligada a la forma en la que quereis implementar la idea en vuestros proyectos.

Saludos.                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ElQueSeRompeElOrto en 13 de Diciembre de 2002, 06:46:41 AM
                                "ethernet" escribio:

Un unsigned short en mi maquina son 16 bits ... y en mi maquina un unsigned short & y un unsigned short * son 32 bits. y mi maquina trabaja mejor con datos de 32 bits. Y la tuya ? XD


Mira ethernet tu maquina deve ser cualquiercosa menos una PC compatible , si es que estamos hablando de pasar argumentos a funciones , esto se realiza algo asi:
En C: -------------------
void vMyFuncionBebe( int Argumento1 ,unsigned short Argumento2 ,int * pArgumento3 );

Compilado seria:(en el momento de la llamada) ------------------------------
Push [DireccionDeRetorno]
push Argumento1
push Argumento2
push Argumento3

Para que no te quede claro que ,"push" si estas en un procesador de 32 bits ,te va a meter en la pila 32 bits ya que como veras no se puede especificar cuantos bytes o bits se meteran ,por lo que si en memoria tu unsigned short ocupa 2 Bytes , irremediablemente se lo metera en la pila como 4 bytes.

Estoy Casi Seguro que es asi ...bue sino alguien corrija un saludo.

                               
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: synchrnzr en 13 de Diciembre de 2002, 09:26:11 AM
                                Mmmm... yo no estaría tan seguro de eso que dices

Sync                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 13 de Diciembre de 2002, 10:53:32 AM
Ya dudo q no se pueda hacer push word ax por ejemplo, aunque para mas detalles y ver si c *siempre* pone 4 bytes (en x86) podemos mirar las macros va_* para funciones con numero de parametros variables.
saludos
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: Loover en 13 de Diciembre de 2002, 11:03:28 AM
                                Creo que el que rompe el culete tiene razón. Los registros (en todos los ordenadores basados en el 80/86 son de 32 bits. Si se apila una variable de 16 bits dejará la parte alta del registro a 0, pero no por eso ocupara 16 bits. Vamos, eso tengo entendido. La verdad es que no tengo muy fresca la asignatura de computadores...

Mirar la parte de en esta dirección:
http://www.ele.uva.es/~imartin/noticias/pe...cos/compilador/                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: synchrnzr en 13 de Diciembre de 2002, 11:25:28 AM
                                Pues permíteme que se la quite :X9:

Haced la prueba del algodón:

PUSH AX
PUSH EAX

y comprobad el valor de ESP a cada paso. Vereis que en el primer PUSH, ESP se decrementa en 2 y en el segundo en 4 ;)

Lo que sí que no se puede hacer es un PUSH de un registro de 8 bits.

Sync

PD: Hace tiempecillo que no programo en ASM que no sea el de la GameBoy Advance, pero antes había programado mucho mucho mucho... y aun os puedo sorprender :D                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: fiero en 13 de Diciembre de 2002, 11:37:27 AM
                                Elqueserompeelorto tiene razón. Aunque se puede poner en pila 16 bits, por defecto, VC mete siempre 32:

mov ax,variable_short
push eax

Es más, cuando dentro de una función se definen parámetros de la siguiente manera:

void funcion(void)
{
    short f,g;

en modo debug se reservan 2 bytes por variable. Sin embargo en modo release (imagino que por cuestiones de optimización para código más rápido), se reservan 4 bytes por variable.

Por cierto, en cuanto al cotw en cuestión muy buena idea.

un saludo

PD: ups, se ha metido sync en medio XD                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: synchrnzr en 13 de Diciembre de 2002, 11:48:28 AM
                                Sí, soy como el jueves (el día, no la revista... bueno... no sé...  :D )

Es probable que el acceder a direcciones alineadas a 32 bits sea más rápido (aunque también tengo mis dudas ^_^) De todas formas si el tema es si se puede acceder a elementos en la pila de 16/32 bits, se puede desde el 386 hasta el Pentium III (y/o compatibles  :P ) Lo que hagan o dejen de hacer los compiladores ya es otra cosa (especialmente el VC++, que es software de Microsoft y hay que tratarlo como tal  :X9: )

Sync                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 13 de Diciembre de 2002, 11:49:25 AM
aja, o sea short *p = new short [1000]; me ocupa 4000 bytes en vez de 2000 ? (me refiero en un x86) .Eso si q optimiza memoria.
Otra cosa es q trabaje con los short como con los int debido a la arquitectura del micro.


saludos
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: fiero en 13 de Diciembre de 2002, 05:27:28 PM
                                ethernet todos llevamos razón, lo de usar 32 bits en short solo vale en el paso de parámetros por pila y en la creación de variables en la pila. Los vectores o asignacion dinámica de vectores es otro cantar... :ojo:

un saludo                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: Pogacha en 13 de Diciembre de 2002, 06:38:27 PM
                                Pido permiso señores pero la custion son las directivas de enpaquetamiento y alineacion del compilador, pack byte, pack word, align .8, las cuales cambia en cada compilador.
Espero que este dato les sirva.                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 13 de Diciembre de 2002, 08:25:28 PM
Yo por mucho q cambie el factor de empaquetamiento el sizeof sigue siendo el mismo para datos basicos como char short int etc, NO PARA STRUCTS, REPITO, NO PARA STRUCTS (q nos conocemos xD).

En efecto se comprueba q aunque sea un short mete 4 bytes en la pila lo cual   me da la razon a mi q es mejor usar un int o unsigned int q un short para ese caso concreto puesto q puedes ampliar el rango de uso sin problemas.

A lo q me referia en mi primer post es q me parece una tonteria usar short int & puesto q no tiene ningun sentido pasar sizeof(tamaño_bus_direcciones_maquina/8) pudiendo pasar sizeof(short int). Otras cosa muy diferente es q el compilador meta siempre 4 bytes, q puede q ciertos compiladores no lo hagan.

Por lo menos hemos dado vida al cotw !! XDDD

Nota; todas las pruebas las he hecho en vc++6.0.

saludos
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: Vicente en 13 de Diciembre de 2002, 09:42:14 PM
                                Hola,

Citar"ethernet" escribio:
En C: -------------------
void vMyFuncionBebe( int Argumento1 ,unsigned short Argumento2 ,int * pArgumento3 );

Compilado seria:(en el momento de la llamada) ------------------------------
Push [DireccionDeRetorno]
push Argumento1
push Argumento2
push Argumento3

  me parece que los push de los argumentos van al revés... Primero el 3, luego el 2, luego el 1.

  Un saludo,

Vicente                                
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: ethernet en 13 de Diciembre de 2002, 10:39:08 PM
Va, eso depende mucho de muchas cosas, en vc++ por ejemplo hay una opcion para q pase los argumentos por registros si puede.
saludos
Título: Reciclado de memoria - Fernando Rodríguez
Publicado por: synchrnzr en 15 de Diciembre de 2002, 01:30:26 PM
                                Po zi, no todos los compiladores lo hacen. Puedes probar con cualquier C de Borland, por ejemplo (te lo he buscado especialmente pa ti, ethernet XDD) Yo lo que me pregunto es si verdaderamente se ahorra tiempo metiendo registros de 32 bits en vez de 16 en la pila. Según Intel, el número de ciclos de CPU consumidos en un PUSH es el mismo para registros de 32 y de 16 bits, lo único que podría influir pues serían cuestiones de caché o de pipelining pero ahí ya no entro... :-?

Sync