Abr 27
GNU/Linux Memcache es un sistema para almacenamiento de objetos en memoria que pueden ser solicitados por varios procesos, incluso en distintas máquinas y que actúa como caché para acelerar estas peticiones. Memcache ha sido diseñado de manera genérica aunque su mayor utilidad y para la que fue desarrollado inicialmente es para reducir la carga en sitios web debido a las solicitudes a base de datos que en muchos casos son innecesarias.

    Memcache ha sido desarrollado por Danga Interactive para livejournal en primera instancia pero luego liberado bajo licencia BSD. Hoy en día es empleado por muchos otros sitios webs debido a su gran utilidad, entre ellos: Livejournal, Slashdot, Wikipedia, SourceForge, FotoLog y un largo etc.

    El funcionamiento de memcache es de concepción muy sencilla. En lugar de acceder a la base de datos para solicitar determinada información primero se accede a memcached (el servidor de memcache) a través de tcp/ip (así se puede acceder a servidores memcache en máquinas remotas o en local). Si este tiene la información la devuelve y si no debemos hacer la petición a la base de datos e introducir los datos en memcached para que puedan ser accedidos directamente la próxima vez que los necesitemos. Además cada dato introducido en memcached tiene un tiempo de expiración, tras pasar este tiempo almacenado en el servidor este se considera descartable y se borra del servidor, dejando espacio para otros objetos.

    De una manera muy sencilla también es posible emplear varios servidores memcache, creando una cache distribuida todavía más eficiente o incluso utilizar varios niveles de caché entre máquinas locales y/o remotas.

    Memcaché está basado en libevent una librería de notificación de eventos asíncrona que permite ejecutar callbacks cuando un determinado evento es disparado (además de eventos puede reaccionar a señales o a intervalos de tiempo específicos, más adelante quizás le dedique un post a esta librería).

    Para instalar memcached en nuestro servidor debemos bajarnos las fuentes del sitio de Danga Interactive. La compilación e instalación no debería ser complicada. También es posible descargar fuentes y binario con apt-get o con el gestor de paquetes que tengamos instalado (absténganse windowzers)

apt-get install memcached

 El servidor memcached tiene unas pocas opciones en la línea de argumentos, estos son:

-d (implicito)
-v (verbose)
-vv (más verbose)
-m (memoría en megas disponible para el demonio)
-p (puerto a la escucha, por defecto 11211
-u (usuario bajo el que se ejecuta el servidor)
-l (IP de la que se espera conexiónes, es la única medida de seguridad del servidor, el valor por defecto es escuchar comunicaciones desde cualquier ip lo cual es completamente inseguro si no se está detrás de un firewall)
-c (número máximo de conexiones simultaneas)
-k (activa bloqueos)
-M (devuelve error cuando la memoria se agota)
-r (limita los core dump)

 El demonio toma toda la memoria especificada por el parámetro -m al principio y cuando no puede alamacenar más datos desecha aquellos accedidos menos recientemente (si no se le pasa el parámetro -M)

Ejemplo:
# memcached -d -m 2048 -l 10.0.0.40 -p 11211

El comando anterior iniciará el servidor usando 2GB de memoria y escuchando conexiones desde la ip 10.0.0.40 al puerto 11211. Recordemos que es posible iniciar más servidores memcache en la misma máquina.

Existen disponibles diversas APIs para conectarse al servidor escritas en diferentes lenguajes: PHP, Python, PERL, Ruby, Java, C, C#

Ejemplo en php de conexión con el servidor memcached:


$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");

$version = $memcache->getVersion();
echo "Server's version: ".$version."
\n";

$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;

$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server");
echo "Store data in the cache (data will expire in 10 seconds)
\n";

$get_result = $memcache->get('key');
echo "Data from the cache:
\n";

var_dump($get_result);

?>

Publicado por Abraham Covelo

Abr 26
Ocio

Gato bebiendo leche de vaca, literalmente

Publicado por Abraham Covelo

Abr 26
Programación La función alloca reserva espacio en la pila de la función que lo llama, devolviendo un puntero ha este espacio reservado. Este espacio temporal es automáticamente liberado cuando la función que llama a alloca retorna.

Esta es la firma o prototipo de la función:

void *alloca(size_t size);

Su declaración está en el archivo de cabecera alloca.h. El parámetro que se le pasa es el número de bytes que se desean reservar. Alloca además devuelve un puntero nulo cuando no tiene éxito al reservar memoria.

Alloca presenta una serie de ventajas con respecto a malloc a la hora de reservar memoria. Alloca no produce segmentación en los bloques de memoria reservados, ya que el espacio se reserva en la pila. Alloca apenas malgasta espacio y es bastante rápido. Cuando la función que llama a alloca es abandonada la memoria es liberada evitando posibles memory leaks. Esto también ocurre en caso de error en la función, la memoria es liberada de inmediato.

Ejemplo de función que emplea alloca:

int open2(char *str1, char *str2, int flags, int mode)
{
char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1);
stpcpy (stpcpy (name, str1), str2);
return open(name, flags, mode);
}

Para tener un código similar empleando sólo malloc y free debemos escribir:

int open2 (char *str1, char *str2, int flags, int mode)
{
char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1);
int desc;
if (name == 0)
fatal ("virtual memory exceeded");
stpcpy (stpcpy (name, str1), str2);
desc = open (name, flags, mode);
free (name);
return desc;
}

Alloca, sin embargo, también tiene algunas desventajas:

Si intentas reservas más memoria de la que la máquina puede reservar no obtendrás un mensaje de error claro. En su lugar tendrás una señal fatal como las obtenidas en un recursion infinita; probablemente una violación de segmento.

Algunos sistemas no-GNU no tienen soporte para alloca, convirtiendo a alloca en menos portable. Sin embargo hay algunas implementaciones en C para solventar estas deficiencias en estos sistemas.

Sigue este link para saber más de reserva de memoria

Publicado por Abraham Covelo

Abr 20
Programación Obstack es otros de los medios que emplea la librería C de GNU para la asignación dinámica de memoria. Obstack es una pila de objetos (datos) que puede crecer dinámicamente. Es posible crear cualquier número de obstacks para, en cada uno, ir almacenando diferentes conjuntos de datos. En cada obstack el último objeto en entrar es el primero en salir.

    Obstack es pues otro de los métodos de la librería glibc para la reserva dinámica de memoria.

    A parte de esta limitación en el orden de almacenaje obstack es capaz de contener cualquier número de objetos de cualquier tamaño. Obstack está implementado con macros, de manera que la asignación de espacio es muy rápida si los objetos son pequeños. La única sobrecarga por objeto es el relleno necesario para colocar un objeto en unos límites adecuados.

    Para la creación de un obstack debes primero incluir el archivo de cabecera obstack.h. En este archivo se declara la estructura obstack de tamaño fijo y que registra el estado del obstack y como encontrar el espacio donde los objetos están localizados. No se debe intentar acceder al contenido de esta estructura directamente sino que se debe utilizar las funciones diseñadas especificamente para obstack.

    Obstack puede ser tratado como cualquier otro tipo de objetos, puedes crear obstack dinamicamente o crear obstacks que contengan a su vez otros obstacks.

    Todas las funciones que trabajan con obstacks necesitan que se les especifique el obstack a usar. Se hace esto a través de un puntero a la estructura de tipo struct obstack* .

    Los objetos dentro del obstack son empaquetados en bloques llamados chunks. La estructura obstack apunta a una cadena de chunks actualmente en uso.

    La librería obstack obtiene un nuevo chunk cada vez que debe insertar un nuevo objeto que no cabe en un chunk anterior. La librería administra automáticamente estos chunks de manera que no hay que prestarles demasiada atención, pero hay que propocionar una función a la librería obstack para que esta se haga con un nuevo chunk. Generalmente se debe proporcionar un a función que emplea malloc directa o indirectamente. También se debe proporcionar una función que libere el chunk (free).

Ejemplo:

#include //declara todas las variables, funciones y macros necesarios para obstack

//Estas dos macros definen los métodos para la generación de memoria dinámica y su liberación
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free

...

//función que se llamara en el caso de error en la reserva dinámica de memoria
void my_obstack_alloc_failed(void)
{
...
}

...

//Declaramos nuestra estructura obstack
static struct obstack myobstack;

...

//La inicializamos
obstack_init(&myobstack);

...

//Declaramos que función será llamada en caso de error al reservar memoria dinámica
obstack_alloc_failed_handler = &my_obstack_alloc_failed;

//Grabamos en nuestro obstack la cadena "hola mundo"
obstack_alloc("hola mundo",11);

Para almacenar un bloque con un contendio específico utilizamos la función obstack_copy

void* obstack_copy (struct obstack* obstack-ptr, void* address, int size)

La función obstrack_copy0 además agrega un caracter nulo (ascii 0) al final.

void* obstack_copy0 (struct obstack* obstack-ptr, void* address, int size)

En el último argumento size no debemos tener en cuenta este carácter nulo extra. Ejemplo:

char*
obstack_savestring (char* addr, int size)
{
return obstack_copy0 (&myobstack, addr, size);
}

    Para liberar objetos en el obstack se emplea obstack_free

void obstack_free (struct obstack* obstack-ptr, void* object)

    Si objeto es un puntero nulo, todo lo almacenado en obstack será liberado. Cualquier otro valor debe ser un puntero a un objeto del obstack. Ese objeto será liberado y todos los que se encuentran a continuación de él.

    Observa que si object es un puntero nulo, el resultado será un obstack no inicializado. Para liberar todos los objetos del obstack pero dejando el obstack válido para agregar nuevos objetos tenemos que pasarle como object el primer objeto almacenado.

    Recuerda que obstack está agrupado en chunks. Si se liberan todos los objetos de un chunk, obstack automaticamente liberará este chunk para que pueda ser utilizado como recurso para otros elementos del programa.

    Recordemos que los interfaces definidos en obstack pueden estar definidos como funciones o como macros. Ejemplo:

char* x;
void* (* funcp) ();
/* Use the macro. */
x = (char* ) obstack_alloc (obptr, size);
/* Call the function. */
x = (char* ) (obstack_alloc) (obptr, size);
/* Take the address of the function. */
funcp = obstack_alloc;

    Si empleas otro compilador que no sea el de GNU debes tener esto en cuenta.

Para saber más:


GNU C Library Obstacks


Publicado por Abraham Covelo

(Página 1 de 4, en total 16 entradas)