Optimización del rederizador (Desafio - duda)

Andaba armando un sencillo (por el momento) motor, cuando me surgió la duda de cuál forma puede ser más optimizada al acceder a memoria. Entre las dos formas que contiene la misma función.

void drawEntities(entitymanager* man)
{
// Forma uno
	for(uint i=0; i<man->entities->size; ++i)
		drawEntity(Vector_getValue(man->entities,i));
// Forma dos
	entity* ents = man->entities->data;
	for(uint i=0; i<man->entities->size; i+=sizeof(entity))
		drawEntity(ents+i);
}

“man” es el gestor de entidades, man→entities guarda un vector dinámico dónde se guarda una entidad a lado de otra toda junta en memoria.

Por lo que, la función Vector_getValue me devuelve una entidad en base al indice que le pase, mientras que la otra forma, desreferencia el puntero, para guardar la dirección en una variable local, que apunta a la primer identidad, si le sumo el tamaño (en bytes) pasa a apuntar a la siguiente entidad.

1 me gusta

Diria que la forma la Forma 2 es la mejor, trata de ser mas directa; por mi intuición lo que hace “Vector_getValue” es tener un array con todo los Entity que tienes o tener un for que se pare justo en el indice que necesitas, por ese lado prefiero más la Forma 2.

Por lo otro lado no sé si sea un problema pero pongamos un ejemplo: que el tipo entity sea de 64 bytes, cada vez que quiera sumarle el tamaño de entity a i va a ir en 64 en 64, debes de 1 en 1. No sé si ya habias pensado en ello o se te paso, es un pequeño problema el que veo ahí.

Hola,

Supongo que estás usando C ó C++. Yo te diría de probar una herramienta de “memory profiling” para ver cuál de ellas es más optimizada.

Un saludo

No especifique,lo siento, estoy usando estrictamente C, no C++

Yo elegí la forma 2, con una pequeña modificación. Con el “man++” el compilador suma lo que haya falta para llegar al siguiente elemento.

void drawEntities(entitymanager* man)
{
//Forma 1
	//for(uint i=0; i<man->entities->size; ++i)
	//	drawEntity(Vector_getValue(man->entities,i));
//Forma 2
	entity* ents = man->entities->data;
	for(uint i=0; i<man->entities->size; ++i){
		drawEntity(ents);
		ents++;
	}
}

Las funciones de “Vector_*” provienen de una implementación casera del vector de c++ homologo.

La función:

#include <vector.h>




Vector *Vector_init(size_t elem_size) {
	Vector *vector = (Vector*)malloc(sizeof(Vector));
	vector->data = malloc(1*elem_size);
	vector->size = 0;
	vector->capacity = 1;
	vector->elem_size = elem_size;
	return vector;
}


void Vector_pushback(Vector *vector, void *element) {
	if (vector->size == vector->capacity) {
		Vector_newsize(vector, vector->capacity * 2);
	}
	memcpy((char*)vector->data+(vector->size*vector->elem_size),
			element,vector->elem_size);
	vector->size++;
}

void *Vector_getValue(Vector *vector, int index) {
	if (index < 0 || index >= vector->size) {
        return NULL; // Retorna NULL si el índice está fuera de límites
    }
	return (char*)vector->data+(index*vector->elem_size);
}

void Vector_newsize(Vector *vector, int newReserve) {
	vector->data = realloc(vector->data, newReserve*vector->elem_size);
	vector->capacity = newReserve;
}

void Vector_destroy(Vector *vector) {
	free(vector->data);
	free(vector);
}