From f2c6c069714c203c1450701c459c761f7b85880f Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 10 Jun 2009 17:54:07 -0300 Subject: [PATCH] =?utf8?q?Terminar=20descripci=C3=B3n=20de=20la=20fase=20d?= =?utf8?q?e=20barrido?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- source/dgc.rst | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/source/dgc.rst b/source/dgc.rst index dc32223..f7e42ea 100644 --- a/source/dgc.rst +++ b/source/dgc.rst @@ -494,7 +494,79 @@ dividirse en dos pasos básicos:: sweep() rebuild_free_lists() -El barrido se realiza con una pasada por sobre todo el heap +El barrido se realiza con una pasada por sobre todo el *heap* de la siguiente +manera:: + + function sweep() is + foreach pool in heap + foreach page in pool + if page.block_size <= PAGE // saltea FREE y CONTINUATION + foreach block in page + if block.mark is false + if block.final is true + finalize(block) + block.free = true + block.final = false + block.noscan = false + if page.block_size is PAGE // objeto grande + free_big_object(pool, page) + +Como se observa, se recorre todo el *heap* en busca de bloques y páginas +libres. Los bloques libres son marcados con el atributo ``free`` y las páginas +libres son marcadas con el tamaño de bloque simbólico ``FREE``. Para los +objetos grandes se marcan todas las páginas que utilizaban como ``FREE``:: + + function free_big_object(pool, page) is + pool_end = cast(byte*) pool.pages + (PAGE_SIZE * pool.number_of_pages) + do + page = cast(byte*) page + PAGE_SIZE + page.block_size = FREE + while page.block_size is CONTINUATION and page < pool_end + +Además, los bloques que tienen en atributo ``final`` son finalizados llamando +a la función ``finalize()``. Esta función es un servicio que provee la +biblioteca *runtime* y en última instancia llama al destructor del objeto +almacenado en el bloque a liberar. + +Una vez marcados todos los bloques y páginas como libre, se procede +a reconstruir las listas de libres. En el proceso buscan las páginas que +tengan todos los bloques libres para marcar la página completa como libre (de +manera que pueda utilizarse para albergar otro tamaño de bloque u objetos +grandes de ser necesario):: + + function rebuild_free_lists() is + foreach free_list in heap + free_list.clear() + foreach pool in heap + foreach page in pool + if page.block_size < PAGE // objetos pequeños + if is_page_free(page) + page.block_size = FREE + else + foreach block in page + if block.free is true + free_lists[page.block_size].link(block) + +Esta reorganización de listas libres además mejoran la localidad de +referencia y previenen la fragmentación. La localidad de referencia se ve +mojorada debido a que asignaciones de memoria proximas en el tiempo serán +también próximas en espacio porque pertenecerán a la misma página (al menos si +las asignaciones son todas del mismo tamaño). La fragmentación se minimiza por +el mismo efecto, primero se asignarán todos los bloques de la misma página. + +A continuación se presenta la implementación de una de las funciones +suplementarias de la fase de barrido:: + + function is_page_free(page) is + foreach block in page + if block.free is false + return false + return true + +Las demás funciones suplementarias pertenecen a la manipulación de listas +libres que no son más que operaciones sobre una lista simplemente enlazada. En +la sección :ref:`dgc_impl` se verá con más detalles como las implementa el +recolector actual. -- 2.43.0