]> git.llucax.com Git - z.facultad/75.00/informe.git/commitdiff
Agregar explicación del problema con ciclos de RC
authorLeandro Lucarella <llucax@gmail.com>
Tue, 26 May 2009 00:13:54 +0000 (21:13 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 31 May 2009 00:30:18 +0000 (21:30 -0300)
También actualizar el ejemplo para agregar un ciclo en la
estructura de datos.

source/gc.rst
source/referencias.rst

index 5d21433d5264ff2d2583a5b49c6ec5adba11cb2b..4f9f91a82bab24e1629a535638e1ca2d05b24221 100644 (file)
@@ -803,11 +803,43 @@ siguientes (acompañadas de una implementación básica)::
       *ref = cell
 
 
       *ref = cell
 
 
+
 .. _ref_gc_rc_cycles:
 
 Ciclos
 ^^^^^^
 
 .. _ref_gc_rc_cycles:
 
 Ciclos
 ^^^^^^
 
+El conteo de referencias tiene, sin embargo, un problema fundamental:
+**falla con estructuras cíclicas**. Esto significa que siempre que haya un
+ciclo en el grafo de conectividad, hay una pérdida de memoria potencial en
+el programa. Un ciclo es un camino :math:`\underset{v \to v}{C}`, es decir,
+el *vértice inicial* es el mismo que el *vértice final*.
+
+Cuando esto sucede, las celdas que participan del ciclo tienen siempre su
+contador mayor que 0, sin embargo puede no haber ningún elemento del *root
+set* que apunte a una celda dentro del ciclo, por lo tanto el ciclo es
+*basura* (al igual que cualquier otra celda que sea referenciada por el
+ciclo pero que no tenga otras referencias externas) y sin embargo los
+contadores no son 0. Los ciclos, por lo tanto, *rompen* la invariante del
+conteo de referencia.
+
+Hay formas de solucionar esto, pero siempre recaen en un esquema que va por
+fuera del conteo de referencias puro. En general los métodos para
+solucionar esto son variados y van desde realizar un marcado del subgrafo
+para detectar nodos hasta tener otro recolector completo de *emergencia*,
+pasando por tratar los ciclos como un todo contar las referencias al ciclo
+completo en vez de a cada celda en particular.
+
+Incluso con este problema, el conteo de referencia sin ningún tipo de
+solución en cuanto a la detección y recolección de ciclos fue utilizado en
+muchos lenguajes de programación sin que su necesidad sea tan evidente. Por
+ejemplo Python_ agregó recolección de ciclos en la versión 2.0 [NAS00]_
+(liberada en octubre de 2000) y PHP_ recién agrega detección de ciclos en
+la versión 5.3 (todavía no liberada al momento de escribir este documento)
+[PHP081]_.
+
+
+
 .. _ref_gc_rc_example:
 
 Ejemplo
 .. _ref_gc_rc_example:
 
 Ejemplo
@@ -857,7 +889,7 @@ son todas parte del *live set*.
 
             h1 [ label = "h1\n1|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
 
             h1 [ label = "h1\n1|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
-            h3 [ label = "h3\n2|<l> l|<r> r" ];
+            h3 [ label = "h3\n3|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -870,6 +902,7 @@ son todas parte del *live set*.
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -904,7 +937,7 @@ son todas parte del *live set*.
 
             h1 [ label = "h1\n1|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
 
             h1 [ label = "h1\n1|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
-            h3 [ label = "h3\n2|<l> l|<r> r" ];
+            h3 [ label = "h3\n3|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -917,6 +950,7 @@ son todas parte del *live set*.
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -956,7 +990,7 @@ son todas parte del *live set*.
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n2|<l> l|<r> r" ];
-            h3 [ label = "h3\n2|<l> l|<r> r" ];
+            h3 [ label = "h3\n3|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -969,6 +1003,7 @@ son todas parte del *live set*.
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1014,7 +1049,7 @@ son todas parte del *live set*.
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n2|<l> l|<r> r" ];
+            h3 [ label = "h3\n3|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1027,6 +1062,7 @@ son todas parte del *live set*.
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1065,7 +1101,7 @@ son todas parte del *live set*.
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l|<r> r" ];
+            h3 [ label = "h3\n2|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1078,6 +1114,7 @@ son todas parte del *live set*.
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
             h2:r -> h5;
             h3:l -> h2;
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1129,7 +1166,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l\n*|<r> r" ];
+            h3 [ label = "h3\n2|<l> l\n*|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1143,6 +1180,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h2;
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
             h3:l -> h2;
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1181,7 +1219,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l\n*|<r> r" ];
+            h3 [ label = "h3\n2|<l> l\n*|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1195,6 +1233,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h2 [ style = bold, color = black ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
             h3:l -> h2 [ style = bold, color = black ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1234,7 +1273,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l\n*|<r> r" ];
+            h3 [ label = "h3\n2|<l> l\n*|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n1|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1248,6 +1287,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h2 [ style = invis ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
             h3:l -> h2 [ style = invis ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1293,7 +1333,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l\n*|<r> r" ];
+            h3 [ label = "h3\n2|<l> l\n*|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n2|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1307,6 +1347,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h2 [ style = invis ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
             h3:l -> h2 [ style = invis ];
             h3:l -> h5 [ style = dotted, color = black ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1345,7 +1386,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
 
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n1|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l\n*|<r> r" ];
+            h3 [ label = "h3\n2|<l> l\n*|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1359,6 +1400,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h5 [ style = bold, color = black ];
             h3:l -> h2 [ style = invis ];
             h3:r -> h6;
             h3:l -> h5 [ style = bold, color = black ];
             h3:l -> h2 [ style = invis ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1399,7 +1441,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n0|<l> l|<r> r" ];
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h1 [ label = "h1\n0|<l> l|<r> r" ];
             h2 [ label = "h2\n0|<l> l|<r> r" ];
-            h3 [ label = "h3\n1|<l> l|<r> r" ];
+            h3 [ label = "h3\n2|<l> l|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
             h4 [ label = "h4\n0|<l> l|<r> r" ];
             h5 [ label = "h5\n1|<l> l|<r> r" ];
             h6 [ label = "h6\n1|<l> l|<r> r" ];
@@ -1413,6 +1455,7 @@ conduce al decremento del contador de ``h2`` y ``h3`` que permanecen en el
             h3:l -> h5;
             h3:l -> h2 [ style = invis ];
             h3:r -> h6;
             h3:l -> h5;
             h3:l -> h2 [ style = invis ];
             h3:r -> h6;
+            h6:r -> h3:r;
 
          }
 
 
          }
 
@@ -1430,6 +1473,135 @@ referencia ``h3.l`` para que apunte a ``h5`` (ver figura
 :vref:`fig:gc-rc-up-2`).
 
 
 :vref:`fig:gc-rc-up-2`).
 
 
+.. fig:: fig:gc-rc-cycle
+   :padding: 0.5
+
+   Eliminación de la referencia ``r1`` :math:`\to` ``h3`` (pérdida de
+   memoria debido a un ciclo).
+
+   .. subfig::
+
+      El ejecutarse ``update(r1, null)`` se visita la celda ``h3``.
+
+      .. digraph:: g4_6
+
+         margin = 0;
+         ratio  = fill;
+         size   = "1.9,2.6";
+         edge [ color = gray40 ];
+         node [
+            shape     = record,
+            width     = 0,
+            height    = 0,
+            style     = filled,
+            fillcolor = gray25,
+            fontcolor = white
+         ];
+
+         subgraph cluster_all {
+
+            root [
+               label     = "root\nset|<r0> r0|<r1> r1\n*",
+               style     = filled,
+               fillcolor = gray96,
+               fontcolor = black,
+            ];
+
+            subgraph marked {
+               node [ fillcolor = white, fontcolor = black ];
+               h1; h2; h4;
+            };
+
+            h1 [ label = "h1\n0|<l> l|<r> r" ];
+            h1 [ label = "h1\n0|<l> l|<r> r" ];
+            h2 [ label = "h2\n0|<l> l|<r> r" ];
+            h3 [ label = "h3\n2|<l> l|<r> r" ];
+            h4 [ label = "h4\n0|<l> l|<r> r" ];
+            h5 [ label = "h5\n1|<l> l|<r> r" ];
+            h6 [ label = "h6\n1|<l> l|<r> r" ];
+
+            root:r0 -> h1 [ style = invis ];
+            h1:l -> h2 [ style = invis ];
+            h1:r -> h3 [ style = invis ];
+            root:r1 -> h3 [ style = bold, color = black ];
+            h2:l -> h4 [ style = invis ];
+            h2:r -> h5 [ style = invis ];
+            h3:l -> h5;
+            h3:l -> h2 [ style = invis ];
+            h3:r -> h6;
+            h6:r -> h3:r;
+
+         }
+
+   .. subfig::
+
+      Se decrementa el contador de ``h3`` pero sigue siendo mayor que 0 por
+      el ciclo.
+
+      .. digraph:: g5_2
+
+         margin = 0;
+         ratio  = fill;
+         size   = "1.9,2.6";
+         edge [ color = gray40 ];
+         node [
+            shape     = record,
+            width     = 0,
+            height    = 0,
+            style     = filled,
+            fillcolor = gray25,
+            fontcolor = white
+         ];
+
+         subgraph cluster_all {
+
+            root [
+               label     = "root\nset|<r0> r0|<r1> r1\n*",
+               style     = filled,
+               fillcolor = gray96,
+               fontcolor = black,
+            ];
+
+            subgraph marked {
+               node [ fillcolor = white, fontcolor = black ];
+               h1; h2; h4;
+            };
+
+            h1 [ label = "h1\n0|<l> l|<r> r" ];
+            h1 [ label = "h1\n0|<l> l|<r> r" ];
+            h2 [ label = "h2\n0|<l> l|<r> r" ];
+            h3 [ label = "h3\n1|<l> l|<r> r" ];
+            h4 [ label = "h4\n0|<l> l|<r> r" ];
+            h5 [ label = "h5\n1|<l> l|<r> r" ];
+            h6 [ label = "h6\n1|<l> l|<r> r" ];
+
+            root:r0 -> h1 [ style = invis ];
+            h1:l -> h2 [ style = invis ];
+            h1:r -> h3 [ style = invis ];
+            root:r1 -> h3 [ style = invis ];
+            h2:l -> h4 [ style = invis ];
+            h2:r -> h5 [ style = invis ];
+            h3:l -> h5;
+            h3:l -> h2 [ style = invis ];
+            h3:r -> h6;
+            h6:r -> h3:r;
+
+         }
+
+
+Finalmente se presenta lo que sucede cuando se elimina la última referencia
+a un ciclo (en este caso un ciclo simple de 2 celdas: ``h3`` y ``h6``). Se
+elimina la única referencia externa al ciclo (``r1``), por lo que se visita
+la celda ``h3`` decrementando su contador de referencias, pero éste
+continúa siendo mayor que 0 porque la celda ``h6`` (parte del ciclo) la
+referencia. Por lo tanto el ciclo, y todas las celdas a las que apunta que
+no tienen otras referencias externas y por lo tanto deberían ser *basura*
+también (``h5``), no pueden ser recicladas y su memoria es perdida (ver
+figura :vref:`fig:gc-rc-cycle`).
+
+
+
+
 Marcado y barrido
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Marcado y barrido
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index 4da9e82f309ebe71122d3d1f16502eea5a931474..220bfade1bc4b3a155346dc51edc41ff4495a898 100644 (file)
    ACM SIGPLAN conference on Programming language design and
    implementation. 2006. ISBN 1-59593-320-4.
 
    ACM SIGPLAN conference on Programming language design and
    implementation. 2006. ISBN 1-59593-320-4.
 
+.. [NAS00] Neil Schemenauer. `Garbage Collection for Python`__. 2000.
+__ http://arctrix.com/nas/python/gc/
+
+.. [PHP081] PHP Team. `PHP 5.3 alpha1 released!`__. PHP news archive.
+   2008-08-01.
+__ http://www.php.net/archive/2008.php#id2008-08-01-1
+
 
 .. include:: links.rst
 
 
 .. include:: links.rst