Búsqueda Híbrida y Rank Fusion (Semántica + Palabras Clave)

Descripción general

La búsqueda híbrida en Fess combina la búsqueda tradicional por palabras clave (BM25) con la búsqueda semántica (vectorial) y fusiona ambos conjuntos de resultados mediante Rank Fusion para producir clasificaciones más precisas y relevantes. Rank Fusion integra los resultados de múltiples buscadores en un único ranking optimizado.

En Fess 15.9, la búsqueda semántica (chunking de contenido + búsqueda vectorial) se proporciona como una función del núcleo. Una vez que la habilita, el buscador semántico se registra automáticamente con Rank Fusion. Consulte Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial) para su configuración.

La función de Rank Fusion de Fess integra múltiples resultados de búsqueda para proporcionar resultados de búsqueda más precisos.

Qué es Rank Fusion

Rank Fusion es una técnica que combina resultados de múltiples algoritmos de búsqueda o métodos de puntuación (por ejemplo, palabras clave/BM25 y búsqueda semántica/vectorial) para generar un único ranking optimizado.

Principales beneficios:

  • Combina las fortalezas de diferentes algoritmos

  • Mejora la precisión de búsqueda

  • Proporciona resultados de búsqueda diversos

Algoritmos compatibles

Fess soporta el algoritmo RRF (Reciprocal Rank Fusion) para Rank Fusion.

RRF (Reciprocal Rank Fusion)

RRF calcula una puntuación sumando el recíproco de la posición de cada documento en cada resultado de búsqueda. Cuando un documento es recuperado por múltiples buscadores, sus puntuaciones se suman.

Fórmula:

score(d) = Σ 1 / (k + rank(d))
  • k: Parámetro constante que controla la influencia del rango (valor predeterminado: 20)

  • rank(d): Posición del documento d en cada resultado de búsqueda (base 0)

  • Σ: Suma sobre todos los buscadores en los que aparece el documento d

Nota

Cuando la fusión la realiza Fess (el comportamiento predeterminado), el algoritmo es siempre RRF y no se admite la ponderación por buscador: la contribución de cada buscador se suma con el mismo peso, y rank.fusion.rank_constant es el único ajuste que permite modificar la tendencia del ranking. Cuando la fusión la realiza el motor de búsqueda, se dispone de otras técnicas de combinación y de pesos por buscador (consulte Rank Fusion en el motor de búsqueda).

Configuración

fess_config.properties

Configuración básica:

# Tamaño de ventana (número de resultados a fusionar)
# Nota: Debe ser >= paging.search.page.max.size × 2.
# Si el valor es inferior a este mínimo, se utiliza automáticamente el mínimo.
rank.fusion.window_size=200

# Constante de rango (parámetro k para RRF)
rank.fusion.rank_constant=20

# Número de hilos para procesamiento paralelo
# (si es 0 o menos, se usa availableProcessors × 3 ÷ 2 + 1)
rank.fusion.threads=-1

# Nombre del campo de puntuación (campo que almacena la puntuación fusionada)
rank.fusion.score_field=rf_score
Propiedad Predeterminado Descripción
rank.fusion.window_size 200 Número máximo de resultados recuperados de cada buscador para la fusión. Debe ser >= paging.search.page.max.size × 2 (200 de forma predeterminada); si se establece un valor menor, se eleva automáticamente a este mínimo (se registra una advertencia WARN al iniciar).
rank.fusion.rank_constant 20 La constante k en la fórmula RRF. Un valor mayor reduce la diferencia de puntuación entre los resultados con mayor y menor rango.
rank.fusion.threads -1 Número de hilos del grupo de hilos fijo que ejecuta múltiples buscadores en paralelo. Si se especifica 0 o menos, se usa availableProcessors × 3 ÷ 2 + 1 automáticamente (al tratarse de aritmética entera, la parte decimal se trunca; por ejemplo: 4 núcleos → 7, 5 núcleos → 8).
rank.fusion.score_field rf_score Nombre del campo del documento de resultados utilizado para almacenar la puntuación fusionada.

Nota

Cuándo se aplican los cambios de configuración

Los cuatro ajustes anteriores requieren reiniciar Fess para que un cambio se aplique. Los valores leídos de fess_config.properties se almacenan en caché en la JVM, por lo que modificar el archivo mientras Fess está en ejecución no tiene ningún efecto.

A modo de referencia, rank.fusion.window_size se lee una sola vez al iniciar y rank.fusion.threads se lee en el momento en que se crea el grupo de hilos. El grupo de hilos se crea cuando se registra un buscador distinto de default (por ejemplo, el buscador semántico), de modo que si la búsqueda semántica está deshabilitada no se crea ningún grupo de hilos.

Propiedades del sistema JVM

Los buscadores a utilizar se especifican como una propiedad del sistema JVM. Añada lo siguiente a fess.in.sh:

FESS_JAVA_OPTS="$FESS_JAVA_OPTS -Drank.fusion.searchers=default,semantic_chunk"

En el caso de fess.in.bat, escriba lo siguiente:

set FESS_JAVA_OPTS=%FESS_JAVA_OPTS% -Drank.fusion.searchers=default,semantic_chunk

Esta propiedad se comporta de la siguiente manera:

  • Se establece como opción JVM, no en fess_config.properties. Especifique el nombre de la clave tal cual: rank.fusion.searchers. Las formas con los prefijos -Dfess.config. o -Dfess.system., habituales en otros ajustes (por ejemplo, -Dfess.config.rank.fusion.searchers), no se reconocen.

  • En lugar de una opción JVM, también puede escribirlo en una sola línea, como rank.fusion.searchers=default,semantic_chunk, en el campo «Propiedades del sistema» de «Sistema > General» de la pantalla de administración. Tenga en cuenta que el valor de ese campo solo se aplica cuando todavía no existe una propiedad del sistema con el mismo nombre. Por ello, si se ha indicado con -D, la opción JVM tiene prioridad, y para modificar un valor que ya se ha aplicado es necesario reiniciar Fess.

  • default es el buscador que realiza la búsqueda estándar por palabras clave y siempre está disponible.

  • El nombre de un buscador se deriva del nombre de su clase de implementación eliminando el sufijo Searcher y convirtiendo el resto a snake_case en minúsculas (SemanticChunkSearcher → semantic_chunk). El buscador semántico integrado en el núcleo (Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial)) se registra con el nombre semantic_chunk.

  • Si esta propiedad no se especifica, se utilizan todos los buscadores registrados. Si ninguno de los nombres especificados coincide con un buscador registrado, solo se utiliza el buscador default. Si utiliza el buscador semántico integrado en el núcleo (Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial)), normalmente no necesita establecer esta propiedad en absoluto.

  • La fusión de resultados se realiza únicamente cuando hay dos o más buscadores disponibles. Cuando solo hay un buscador disponible, no se realiza la fusión y se devuelven los resultados de búsqueda normales.

Advertencia

Si anteriormente utilizaba el plugin fess-webapp-semantic-search de Fess 15.7 o anterior, es posible que se le haya indicado que estableciera esta propiedad como -Drank.fusion.searchers=default,semantic. Ese plugin registraba su buscador con el nombre semantic, que es un buscador diferente del nombre del buscador integrado en el núcleo, semantic_chunk, introducido en la 15.9. Si traslada esa configuración de la era 15.7 a la 15.9 sin cambios, la lista de permitidos nunca incluye semantic_chunk, por lo que la búsqueda semántica integrada en el núcleo (chunking de contenido + búsqueda vectorial) no funciona en absoluto — Fess sigue devolviendo silenciosamente resultados de búsqueda por palabras clave normales (se registra una advertencia al iniciar, pero la exclusión por solicitud en sí solo se registra en el nivel DEBUG). Si su configuración especifica default,semantic, elimine este ajuste o añada semantic_chunk. Consulte «Migración desde la versión 15.7 o anterior» en Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial) para más detalles.

Rank Fusion en el motor de búsqueda

Si establece rank.fusion.engine.enabled=true, la fusión la realiza OpenSearch en lugar de Fess. Las consultas de los buscadores se combinan en una única solicitud de búsqueda (una consulta hybrid), y un search pipeline de OpenSearch normaliza y combina las puntuaciones. Como la fusión se realiza en una sola solicitud, el número total de resultados y los recuentos de las facetas también corresponden al conjunto de resultados fusionado.

Esto requiere el plugin neural-search de OpenSearch. Está incluido en la distribución estándar de OpenSearch y en la imagen ghcr.io/codelibs/fess-opensearch, pero no en la distribución mínima.

Los ajustes se escriben en fess_config.properties (un cambio requiere reiniciar Fess):

rank.fusion.engine.enabled=true
rank.fusion.combination.technique=rrf
rank.fusion.normalization.technique=min_max
rank.fusion.combination.weights=
rank.fusion.pagination_depth=1000
Propiedad Valor predeterminado Descripción
rank.fusion.engine.enabled false true hace que la fusión la realice el motor de búsqueda.
rank.fusion.combination.technique rrf Cómo se combinan las puntuaciones: rrf, arithmetic_mean, geometric_mean o harmonic_mean. Con rrf, se utiliza rank.fusion.rank_constant como la constante k, lo que da la misma fórmula que cuando la fusión la realiza Fess.
rank.fusion.normalization.technique min_max Cómo se normalizan las puntuaciones antes de combinarlas: min_max, l2 o z_score. No se utiliza con rrf.
rank.fusion.combination.weights (vacío) Peso de cada buscador, como pares nombre:peso separados por comas (por ejemplo, default:0.7,semantic_chunk:0.3). Cada peso debe estar entre 0.0 y 1.0, los pesos deben sumar 1.0 y deben indicarse todos los buscadores que participan en la fusión. Si está vacío, los buscadores tienen el mismo peso. Un valor que no cumple estas reglas se notifica con un registro ERROR, y esa búsqueda la fusiona Fess.
rank.fusion.pagination_depth 1000 Cuántos resultados aporta cada buscador a la fusión por shard. Limita la profundidad hasta la que un cliente puede paginar y el conjunto de documentos que se fusionan: una búsqueda fusionada en el motor de búsqueda puede paginar como máximo esta cantidad de resultados. El valor enviado al motor de búsqueda nunca supera indexer.max.result.window.size.

Nota

La normalización z_score solo puede combinarse con arithmetic_mean. Se trata de una restricción del plugin neural-search. Si se combina con geometric_mean o harmonic_mean, Fess rechaza la combinación, escribe un registro ERROR que nombra ambas configuraciones y fusiona esa búsqueda por sí mismo.

En los siguientes casos el motor de búsqueda no realiza la fusión, y Fess fusiona los resultados en su lugar.

  • Una búsqueda que incluye parámetros de búsqueda avanzada (as.*)

  • Una búsqueda que especifica un criterio de ordenación, una búsqueda por geolocalización o una búsqueda de documentos similares. Estas omiten por completo la búsqueda semántica, por lo que los resultados provienen solo de la búsqueda por palabras clave (consulte Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial)).

  • Un valor de rank.fusion.combination.weights que no cumple las reglas anteriores

  • La normalización z_score combinada con geometric_mean o harmonic_mean (un registro ERROR nombra ambas configuraciones)

  • El motor de búsqueda no puede ejecutar solicitudes fusionadas en absoluto: no reconoce la consulta hybrid o el procesador del pipeline de búsqueda, por ejemplo porque falta el plugin neural-search o es demasiado antiguo. Se escribe un registro WARN en cada una de esas búsquedas, y la siguiente búsqueda vuelve a pedírselo al motor de búsqueda, de modo que la fusión en el motor se reanuda por sí sola, sin reiniciar Fess, en cuanto se instala o actualiza el plugin.

Cualquier otro fallo de una solicitud fusionada (una consulta no válida, un índice cerrado, un fallo de shard, etc.) se notifica solo para esa búsqueda, igual que sin la fusión en el motor de búsqueda, y la siguiente búsqueda vuelve a fusionarla el motor de búsqueda.

Tenga en cuenta lo siguiente cuando la fusión la realiza el motor de búsqueda.

  • rank.fusion.timeout no se aplica. El embedding de la consulta se calcula de forma síncrona antes de enviar la solicitud de búsqueda, por lo que un proveedor de embeddings lento o que no responde retrasa la búsqueda hasta el tiempo de espera propio del proveedor (por ejemplo, content_chunker.embedding.ollama.timeout). Si el proveedor reintenta, los reintentos se suman a ese tiempo. Por ejemplo, el proveedor integrado opensearch repite una espera de content_chunker.embedding.opensearch.timeout (60000 ms de forma predeterminada) hasta content_chunker.embedding.opensearch.retry.max (3 de forma predeterminada) veces, por lo que un proveedor que no responde puede retrasar una búsqueda 180 segundos de forma predeterminada, más las esperas entre reintentos.

  • rank.fusion.window_size y rank.fusion.threads solo se utilizan cuando la fusión la realiza Fess.

  • Una búsqueda fusionada puede paginar como máximo rank.fusion.pagination_depth resultados, porque el motor de búsqueda solo fusiona los primeros rank.fusion.pagination_depth resultados de cada buscador por shard. El número de páginas, el enlace a la página siguiente y los números de página se detienen ahí, y una página cuya posición inicial (start) es rank.fusion.pagination_depth o mayor se rechaza con el mismo error que, en cualquier otra búsqueda, una página más allá de index.max_result_window (en la API de búsqueda v2, HTTP 400 con invalid_request). Una página que empieza después del último resultado fusionado pero dentro de ese límite (por ejemplo, desde un enlace obsoleto) se devuelve vacía. Las búsquedas que no se fusionan en el motor de búsqueda pueden paginar hasta index.max_result_window, como antes.

  • El número total de resultados es exacto mientras sea inferior a rank.fusion.pagination_depth. A partir de ese valor, el motor de búsqueda puede contar menos resultados de los que realmente coinciden, por lo que el número se informa como un límite inferior (en la API de búsqueda, record_count_relation es GREATER_THAN_OR_EQUAL_TO).

  • Aumentar rank.fusion.pagination_depth permite paginar más a fondo, pero cada búsqueda fusionada recopila esa cantidad de resultados por buscador y shard, por lo que todas las búsquedas se vuelven más lentas, no solo las páginas profundas.

  • El k de la consulta knn del buscador semántico (el número de vecinos por shard) es content_chunker.search.knn.k. Una búsqueda vectorial devuelve vecinos aunque su similitud sea baja, por lo que, sin content_chunker.search.min_score, el número total de resultados incluye esos resultados vectoriales y, en un índice pequeño, puede abarcar la mayoría de los documentos que el usuario puede ver. Establezca content_chunker.search.min_score para acotarlo (consulte Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial)).

  • El campo searcher se añade a los resultados como de costumbre, pero rf_score no.

Integración con la búsqueda híbrida

Rank Fusion es particularmente eficaz para la búsqueda híbrida, que combina la búsqueda por palabras clave y la búsqueda semántica. Para usar la búsqueda semántica, configure la función de chunking de contenido y establezca content_chunker.search.enabled=true.

Advertencia

Los ajustes content_chunker.*, como content_chunker.enabled y content_chunker.search.enabled, no pertenecen a fess_config.properties, sino que son propiedades del sistema. Escríbalos en conf/system.properties o especifíquelos como opción JVM, por ejemplo -Dfess.system.content_chunker.search.enabled=true. Si los escribe en fess_config.properties, no tendrán ningún efecto. Además, content_chunker.search.enabled solo se evalúa al iniciar, por lo que tras habilitarlo es necesario reiniciar Fess.

Consulte Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial) para más detalles.

Verificación de los resultados de la fusión

Puede comprobar si Rank Fusion está funcionando realmente mediante los dos campos siguientes, que se añaden a los resultados de búsqueda.

Campo Contenido
searcher Array con los nombres de los buscadores que recuperaron el documento (por ejemplo, ["default", "semantic_chunk"]). Si contiene ambos, significa que el documento coincidió tanto en la búsqueda por palabras clave como en la búsqueda semántica.
rf_score Puntuación fusionada calculada mediante RRF. El nombre del campo se puede cambiar con rank.fusion.score_field.

Ambos son valores que se añaden dinámicamente en el momento de la búsqueda y no se almacenan en el índice. Además, de forma predeterminada no se incluyen en la respuesta de /api/v2/search, por lo que, para consultarlos, establezca lo siguiente en fess_config.properties y reinicie Fess:

query.additional.api.response.fields=rf_score,searcher

Nota

query.additional.api.response.fields es un ajuste que añade elementos a la lista de permitidos de los campos que pueden incluirse en la respuesta de la API de búsqueda v2. No añada campos de control de acceso como role o virtual_host, ya que la información de control de acceso quedaría expuesta en la respuesta de la API de búsqueda.

Impacto en el número de resultados

Cuando Rank Fusion lo realiza Fess, el número total de resultados devuelto no es sin más el del buscador principal (el buscador default registrado en primer lugar), sino que se corrige de la siguiente manera:

Número total de resultados = número total del buscador principal + valor de corrección

El valor de corrección es el número de documentos que, estando entre los window_size ÷ 2 primeros resultados tras la fusión, no estaban entre los window_size ÷ 2 primeros resultados del buscador principal. Es decir, el número aumenta en la cantidad de documentos que solo encontró la búsqueda semántica. Por ello, para una misma consulta el número de resultados puede variar según si la búsqueda híbrida está habilitada o no.

Tenga en cuenta que, si el número total de resultados del buscador principal se devuelve como un valor aproximado (un límite inferior), esta corrección no se aplica. Los recuentos de facetas (etiquetas, etc.) también se toman tal cual de los resultados del buscador principal.

Cuando la fusión la realiza el motor de búsqueda (consulte Rank Fusion en el motor de búsqueda), el número total de resultados y los recuentos de facetas abarcan la unión de los resultados de la búsqueda por palabras clave y de la búsqueda semántica. Cada buscador aporta como máximo rank.fusion.pagination_depth resultados por shard, y el buscador semántico está limitado además por content_chunker.search.knn.k. Por ello, una misma consulta informa un número total de resultados y unos recuentos de facetas distintos según rank.fusion.engine.enabled, y en un índice pequeño suelen ser mayores cuando la fusión la realiza el motor de búsqueda, porque la búsqueda semántica aporta sus resultados.

Ejemplos de uso

Búsqueda híbrida básica

  1. Calcular la puntuación BM25 con la búsqueda por palabras clave

  2. Calcular la similitud vectorial con la búsqueda semántica

  3. Fusionar ambos resultados con RRF

  4. Generar el ranking final

Flujo de búsqueda:

User Query
    ↓
┌──────────────────┬──────────────────┐
│  Keyword Search  │ Semantic Search  │
│    (BM25)        │  (Vector)        │
└────────┬─────────┴────────┬─────────┘
         ↓                  ↓
     Rank List 1        Rank List 2
         └────────┬─────────┘
                  ↓
          Rank Fusion (RRF)
                  ↓
          Final Ranking

Consideraciones de rendimiento

Uso de memoria

  • El uso de memoria aumenta porque se retienen múltiples resultados de búsqueda.

  • Use rank.fusion.window_size para limitar el número máximo de resultados a fusionar. El buscador principal (el buscador default en primer lugar) recupera hasta window_size resultados, mientras que cada uno de los demás buscadores recupera window_size ÷ número de buscadores resultados (número de buscadores es el total incluyendo el buscador principal, y la división se trunca).

  • Por ejemplo, con dos buscadores (default y semantic_chunk) y window_size=200, el buscador principal recupera 200 resultados y el buscador semántico 100, por lo que se retienen como máximo 300 documentos.

# Tamaño de ventana para la fusión
rank.fusion.window_size=200

Advertencia

rank.fusion.window_size no puede ser inferior a paging.search.page.max.size × 2. Si paging.search.page.max.size tiene su valor predeterminado 100, el límite inferior es 200, que coincide con el valor predeterminado de rank.fusion.window_size. Es decir, en la configuración predeterminada no es posible establecer window_size por debajo de su valor predeterminado. Si establece un valor menor, se registra una advertencia WARN al iniciar y el valor se eleva a 200. Para reducirlo realmente es necesario reducir antes paging.search.page.max.size, pero esto también reduce el número máximo de resultados que se pueden solicitar por página desde la pantalla de búsqueda y la API.

Tiempo de procesamiento

  • El tiempo de respuesta aumenta porque se ejecutan múltiples búsquedas.

  • Use rank.fusion.threads para establecer el número de hilos para la ejecución paralela.

# Número de hilos para ejecución paralela
# (si es 0 o menos, availableProcessors × 3 ÷ 2 + 1)
rank.fusion.threads=-1

Nota

Cuando la fusión la realiza Fess, se espera a los buscadores distintos del principal un máximo de rank.fusion.timeout milisegundos (predeterminado 10000). Un buscador que no ha respondido en ese plazo queda excluido de esa búsqueda, y los resultados se marcan como parciales (tiempo de espera agotado). Al buscador principal siempre se le espera. Con 0 o menos, se espera sin límite. Este ajuste no se aplica cuando la fusión la realiza el motor de búsqueda (consulte Rank Fusion en el motor de búsqueda).

Comportamiento cuando falla un buscador

Si alguno de los buscadores falla con una excepción, sus resultados se tratan como vacíos: se registra una advertencia WARN y la fusión continúa únicamente con los resultados de los buscadores restantes. La propia solicitud de búsqueda no produce ningún error.

Sin embargo, los errores de sintaxis de consulta (InvalidQueryException) y la superación del límite de paginación (ResultOffsetExceededException) son excepciones a esta regla: estos se devuelven como errores tal cual. Además, en las páginas profundas en las que no se realiza la fusión (donde posición de inicio × 2 es mayor o igual que rank.fusion.window_size), una excepción producida en el buscador principal se devuelve tal cual como error de la solicitud de búsqueda.

El buscador semántico devuelve resultados vacíos cuando no puede conectarse al proveedor de embeddings o cuando falla el procesamiento de los embeddings. También en este caso no se produce ningún error, y solo se obtienen los resultados de la búsqueda por palabras clave.

Solución de problemas

Los resultados de búsqueda difieren de lo esperado

Síntoma: Los resultados tras Rank Fusion difieren de lo esperado

Verificaciones:

  1. Verificar el campo searcher (consulte «Verificación de los resultados de la fusión»). Si todos los documentos muestran únicamente ["default"], el buscador semántico no está devolviendo resultados.

  2. Comprobar si la búsqueda semántica se está omitiendo. En las consultas que contienen sintaxis de búsqueda como frases o comodines, así como en las búsquedas con ordenación, la búsqueda por ubicación y la búsqueda de documentos similares, el buscador semántico no devuelve resultados y solo se obtienen los de la búsqueda por palabras clave. Consulte Búsqueda Semántica (Chunking de Contenido + Búsqueda Vectorial) para más detalles sobre las condiciones de omisión.

  3. Verificar los resultados de cada tipo de búsqueda individualmente

  4. Ajustar el valor de rank.fusion.rank_constant

  5. En páginas profundas (donde posición de inicio × 2 es mayor o igual que rank.fusion.window_size; de forma predeterminada, a partir del resultado 101), la fusión no se realiza y solo se utiliza el buscador principal. Si desea resultados fusionados en más páginas, aumente rank.fusion.window_size. Cuando la fusión la realiza el motor de búsqueda, este límite no existe: se fusionan todas las páginas, hasta rank.fusion.pagination_depth resultados (consulte Rank Fusion en el motor de búsqueda).

La búsqueda es lenta

Síntoma: La búsqueda se vuelve lenta cuando Rank Fusion está habilitado

Soluciones:

  1. Ajustar rank.fusion.threads:

    rank.fusion.threads=4
    
  2. Reducir rank.fusion.window_size. Sin embargo, no puede quedar por debajo de su límite inferior (paging.search.page.max.size × 2), por lo que en la configuración predeterminada se deben establecer los dos ajustes siguientes conjuntamente:

    paging.search.page.max.size=50
    rank.fusion.window_size=100
    

    Tenga en cuenta que el número máximo de resultados que se pueden solicitar por página también se reduce. Tras aplicar la configuración es necesario reiniciar.

  3. Cuando la fusión la realiza el motor de búsqueda, reducir rank.fusion.pagination_depth. Esto también reduce la profundidad hasta la que se pueden paginar los resultados fusionados. Tras cambiarlo es necesario reiniciar.

Memoria insuficiente

Síntoma: Se produce OutOfMemoryError

Soluciones:

  1. Reducir rank.fusion.window_size siguiendo el mismo procedimiento que en «La búsqueda es lenta»

  2. Aumentar el tamaño del heap de JVM

Referencia