]> git.llucax.com Git - z.facultad/75.00/informe.git/blobdiff - source/solucion.rst
Mejorar estilo de página de resumen/agradecimientos
[z.facultad/75.00/informe.git] / source / solucion.rst
index 32a94bd1fab2ab9682f7e2617797f8910a656666..074278a916769230f31f9326d6071b8c6687758b 100644 (file)
@@ -1,6 +1,6 @@
 
 .. Acá va lo que decidí hacer en base al análisis anterior y sus razones.
-   ESTADO: EMPEZADO
+   ESTADO: TERMINADO
 
 
 .. _solucion:
@@ -8,13 +8,13 @@
 Solución adoptada
 ============================================================================
 
-Como hemos visto en :ref:`dgc_bad`, la mejora del recolector de basura puede
-ser abordada desde múltiples flancos. Por lo tanto, para reducir la cantidad
-de posibilidades hay que tener en cuenta uno de los principales objetivos de
-este trabajo: encontrar una solución que tenga una buena probabilidad de ser
-adoptada por el lenguaje, o alguno de sus compiladores al menos. Para asegurar
-esto, la solución debe tener un alto grado de aceptación en la comunidad, lo
-que implica algunos puntos claves:
+Como hemos visto en :ref:`dgc`, la mejora del recolector de basura puede ser
+abordada desde múltiples flancos, con varias alternativas viables. Por lo
+tanto, para reducir la cantidad de posibilidades hay que tener en cuenta uno
+de los principales objetivos de este trabajo: encontrar una solución que tenga
+una buena probabilidad de ser adoptada por el lenguaje, o alguno de sus
+compiladores al menos. Para asegurar esto, la solución debe tener un alto
+grado de aceptación en la comunidad, lo que implica algunos puntos claves:
 
 * La eficiencia general de la solución no debe ser notablemente peor, en
   ningún aspecto, que la implementación actual.
@@ -38,6 +38,8 @@ se intenta abordar los demás problemas planteados siempre que sea posible
 hacerlo sin alejarse demasiado del objetivo principal.
 
 
+.. highlight:: d
+
 .. _sol_bench:
 
 Banco de pruebas
@@ -141,8 +143,8 @@ El código fuente del programa es el siguiente::
             indi[] = testPop1.individuals ~ testPop2.individuals;
          }
          version (everythingOk) {
-            indi[0..N1] = testPop1.individuals;
-            indi[N1..N2] = testPop2.individuals;
+            indi[0 .. N1] = testPop1.individuals;
+            indi[N1 .. N2] = testPop2.individuals;
          }
       }
       return 0;
@@ -279,8 +281,8 @@ Este programa trivial lee un archivo de texto y genera un arreglo de cadenas
 de texto resultantes de partir el texto en palabras. Fue escrito por Leonardo
 Maffi y también hallado__ en el grupo de noticias de D_. Su objetivo era
 mostrar lo ineficiente que puede ser concatenar datos a un mismo arreglo
-repetidas veces y ha desembocado en una pequeña `optimización`__ que sirvió
-para apalear el problema de forma razonablemente efectiva.
+repetidas veces y ha desembocado en una pequeña optimización que sirvió para
+paliar el problema de forma razonablemente efectiva [PAN09]_.
 
 El código es el siguiente::
 
@@ -302,7 +304,6 @@ El código es el siguiente::
    }
 
 __ http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=67673
-__ http://d.puremagic.com/issues/show_bug.cgi?id=1923
 
 
 ``rnddata``
@@ -563,6 +564,8 @@ ser útiles para encontrar problemas muy particulares, está es la que da una
 lectura más cercana a la realidad del uso de un recolector.
 
 
+.. highlight:: pcode
+
 .. _sol_mod:
 
 Modificaciones propuestas
@@ -799,7 +802,9 @@ Caché de ``Pool.findSize()``
 Se crea un caché de tamaño de bloque para el método ``findSize()`` de un
 *pool*. Esto acelera considerablemente las operaciones que necesitan pedir el
 tamaño de un bloque reiteradamente, por ejemplo, al añadir nuevos elementos
-a un arreglo dinámico.
+a un arreglo dinámico. En esencia es una extensión a una de las optimizaciones
+propuestas por Vladimir Panteleev [PAN09]_, que propone un caché global para
+todo el recolector en vez de uno por *pool*.
 
 Esta mejora tampoco afecta a la corrección del algoritmo, ya que nuevamente no
 afecta su comportamiento a nivel lógico, solo cambia detalles en la
@@ -882,7 +887,7 @@ Probablemente el caso más significativo, y por tanto el único que vale la pena
 mencionar, es la conversión de marcado iterativo a marcado recursivo y luego
 a un esquema híbrido. Como se describe en :ref:`dgc_bad`, el marcado iterativo
 tiene sus ventajas, pero tiene desventajas también. Al convertirlo a puramente
-recursivo, se impracticable por resultar en errores de desbordamiento de pila.
+recursivo, es impracticable por resultar en errores de desbordamiento de pila.
 
 Por lo tanto se prueba con un esquema híbrido, poniendo un límite a la
 recursividad, volviendo al algoritmo iterativo cuando se alcanza este límite.
@@ -930,10 +935,10 @@ puede ver, por ejemplo, el tiempo total de ejecución de Dil_ al generar la
 documentación completa del código de Tango_, según varía el valor de
 ``MAX_DEPTH``.
 
-.. fig:: fig:sol-mark-rec
+.. flt:: fig:sol-mark-rec
 
    Análisis de tiempo total de ejecución en función del valor de
-   ``MAX_DEPTH``.
+   ``MAX_DEPTH``
 
    Tiempo total de ejecución de Dil_ al generar la documentación completa del
    código de Tango_ en función del valor de ``MAX_DEPTH``. El rombo no
@@ -1083,18 +1088,14 @@ recolector.
 Marcado preciso
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-En paralelo con este trabajo, David Simcha comienza a explorar la posibilidad
-de agregar precisión parcial al recolector, generando información sobre la
-ubicación de los punteros para cada tipo [DBZ3463]_. Su trabajo se limita
-a una implementación a nivel biblioteca de usuario y sobre `D 2.0`_.
-Desafortunadamente su trabajo pasa desapercibido por un buen tiempo.
+Para agregar el soporte de marcado preciso se aprovecha el trabajo realizado
+por Vincent Lang (ver :ref:`dgc_via_art`) [DBZ3463]_, dado que se basa en `D
+1.0`_ y Tango_, al igual que este trabajo. Dado el objetivo y entorno común,
+se abre la posibilidad de adaptar sus cambios a este trabajo, utilizando una
+versión modificada de DMD_ (dado que los cambios aún no son integrados al
+compilador oficial).
 
-Luego Vincent Lang (mejor conocido como *wm4* en la comunidad de D_), retoma
-este trabajo, pero modificando el compilador DMD_ y trabajando con `D 1.0`_
-y Tango_, al igual que este trabajo. Dado el objetivo y entorno común, se abre
-la posibilidad de adaptar los cambios de Vincent Lang a este trabajo,
-utilizando una versión modificada de DMD_ (dado que los cambios aún no son
-integrados al compilador oficial).
+.. TODO: Apéndice con parches a DMD y Tango?
 
 Información de tipos provista por el compilador
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1104,9 +1105,10 @@ memoria. Esta información se pasa como un puntero a un arreglo de palabras con
 la estructura mostrada en la figura :vref:`fig:sol-ptrmap` y que se describe
 a continuación.
 
-.. fig:: fig:sol-ptrmap
+.. flt:: fig:sol-ptrmap
+   :type: table
 
-   Estructura de la información de tipos provista por el compilador.
+   Estructura de la información de tipos provista por el compilador
 
    .. aafig::
       :scale: 110
@@ -1136,7 +1138,9 @@ a continuación.
 
 Los conjuntos de bits guardan la información sobre la primera palabra en el
 bit menos significativo. Dada la complejidad de la representación, se ilustra
-con un ejemplo. Dada la estructura::
+con un ejemplo. Dada la estructura:
+
+.. code-block:: d
 
    union U {
       ubyte ub;
@@ -1166,9 +1170,9 @@ palabra sea realmente un puntero, pero indica que debe ser escaneado. El
 recolector debe debe ser conservativo en este caso, y escanear esa palabra
 como si fuera un puntero.
 
-.. fig:: fig:sol-ptrmap-example
+.. flt:: fig:sol-ptrmap-example
 
-   Ejemplo de estructura de información de tipos generada para el tipo ``S``.
+   Ejemplo de estructura de información de tipos generada para el tipo ``S``
 
    .. aafig::
       :textual:
@@ -1226,10 +1230,10 @@ ese caso no hace falta directamente escanear ninguna palabra del bloque.
 En la figura :vref:`fig:sol-ptrmap-blk` se puede ver, como continuación del
 ejemplo anterior, como se almacenaría en memoria un objeto del tipo ``S``.
 
-.. fig:: fig:sol-ptrmap-blk
+.. flt:: fig:sol-ptrmap-blk
 
    Ejemplo de bloque que almacena un objeto de tipo ``S`` con información de
-   tipo.
+   tipo
 
    .. aafig::
       :scale: 110
@@ -1380,11 +1384,12 @@ que la memoria sea compartida entre los procesos de forma explícita.
 
 Esto, sin embargo, no significa que la memoria física sea realmente duplicada;
 en general todos los sistemas operativos modernos (como Linux_) utilizan una
-técnica llamada *copy-on-write* (*copiar-al-escribir* en castellano) que
-retrasa la copia de memoria hasta que alguno de los dos procesos escribe en un
-segmento. Recién en ese momento el sistema operativo realiza la copia de **ese
-segmento solamente**. Es por esto que la operación puede ser muy eficiente,
-y la copia de memoria es proporcional a la cantidad de cambios que hayan.
+técnica llamada *COW* (de *copy-on-write* en inglés, *copiar-al-escribir* en
+castellano) que retrasa la copia de memoria hasta que alguno de los dos
+procesos escribe en un segmento. Recién en ese momento el sistema operativo
+realiza la copia de **ese segmento solamente**. Es por esto que la operación
+puede ser muy eficiente, y la copia de memoria es proporcional a la cantidad
+de cambios que hayan.
 
 :manpage:`fork(2)` tiene otra propiedad importante de mencionar: detiene todos
 los hilos de ejecución en el proceso hijo. Es decir, el proceso hijo se crear
@@ -1431,8 +1436,8 @@ siguientes [#solforkerr]_::
 
    function collect() is
       stop_the_world()
-      child_pid = fork()
       fflush(null) // evita que se duplique la salida de los FILE* abiertos
+      child_pid = fork()
       if child_pid is 0 // proceso hijo
          mark_phase()
          exit(0) // termina el proceso hijo
@@ -1583,7 +1588,7 @@ empezar la fase de marcado no sean barridas por tener ese bit activo::
             pages = assign_pages(pool, number_of_pages)
       pages[0].block.free = true                         // Agregado
       pages[0].block_size = PAGE
-      foreach page in pages[1..end]
+      foreach page in pages[1 .. end]
          page.block_size = CONTINUATION
       return pages[0]
 
@@ -1727,8 +1732,8 @@ necesarios si no se utiliza la opción ``eager_alloc``::
          else if early                 // Agregado
             return                     //
       stop_the_world()
-      child_pid = fork()
       fflush(null)
+      child_pid = fork()
       if child_pid is 0 // proceso hijo
          mark_phase()
          exit(0)
@@ -1908,8 +1913,6 @@ que se especifique lo contrario), que se detallan a continuación.
    ``$dst_dir`` es el directorio donde almacenar los archivos generados
    y ``$tango_files`` es la lista de archivos fuente de Tango_.
 
-.. highlight:: d
-
 El resto de los programas se ejecutan sin parámetros (ver :ref:`sol_bench`
 para una descripción detallada sobre cada uno).
 
@@ -1965,8 +1968,6 @@ todo
 
       conservative=0:fork=1:early_collect=1:eager_alloc=1
 
-.. highlight:: d
-
 Métricas utilizadas
 ^^^^^^^^^^^^^^^^^^^
 Para analizar los resultados se utilizan varias métricas. Las más importantes
@@ -2082,9 +2083,10 @@ direcciones antiguo, que no tiene una componente aleatoria y asigna primero
 direcciones bajas. La opción ``-R`` solamente desactiva la componente azarosa
 al momento de asignar direcciones.
 
-.. ftable:: t:sol-setarch
+.. flt:: t:sol-setarch
+   :type: table
 
-   Variación entre corridas para TBGC.
+   Variación entre corridas para TBGC
 
    Variación entre corridas para TBGC. La medición está efectuada utilizando
    los valores máximo, mínimo y media estadística de 20 corridas, utilizando
@@ -2092,7 +2094,7 @@ al momento de asignar direcciones.
    realizarse utilizando el desvío estándar en vez de la amplitud máxima, pero
    en este cuadro se quiere ilustrar la variación máxima, no la típica.
 
-   .. subtable::
+   .. subflt::
 
       Del tiempo total de ejecución.
 
@@ -2114,7 +2116,7 @@ al momento de asignar direcciones.
       voronoi  0.886    0.003    0.006
       ======== ======== ======== ========
 
-   .. subtable::
+   .. subflt::
 
       Del consumo máximo de memoria.
 
@@ -2153,67 +2155,6 @@ para evaluar el este efecto en los resultados, siempre que sea posible se
 analizan los resultados de un gran número de corridas observando
 principalmente su mínima, media, máxima y desvío estándar.
 
-.. Tamaño del ejecutable (XXX: SEGUN LAS PRUEBAS NO FUCKING CAMBIA!!!)
-   El tamaño del ejecutable es un factor importante. Cuanto más grande es el
-   ejecutable, más parecieran variar los resultados. Por ejemplo se observa un
-   incremento de la estabilidad de los resultados al eliminar toda información
-   de depuración (*debug*) del ejecutable, utilizando el comando
-   :manpage:`strip(1)` (*stripped*). En el cuadro :vref:`t:sol-exesize-tbgc`
-   se puede ver la reducción del tamaño del ejecutable para TBGC cuando se
-   elimina la información de depuración (4.25 veces más chico en promedio),
-   mientas que en el cuadro :vref:`t:sol-exesize-cdgc` se puede ver CDGC (4.6
-   veces más chico en promedio).
-   .. ftable:: t:sol-exesize-tbgc
-      Reducción del tamaño del ejecutable para TBGC.
-      ======== ======== ======== ==============
-      Nombre   Debug    Stripped Debug/Stripped
-      ======== ======== ======== ==============
-      bh       586517   138060   4.248
-      bigarr   547687   192004   2.852
-      bisort   485857   115164   4.219
-      conalloc 616613   149848   4.115
-      concpu   616575   149848   4.115
-      dil      7293277  1859208  3.923
-      em3d     505019   116324   4.341
-      mcore    461767   105748   4.367
-      rnddata  2832935  1492588  1.898
-      sbtree   526402   129860   4.054
-      split    589353   144308   4.084
-      tree     462009   105844   4.365
-      tsp      544901   128412   4.243
-      voronoi  601259   141112   4.261
-      ======== ======== ======== ==============
-   .. ftable:: t:sol-exesize-cdgc
-      Reducción del tamaño del ejecutable para CDGC.
-      ========  ======== ======== ===============
-      Nombre    Debug    Stripped Debug/Stripped
-      ========  ======== ======== ===============
-      bh        736115   159884   4.604
-      bigarr    697406   213832   3.261
-      bisort    635537   136988   4.639
-      conalloc  766328   171676   4.464
-      concpu    766294   171676   4.464
-      dil       7442657  1881028  3.957
-      em3d      658827   142248   4.632
-      mcore     611486   127576   4.793
-      rnddata   2986736  1518512  1.967
-      sbtree    680217   155784   4.366
-      split     739072   166136   4.449
-      tree      611728   127672   4.791
-      tsp       694581   150236   4.623
-      voronoi   750847   162936   4.608
-      ========  ======== ======== ===============
-   TODO: Mostrar tiempos de corridas.
-
-
-.. Resultados generales
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. Primero se presenta una visión global de los resultados, utilizando las
-   métricas más importantes. Para generar los gráficos se utilizan los valores
-   máximos (en blanco), mínimos (en negro), media y desvío estándar (en gris)
-   calculados en base a, como mínimo, 20 corridas (para algunos casos se hacen
-   hasta 50 corridas).
 
 
 Resultados para pruebas sintizadas
@@ -2226,543 +2167,543 @@ modificaciones propuestas, pero en general distan mucho de como se comporta un
 programa real, por lo que los resultados deben ser analizados teniendo esto
 presente.
 
-``bigarr``
-^^^^^^^^^^
-.. fig:: fig:sol-bigarr-1cpu
+.. flt:: fig:sol-bigarr-1cpu
 
-   Resultados para ``bigarr`` (utilizando 1 procesador).
+   Resultados para ``bigarr`` (utilizando 1 procesador)
 
    Resultados para ``bigarr`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-bigarr-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-bigarr-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-bigarr-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-bigarr-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-bigarr-1cpu.pdf
 
-.. fig:: fig:sol-bigarr-4cpu
+.. flt:: fig:sol-bigarr-4cpu
 
-   Resultados para ``bigarr`` (utilizando 4 procesadores).
+   Resultados para ``bigarr`` (utilizando 4 procesadores)
 
    Resultados para ``bigarr`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-bigarr-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-bigarr-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-bigarr-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-bigarr-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-bigarr-4cpu.pdf
 
-En la figura :vref:`fig:sol-bigarr-1cpu` se pueden observar los resultados
-para ``bigarr`` al utilizar un solo procesador. En ella se puede notar que el
-tiempo total de ejecución en general aumenta al utilizar CDGC, esto es
-esperable, dado esta prueba se limitan a usar servicios del recolector. Dado
-que esta ejecución utiliza solo un procesador y por lo tanto no se puede sacar
-provecho a la concurrencia, es de esperarse que el trabajo extra realizado por
-las modificaciones se vea reflejado en los resultados. En la
-:vref:`fig:sol-bigarr-4cpu` (resultados al utilizar 4 procesadores) se puede
-observar como al usar solamente *eager allocation* se recupera un poco el
-tiempo de ejecución, probablemente debido al incremento en la concurrencia
-(aunque no se observa el mismo efecto al usar *early collection*).
+.. flt:: fig:sol-concpu-1cpu
 
-Observando el tiempo total de ejecución, no se esperaba un incremento tan
-notorio al pasar de TBGC a una configuración equivalente de CDGC **cons**,
-haciendo un breve análisis de las posibles causas, lo más probable parece ser
-el incremento en la complejidad de la fase de marcado dada capacidad para
-marcar de forma precisa (aunque no se use la opción, se paga el precio de la
-complejidad extra y sin obtener los beneficios).  Además se puede observar
-como el agregado de precisión al marcado mejora un poco las cosas (donde sí se
-obtiene rédito de la complejidad extra en el marcado).
-
-En general se observa que al usar *eager allocation* el consumo de memoria
-y los tiempos de pausa se disparan mientras que la cantidad de recolecciones
-disminuye drásticamente. Lo que se observa es que el programa es
-más veloz pidiendo memoria que recolectándola, por lo que crece mucho el
-consumo de memoria. Como consecuencia la fase de barrido (que no corre en
-paralelo al *mutator* como la fase de marcado) empieza a ser predominante en
-el tiempo de pausa por ser tan grande la cantidad de memoria a barrer. Este
-efecto se ve tanto al usar 1 como 4 procesadores, aunque el efecto es mucho
-más nocivo al usar 1 debido a la alta variabilidad que impone la competencia
-entre el *mutator* y recolector al correr de forma concurrente.
-
-Sin embargo, el tiempo de *stop-the-world* es siempre considerablemente más
-pequeño al utilizar marcado concurrente en CDGC, incluso cuando se utiliza
-*eager allocation*, aunque en este caso aumenta un poco, también debido al
-incremento en el consumo de memoria, ya que el sistema operativo tiene que
-copiar tablas de memoria más grandes al efectuar el *fork* (ver
-:ref:`sol_fork`).
-
-``concpu``
-^^^^^^^^^^
-.. fig:: fig:sol-concpu-1cpu
-
-   Resultados para ``concpu`` (utilizando 1 procesador).
+   Resultados para ``concpu`` (utilizando 1 procesador)
 
    Resultados para ``concpu`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-concpu-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-concpu-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-concpu-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-concpu-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-concpu-1cpu.pdf
 
-.. fig:: fig:sol-concpu-4cpu
+.. flt:: fig:sol-concpu-4cpu
 
-   Resultados para ``concpu`` (utilizando 4 procesadores).
+   Resultados para ``concpu`` (utilizando 4 procesadores)
 
    Resultados para ``concpu`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-concpu-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-concpu-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-concpu-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-concpu-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-concpu-4cpu.pdf
 
-En la figura :vref:`fig:sol-concpu-1cpu` se pueden observar los resultados
-para ``concpu`` al utilizar un solo procesador. En ella se aprecia que el
-tiempo total de ejecución disminuye levemente al usar marcado concurrente
-mientras no se utilice *eager allocation* pero aumenta al utilizarlo.
+.. flt:: fig:sol-conalloc-1cpu
 
-Con respecto a la cantidad de recolecciones, uso máximo de memoria y tiempo de
-*stop-the-world* se ve un efecto similar al descripto para ``bigarr`` (aunque
-magnificado), pero sorprendentemente el tiempo total de pausa se dispara,
-además con una variabilidad sorprendente, cuando se usa marcado concurrente
-(pero no *eager allocation*). Una posible explicación podría ser que al
-realizarse el *fork*, el sistema operativo muy probablemente entregue el
-control del único procesador disponible al resto de los hilos que compiten por
-él, por lo que queda mucho tiempo pausado en esa operación aunque realmente no
-esté haciendo trabajo alguno (simplemente no tiene tiempo de procesador para
-correr). Este efecto se cancela al usar *eager allocation* dado que el
-*mutator* nunca se bloquea esperando que el proceso de marcado finalice.
-
-Además se observa una caída importante en la cantidad de recolecciones al
-utilizar marcado concurrente. Esto probablemente se deba a que solo un hilo
-pide memoria (y por lo tanto dispara recolecciones), mientras los demás hilos
-también estén corriendo. Al pausarse todos los hilos por menos tiempo, el
-trabajo se hace más rápido (lo que explica la disminución del tiempo total de
-ejecución) y son necesarias menos recolecciones, por terminar más rápido
-también el hilo que las dispara.
-
-En la :vref:`fig:sol-concpu-4cpu` se pueden ver los resultados al utilizar
-4 procesadores, donde el panorama cambia sustancialmente. El efecto mencionado
-en el párrafo anterior no se observa más (pues el sistema operativo tiene más
-procesadores para asignar a los hilos) pero todos los resultados se vuelven
-más variables. Los tiempos de *stop-the-world* y pausa real (salvo por lo
-recién mencionado) crecen notablemente, al igual que su variación. No se
-encuentra una razón evidente para esto; podría ser un error en la medición
-dado que al utilizar todos los procesadores disponibles del *hardware*,
-cualquier otro proceso que compita por tiempo de procesador puede afectarla
-más fácilmente.
-
-El tiempo total de ejecución crece considerablemente, como se espera, dado que
-el programa aprovecha los múltiples hilos que pueden correr en paralelo en
-procesadores diferentes.
-
-Sin embargo, no se encuentra una razón clara para explicar el crecimiento
-dramático en la cantidad de recolecciones solo al no usar marcado concurrente
-para 4 procesadores.
-
-``conalloc``
-^^^^^^^^^^^^
-.. fig:: fig:sol-conalloc-1cpu
-
-   Resultados para ``conalloc`` (utilizando 1 procesador).
+   Resultados para ``conalloc`` (utilizando 1 procesador)
 
    Resultados para ``conalloc`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-conalloc-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-conalloc-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-conalloc-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-conalloc-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-conalloc-1cpu.pdf
 
-.. fig:: fig:sol-conalloc-4cpu
+.. flt:: fig:sol-conalloc-4cpu
 
-   Resultados para ``conalloc`` (utilizando 4 procesadores).
+   Resultados para ``conalloc`` (utilizando 4 procesadores)
 
    Resultados para ``conalloc`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-conalloc-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-conalloc-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-conalloc-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-conalloc-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-conalloc-4cpu.pdf
 
-En la figura :vref:`fig:sol-conalloc-1cpu` se pueden observar los resultados
-para ``conalloc`` al utilizar un solo procesador. Los cambios con respecto
-a lo observado para ``concpu`` son mínimos. El efecto de la mejoría al usar
-marcado concurrente pero no *eager allocation* no se observa más, dado que
-``conalloc`` pide memoria en todos los hilos, se crea un cuello de botella. Se
-ve claramente como tampoco baja la cantidad de recolecciones hecha debido
-a esto y se invierte la variabilidad entre los tiempos pico de pausa real
-y *stop-the-world* (sin una razón obvia, pero probablemente relacionado que
-todos los hilos piden memoria).
-
-Al utilizar 4 procesadores (figura :vref:`fig:sol-conalloc-4cpu`), más allá de
-las diferencias mencionadas para 1 procesador, no se observan grandes cambios
-con respecto a lo observado para ``concpu``, excepto que los tiempos de pausa
-(real y *stop-the-world*) son notablemente más pequeños, lo que pareciera
-confirmar un error en la medición de ``concpu``.
+.. flt:: fig:sol-split-1cpu
 
-``split``
-^^^^^^^^^
-.. fig:: fig:sol-split-1cpu
-
-   Resultados para ``split`` (utilizando 1 procesador).
+   Resultados para ``split`` (utilizando 1 procesador)
 
    Resultados para ``split`` (utilizando 1 procesador). Se presenta el mínimos
    (en negro), la media centrada entre dos desvíos estándar (en gris), y el
    máximo (en blanco) calculados sobre 50 corridas (para tiempo de ejecución)
    o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-split-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-split-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-split-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-split-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-split-1cpu.pdf
 
-Este es el primer caso donde se aprecia la sustancial mejora proporcionada por
-una pequeña optimización, el caché de ``findSize()`` (ver
-:ref:`sol_minor_findsize`). En la figura :vref:`fig:sol-split-1cpu` se puede
-observar con claridad como, para cualquier configuración de CDGC, hay una
-caída notable en el tiempo total de ejecución. Sin embargo, a excepción de
-cuando se utiliza *eager allocation*, la cantidad de recolecciones y memoria
-usada permanece igual.
-
-La utilización de *eager allocation* mejora (aunque de forma apenas
-apreciable) el tiempo de ejecución, la cantidad de recolecciones baja a un
-tercio y el tiempo de pausa real cae dramáticamente. Al usar marcado
-concurrente ya se observa una caída determinante en el tiempo de
-*stop-the-world*. Todo esto sin verse afectado el uso máximo de memoria,
-incluso al usar *eager allocation*.
+.. flt:: fig:sol-mcore-1cpu
 
-Se omiten los resultados para más de un procesador por ser prácticamente
-idénticos para este análisis.
-
-``mcore``
-^^^^^^^^^
-.. fig:: fig:sol-mcore-1cpu
-
-   Resultados para ``mcore`` (utilizando 1 procesador).
+   Resultados para ``mcore`` (utilizando 1 procesador)
 
    Resultados para ``mcore`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-mcore-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-mcore-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-mcore-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-mcore-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-mcore-1cpu.pdf
 
-.. fig:: fig:sol-mcore-4cpu
+.. flt:: fig:sol-mcore-4cpu
 
-   Resultados para ``mcore`` (utilizando 4 procesadores).
+   Resultados para ``mcore`` (utilizando 4 procesadores)
 
    Resultados para ``mcore`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-mcore-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-mcore-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-mcore-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-mcore-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-mcore-4cpu.pdf
 
-El caso de ``mcore`` es interesante por ser, funcionalmente, una combinación
-entre ``concpu`` y ``split``, con un agregado extra: el incremento notable de
-la competencia por utilizar el recolector entre los múltiples hilos.
+.. flt:: fig:sol-rnddata-1cpu
 
-Los efectos observados (en la figura :vref:`fig:sol-mcore-1cpu` para
-1 procesador y en la figura :vref:`fig:sol-mcore-4cpu` para 4) confirman esto,
-al ser una suma de los efectos observados para ``concpu`` y ``split``, con el
-agregado de una particularidad extra por la mencionada competencia entre
-hilos. A diferencia de ``concpu`` donde el incremento de procesadores resulta
-en un decremento en el tiempo total de ejecución, en este caso resulta en una
-disminución, dado que se necesita mucha sincronización entre hilos, por
-utilizar todos de forma intensiva los servicios del recolector (y por lo tanto
-competir por su *lock* global).
-
-Otro efecto común observado es que cuando el tiempo de pausa es muy pequeño
-(del orden de los milisegundos), el marcado concurrente suele incrementarlo en
-vez de disminuirlo.
-
-``rnddata``
-^^^^^^^^^^^
-.. fig:: fig:sol-rnddata-1cpu
-
-   Resultados para ``rnddata`` (utilizando 1 procesador).
+   Resultados para ``rnddata`` (utilizando 1 procesador)
 
    Resultados para ``rnddata`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-rnddata-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-rnddata-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-rnddata-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-rnddata-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-rnddata-1cpu.pdf
 
+``bigarr``
+^^^^^^^^^^
+En la figura :vref:`fig:sol-bigarr-1cpu` se pueden observar los resultados
+para ``bigarr`` al utilizar un solo procesador. En ella se puede notar que el
+tiempo total de ejecución en general aumenta al utilizar CDGC, esto es
+esperable, dado esta prueba se limitan a usar servicios del recolector. Dado
+que esta ejecución utiliza solo un procesador y por lo tanto no se puede sacar
+provecho a la concurrencia, es de esperarse que el trabajo extra realizado por
+las modificaciones se vea reflejado en los resultados. En la
+:vref:`fig:sol-bigarr-4cpu` (resultados al utilizar 4 procesadores) se puede
+observar como al usar solamente *eager allocation* se recupera un poco el
+tiempo de ejecución, probablemente debido al incremento en la concurrencia
+(aunque no se observa el mismo efecto al usar *early collection*).
+
+Observando el tiempo total de ejecución, no se esperaba un incremento tan
+notorio al pasar de TBGC a una configuración equivalente de CDGC **cons**,
+haciendo un breve análisis de las posibles causas, lo más probable parece ser
+el incremento en la complejidad de la fase de marcado dada capacidad para
+marcar de forma precisa (aunque no se use la opción, se paga el precio de la
+complejidad extra y sin obtener los beneficios).  Además se puede observar
+como el agregado de precisión al marcado mejora un poco las cosas (donde sí se
+obtiene rédito de la complejidad extra en el marcado).
+
+En general se observa que al usar *eager allocation* el consumo de memoria
+y los tiempos de pausa se disparan mientras que la cantidad de recolecciones
+disminuye drásticamente. Lo que se observa es que el programa es
+más veloz pidiendo memoria que recolectándola, por lo que crece mucho el
+consumo de memoria. Como consecuencia la fase de barrido (que no corre en
+paralelo al *mutator* como la fase de marcado) empieza a ser predominante en
+el tiempo de pausa por ser tan grande la cantidad de memoria a barrer. Este
+efecto se ve tanto al usar 1 como 4 procesadores, aunque el efecto es mucho
+más nocivo al usar 1 debido a la alta variabilidad que impone la competencia
+entre el *mutator* y recolector al correr de forma concurrente.
+
+Sin embargo, el tiempo de *stop-the-world* es siempre considerablemente más
+pequeño al utilizar marcado concurrente en CDGC, incluso cuando se utiliza
+*eager allocation*, aunque en este caso aumenta un poco, también debido al
+incremento en el consumo de memoria, ya que el sistema operativo tiene que
+copiar tablas de memoria más grandes al efectuar el *fork* (ver
+:ref:`sol_fork`).
+
+``concpu``
+^^^^^^^^^^
+En la figura :vref:`fig:sol-concpu-1cpu` se pueden observar los resultados
+para ``concpu`` al utilizar un solo procesador. En ella se aprecia que el
+tiempo total de ejecución disminuye levemente al usar marcado concurrente
+mientras no se utilice *eager allocation* pero aumenta al utilizarlo.
+
+Con respecto a la cantidad de recolecciones, uso máximo de memoria y tiempo de
+*stop-the-world* se ve un efecto similar al descripto para ``bigarr`` (aunque
+magnificado), pero sorprendentemente el tiempo total de pausa se dispara,
+además con una variabilidad sorprendente, cuando se usa marcado concurrente
+(pero no *eager allocation*). Una posible explicación podría ser que al
+realizarse el *fork*, el sistema operativo muy probablemente entregue el
+control del único procesador disponible al resto de los hilos que compiten por
+él, por lo que queda mucho tiempo pausado en esa operación aunque realmente no
+esté haciendo trabajo alguno (simplemente no tiene tiempo de procesador para
+correr). Este efecto se cancela al usar *eager allocation* dado que el
+*mutator* nunca se bloquea esperando que el proceso de marcado finalice.
+
+Además se observa una caída importante en la cantidad de recolecciones al
+utilizar marcado concurrente. Esto probablemente se deba a que solo un hilo
+pide memoria (y por lo tanto dispara recolecciones), mientras los demás hilos
+también estén corriendo. Al pausarse todos los hilos por menos tiempo, el
+trabajo se hace más rápido (lo que explica la disminución del tiempo total de
+ejecución) y son necesarias menos recolecciones, por terminar más rápido
+también el hilo que las dispara.
+
+En la :vref:`fig:sol-concpu-4cpu` se pueden ver los resultados al utilizar
+4 procesadores, donde el panorama cambia sustancialmente. El efecto mencionado
+en el párrafo anterior no se observa más (pues el sistema operativo tiene más
+procesadores para asignar a los hilos) pero todos los resultados se vuelven
+más variables. Los tiempos de *stop-the-world* y pausa real (salvo por lo
+recién mencionado) crecen notablemente, al igual que su variación. No se
+encuentra una razón evidente para esto; podría ser un error en la medición
+dado que al utilizar todos los procesadores disponibles del *hardware*,
+cualquier otro proceso que compita por tiempo de procesador puede afectarla
+más fácilmente.
+
+El tiempo total de ejecución crece considerablemente, como se espera, dado que
+el programa aprovecha los múltiples hilos que pueden correr en paralelo en
+procesadores diferentes.
+
+Sin embargo, no se encuentra una razón clara para explicar el crecimiento
+dramático en la cantidad de recolecciones solo al no usar marcado concurrente
+para 4 procesadores.
+
+``conalloc``
+^^^^^^^^^^^^
+En la figura :vref:`fig:sol-conalloc-1cpu` se pueden observar los resultados
+para ``conalloc`` al utilizar un solo procesador. Los cambios con respecto
+a lo observado para ``concpu`` son mínimos. El efecto de la mejoría al usar
+marcado concurrente pero no *eager allocation* no se observa más, dado que
+``conalloc`` pide memoria en todos los hilos, se crea un cuello de botella. Se
+ve claramente como tampoco baja la cantidad de recolecciones hecha debido
+a esto y se invierte la variabilidad entre los tiempos pico de pausa real
+y *stop-the-world* (sin una razón obvia, pero probablemente relacionado que
+todos los hilos piden memoria).
+
+Al utilizar 4 procesadores (figura :vref:`fig:sol-conalloc-4cpu`), más allá de
+las diferencias mencionadas para 1 procesador, no se observan grandes cambios
+con respecto a lo observado para ``concpu``, excepto que los tiempos de pausa
+(real y *stop-the-world*) son notablemente más pequeños, lo que pareciera
+confirmar un error en la medición de ``concpu``.
+
+``split``
+^^^^^^^^^
+Este es el primer caso donde se aprecia la sustancial mejora proporcionada por
+una pequeña optimización, el caché de ``findSize()`` (ver
+:ref:`sol_minor_findsize`). En la figura :vref:`fig:sol-split-1cpu` se puede
+observar con claridad como, para cualquier configuración de CDGC, hay una
+caída notable en el tiempo total de ejecución. Sin embargo, a excepción de
+cuando se utiliza *eager allocation*, la cantidad de recolecciones y memoria
+usada permanece igual.
+
+La utilización de *eager allocation* mejora (aunque de forma apenas
+apreciable) el tiempo de ejecución, la cantidad de recolecciones baja a un
+tercio y el tiempo de pausa real cae dramáticamente. Al usar marcado
+concurrente ya se observa una caída determinante en el tiempo de
+*stop-the-world*. Todo esto sin verse afectado el uso máximo de memoria,
+incluso al usar *eager allocation*.
+
+Se omiten los resultados para más de un procesador por ser prácticamente
+idénticos para este análisis.
+
+``mcore``
+^^^^^^^^^
+El caso de ``mcore`` es interesante por ser, funcionalmente, una combinación
+entre ``concpu`` y ``split``, con un agregado extra: el incremento notable de
+la competencia por utilizar el recolector entre los múltiples hilos.
+
+Los efectos observados (en la figura :vref:`fig:sol-mcore-1cpu` para
+1 procesador y en la figura :vref:`fig:sol-mcore-4cpu` para 4) confirman esto,
+al ser una suma de los efectos observados para ``concpu`` y ``split``, con el
+agregado de una particularidad extra por la mencionada competencia entre
+hilos. A diferencia de ``concpu`` donde el incremento de procesadores resulta
+en un decremento en el tiempo total de ejecución, en este caso resulta en una
+disminución, dado que se necesita mucha sincronización entre hilos, por
+utilizar todos de forma intensiva los servicios del recolector (y por lo tanto
+competir por su *lock* global).
+
+Otro efecto común observado es que cuando el tiempo de pausa es muy pequeño
+(del orden de los milisegundos), el marcado concurrente suele incrementarlo en
+vez de disminuirlo.
+
+``rnddata``
+^^^^^^^^^^^
 En la figura :vref:`fig:sol-rnddata-1cpu` se presentan los resultados para
 ``rnddata`` utilizando 1 procesador. Una vez más estamos ante un caso en el
 cual se observa claramente la mejoría gracias a una modificación en particular
@@ -2810,75 +2751,59 @@ trabajo.
 Resultados para pruebas pequeñas
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-A continuación se presentan los resultados obtenidos para las pruebas pequeñas
-(ver :ref:`sol_bench_small`). Se recuerda que si bien este conjunto de pruebas
-se compone de programas reales, que efectúan una tarea útil, están diseñados
-para ejercitar la asignación de memoria y que no son recomendados para evaluar
-el desempeño de recolectores de basura. Sin embargo se las utiliza igual por
-falta de programas más realistas, por lo que hay que tomarlas como un grado de
-suspicacia.
+.. flt:: fig:sol-bh-1cpu
 
-``bh``
-^^^^^^
-.. fig:: fig:sol-bh-1cpu
-
-   Resultados para ``bh`` (utilizando 1 procesador).
+   Resultados para ``bh`` (utilizando 1 procesador)
 
    Resultados para ``bh`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-bh-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-bh-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-bh-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-bh-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-bh-1cpu.pdf
 
-En la figura :vref:`fig:sol-bh-1cpu` se pueden observar los resultados
-para ``bh`` al utilizar un solo procesador. Ya en una prueba un poco más
-realista se puede observar el efecto positivo del marcado preciso, en especial
-en la cantidad de recolecciones efectuadas (aunque no se traduzca en un menor
-consumo de memoria).
-
-Sin embargo se observa también un efecto nocivo del marcado preciso en el
-consumo de memoria que intuitivamente debería disminuir, pero crece, y de
-forma considerable (unas 3 veces en promedio). La razón de esta particularidad
-es el incremento en el espacio necesario para almacenar objetos debido a que
-el puntero a la información del tipo se guarda al final del bloque (ver
-:ref:`sol_precise`). En el cuadro :vref:`t:sol-prec-mem-bh` se puede observar
-la cantidad de memoria pedida por el programa, la cantidad de memoria
-realmente asignada por el recolector (y la memoria desperdiciada) cuando se
-usa marcado conservativo y preciso. Estos valores fueron tomados usando la
-opción ``malloc_stats_file`` (ver :ref:`sol_stats`).
+A continuación se presentan los resultados obtenidos para las pruebas pequeñas
+(ver :ref:`sol_bench_small`). Se recuerda que si bien este conjunto de pruebas
+se compone de programas reales, que efectúan una tarea útil, están diseñados
+para ejercitar la asignación de memoria y que no son recomendados para evaluar
+el desempeño de recolectores de basura. Sin embargo se las utiliza igual por
+falta de programas más realistas, por lo que hay que tomarlas como un grado de
+suspicacia.
 
-.. ftable:: t:sol-prec-mem-bh
+``bh``
+^^^^^^
+.. flt:: t:sol-prec-mem-bh
+   :type: table
 
-   Memoria pedida y asignada para ``bh`` según modo de marcado.
+   Memoria pedida y asignada para ``bh`` según modo de marcado
 
    Memoria pedida y asignada para ``bh`` según modo de marcado conservativo
    o preciso (acumulativo durante toda la vida del programa).
@@ -2890,252 +2815,269 @@ opción ``malloc_stats_file`` (ver :ref:`sol_stats`).
    Preciso        302.54         472.26         169.72 (36%)
    ============== ============== ============== =================
 
-Más allá de esto, los resultados son muy similares a los obtenidos para
-pruebas sintetizadas que se limitan a ejercitar el recolector (como ``bigarr``
-y ``sbtree``), lo que habla de lo mucho que también lo hace este pequeño
-programa.
-
-No se muestran los resultados para más de un procesador por ser extremadamente
-similares a los obtenidos utilizando solo uno.
+En la figura :vref:`fig:sol-bh-1cpu` se pueden observar los resultados
+para ``bh`` al utilizar un solo procesador. Ya en una prueba un poco más
+realista se puede observar el efecto positivo del marcado preciso, en especial
+en la cantidad de recolecciones efectuadas (aunque no se traduzca en un menor
+consumo de memoria).
 
-``bisort``
-^^^^^^^^^^
-.. fig:: fig:sol-bisort-1cpu
+.. flt:: fig:sol-bisort-1cpu
 
-   Resultados para ``bisort`` (utilizando 1 procesador).
+   Resultados para ``bisort`` (utilizando 1 procesador)
 
    Resultados para ``bisort`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-bisort-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-bisort-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-bisort-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-bisort-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-bisort-1cpu.pdf
 
-La figura :vref:`fig:sol-bisort-1cpu` muestra los resultados para ``bisort``
-al utilizar 1 procesador. En este caso el parecido es con los resultados para
-la prueba sintetizada ``split``, con la diferencia que el tiempo de ejecución
-total prácticamente no varía entre TBGC y CDGC, ni entre las diferentes
-configuraciones del último (evidentemente en este caso no se aprovecha el
-caché de ``findSize()``).
-
-Otra diferencia notable es la considerable reducción del tiempo de pausa real
-al utilizar *early collection* (más de 3 veces menor en promedio comparado
-a cuando se marca conservativamente, y más de 2 veces menor que cuando se hace
-de forma precisa), lo que indica que la predicción de cuando se va a necesitar
-una recolección es más efectiva que para ``split``.
-
-No se muestran los resultados para más de un procesador por ser extremadamente
-similares a los obtenidos utilizando solo uno.
+Sin embargo se observa también un efecto nocivo del marcado preciso en el
+consumo de memoria que intuitivamente debería disminuir, pero crece, y de
+forma considerable (unas 3 veces en promedio). La razón de esta particularidad
+es el incremento en el espacio necesario para almacenar objetos debido a que
+el puntero a la información del tipo se guarda al final del bloque (ver
+:ref:`sol_precise`). En el cuadro :vref:`t:sol-prec-mem-bh` se puede observar
+la cantidad de memoria pedida por el programa, la cantidad de memoria
+realmente asignada por el recolector (y la memoria desperdiciada) cuando se
+usa marcado conservativo y preciso. Estos valores fueron tomados usando la
+opción ``malloc_stats_file`` (ver :ref:`sol_stats`).
 
-``em3d``
-^^^^^^^^
-.. fig:: fig:sol-em3d-1cpu
+.. flt:: fig:sol-em3d-1cpu
 
-   Resultados para ``em3d`` (utilizando 1 procesador).
+   Resultados para ``em3d`` (utilizando 1 procesador)
 
    Resultados para ``em3d`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-em3d-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-em3d-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-em3d-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-em3d-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-em3d-1cpu.pdf
 
-Los resultados para ``em3d`` (figura :vref:`fig:sol-em3d-1cpu`) son
-sorprendentemente similares a los de ``bisort``. La única diferencia es que en
-este caso el marcado preciso y el uso de *early collection** no parecen
-ayudar; por el contrario, aumentan levemente el tiempo de pausa real.
+Más allá de esto, los resultados son muy similares a los obtenidos para
+pruebas sintetizadas que se limitan a ejercitar el recolector (como ``bigarr``
+y ``sbtree``), lo que habla de lo mucho que también lo hace este pequeño
+programa.
 
-Una vez más no se muestran los resultados para más de un procesador por ser
-extremadamente similares a los obtenidos utilizando solo uno.
+No se muestran los resultados para más de un procesador por ser extremadamente
+similares a los obtenidos utilizando solo uno.
 
-``tsp``
-^^^^^^^^
-.. fig:: fig:sol-tsp-1cpu
+``bisort``
+^^^^^^^^^^
+La figura :vref:`fig:sol-bisort-1cpu` muestra los resultados para ``bisort``
+al utilizar 1 procesador. En este caso el parecido es con los resultados para
+la prueba sintetizada ``split``, con la diferencia que el tiempo de ejecución
+total prácticamente no varía entre TBGC y CDGC, ni entre las diferentes
+configuraciones del último (evidentemente en este caso no se aprovecha el
+caché de ``findSize()``).
 
-   Resultados para ``tsp`` (utilizando 1 procesador).
+.. flt:: fig:sol-tsp-1cpu
+
+   Resultados para ``tsp`` (utilizando 1 procesador)
 
    Resultados para ``tsp`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-tsp-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-tsp-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-tsp-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-tsp-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-tsp-1cpu.pdf
 
-Los resultados para ``tsp`` (figura :vref:`fig:sol-tsp-1cpu`) son
-prácticamente idénticos a los de ``bisort``. La única diferencia es que la
-reducción del tiempo de pausa real es un poco menor.
+Otra diferencia notable es la considerable reducción del tiempo de pausa real
+al utilizar *early collection* (más de 3 veces menor en promedio comparado
+a cuando se marca de forma conservativa, y más de 2 veces menor que cuando se
+hace de forma precisa), lo que indica que la predicción de cuando se va
+a necesitar una recolección es más efectiva que para ``split``.
 
-Esto confirma en cierta medida la poca utilidad de este juego de pruebas para
-medir el rendimiento de un recolector, dado que evidentemente, si bien todas
-resuelven problemas diferentes, realizan todas el mismo tipo de trabajo.
+No se muestran los resultados para más de un procesador por ser extremadamente
+similares a los obtenidos utilizando solo uno.
 
-Una vez más no se muestran los resultados para más de un procesador por ser
-extremadamente similares a los obtenidos utilizando solo uno.
+``em3d``
+^^^^^^^^
+Los resultados para ``em3d`` (figura :vref:`fig:sol-em3d-1cpu`) son
+sorprendentemente similares a los de ``bisort``. La única diferencia es que en
+este caso el marcado preciso y el uso de *early collection** no parecen
+ayudar; por el contrario, aumentan levemente el tiempo de pausa real.
 
-``voronoi``
-^^^^^^^^^^^
-.. fig:: fig:sol-voronoi-1cpu
+.. flt:: fig:sol-voronoi-1cpu
 
-   Resultados para ``voronoi`` (utilizando 1 procesador).
+   Resultados para ``voronoi`` (utilizando 1 procesador)
 
    Resultados para ``voronoi`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-voronoi-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-voronoi-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-voronoi-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-voronoi-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-voronoi-1cpu.pdf
 
-.. fig:: fig:sol-voronoi-4cpu
+.. flt:: fig:sol-voronoi-4cpu
 
-   Resultados para ``voronoi`` (utilizando 4 procesadores).
+   Resultados para ``voronoi`` (utilizando 4 procesadores)
 
    Resultados para ``voronoi`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-voronoi-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-voronoi-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-voronoi-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-voronoi-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-voronoi-4cpu.pdf
 
+Una vez más no se muestran los resultados para más de un procesador por ser
+extremadamente similares a los obtenidos utilizando solo uno.
+
+``tsp``
+^^^^^^^^
+Los resultados para ``tsp`` (figura :vref:`fig:sol-tsp-1cpu`) son
+prácticamente idénticos a los de ``bisort``. La única diferencia es que la
+reducción del tiempo de pausa real es un poco menor.
+
+Esto confirma en cierta medida la poca utilidad de este juego de pruebas para
+medir el rendimiento de un recolector, dado que evidentemente, si bien todas
+resuelven problemas diferentes, realizan todas el mismo tipo de trabajo.
+
+Una vez más no se muestran los resultados para más de un procesador por ser
+extremadamente similares a los obtenidos utilizando solo uno.
+
+``voronoi``
+^^^^^^^^^^^
 En la figura :vref:`fig:sol-voronoi-1cpu` se presentan los resultados para
 ``voronoi``, probablemente la prueba más interesante de este conjunto de
 pruebas pequeñas.
@@ -3170,104 +3112,103 @@ al usar 4 (ver figura :vref:`fig:sol-voronoi-4cpu` disminuye levemente (además
 de otros cambios en el nivel de variación, pero en general las medias no
 cambian).
 
-
 Resultados para pruebas reales
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-A continuación se presentan los resultados obtenidos para las pruebas reales
-(ver :ref:`sol_bench_real`). Recordamos que solo se pudo halla un programa que
-pueda ser utilizado a este fin, Dil_, y que el objetivo principal de este
-trabajo se centra alrededor de obtener resultados positivos para este
-programa, por lo que a pesar de ser una única prueba, se le presta particular
-atención.
-
-``dil``
-^^^^^^^
-.. fig:: fig:sol-dil-1cpu
+.. flt:: fig:sol-dil-1cpu
 
-   Resultados para ``dil`` (utilizando 1 procesador).
+   Resultados para ``dil`` (utilizando 1 procesador)
 
    Resultados para ``dil`` (utilizando 1 procesador). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-dil-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-dil-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-dil-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-dil-1cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-dil-1cpu.pdf
 
-.. fig:: fig:sol-dil-4cpu
+A continuación se presentan los resultados obtenidos para las pruebas reales
+(ver :ref:`sol_bench_real`). Recordamos que solo se pudo halla un programa que
+pueda ser utilizado a este fin, Dil_, y que el objetivo principal de este
+trabajo se centra alrededor de obtener resultados positivos para este
+programa, por lo que a pesar de ser una única prueba, se le presta particular
+atención.
+
+``dil``
+^^^^^^^
+En la figura :vref:`fig:sol-dil-1cpu` se presentan los resultados para
+``dil`` al utilizar un procesador. Una vez más vemos una mejoría inmediata del
+tiempo total de ejecución al pasar de TBGC a CDGC, y una vez más se debe
+principalmente al mal factor de ocupación del *heap* de TBGC, dado que
+utilizando CDGC con la opción ``min_free=0`` se obtiene una media del orden de
+los 80 segundos, bastante más alta que el tiempo obtenido para TBGC.
 
-   Resultados para ``dil`` (utilizando 4 procesadores).
+.. flt:: fig:sol-dil-4cpu
+
+   Resultados para ``dil`` (utilizando 4 procesadores)
 
    Resultados para ``dil`` (utilizando 4 procesadores). Se presenta el
    mínimos (en negro), la media centrada entre dos desvíos estándar (en gris),
    y el máximo (en blanco) calculados sobre 50 corridas (para tiempo de
    ejecución) o 20 corridas (para el resto).
 
-   .. subfig::
+   .. subflt::
 
       Tiempo de ejecución (seg)
 
       .. image:: plots/time-dil-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Cantidad de recolecciones
 
       .. image:: plots/ncol-dil-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Uso máximo de memoria (MiB)
 
       .. image:: plots/mem-dil-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       *Stop-the-world* máximo (seg)
 
       .. image:: plots/stw-dil-4cpu.pdf
 
-   .. subfig::
+   .. subflt::
 
       Pausa real máxima (seg)
 
       .. image:: plots/pause-dil-4cpu.pdf
 
-En la figura :vref:`fig:sol-dil-1cpu` se presentan los resultados para
-``dil`` al utilizar un procesador. Una vez más vemos una mejoría inmediata del
-tiempo total de ejecución al pasar de TBGC a CDGC, y una vez más se debe
-principalmente al mal factor de ocupación del *heap* de TBGC, dado que
-utilizando CDGC con la opción ``min_free=0`` se obtiene una media del orden de
-los 80 segundos, bastante más alta que el tiempo obtenido para TBGC.
-
 Sin embargo se observa un pequeño incremento del tiempo de ejecución al
 introducir marcado preciso, y un incremento bastante más importante (de
 alrededor del 30%) en el consumo máximo de memoria. Nuevamente, como pasa con
@@ -3277,14 +3218,10 @@ información del tipo se guarda al final del bloque (ver :ref:`sol_precise`).
 En el cuadro :vref:`t:sol-prec-mem-dil` se puede observar la diferencia de
 memoria desperdiciada entre el modo conservativo y preciso.
 
-El pequeño incremento en el tiempo total de ejecución podría estar dado por la
-mayor probabilidad de tener *falsos punteros* debido al incremento del tamaño
-del *heap*; se recuerda que el *stack* y memoria estática se siguen marcado de
-forma conservativa, incluso en modo preciso.
-
-.. ftable:: t:sol-prec-mem-dil
+.. flt:: t:sol-prec-mem-dil
+   :type: table
 
-   Memoria pedida y asignada para ``dil`` según modo de marcado.
+   Memoria pedida y asignada para ``dil`` según modo de marcado
 
    Memoria pedida y asignada para ``dil`` según modo de marcado conservativo
    o preciso (acumulativo durante toda la vida del programa).
@@ -3296,6 +3233,11 @@ forma conservativa, incluso en modo preciso.
    Preciso        307.48         460.24         152.76 (33%)
    ============== ============== ============== =================
 
+El pequeño incremento en el tiempo total de ejecución podría estar dado por la
+mayor probabilidad de tener *falsos punteros* debido al incremento del tamaño
+del *heap*; se recuerda que el *stack* y memoria estática se siguen marcado de
+forma conservativa, incluso en modo preciso.
+
 También se puede observar una gran disminución del tiempo total de ejecución
 (cerca de un 60%, y más de un 200% comparado con TBGC) alrededor de la mitad)
 al empezar a usar *eager allocation*, acompañado como es usual de una baja en