Translate

domingo, 17 de mayo de 2026

Particionado de Tablas en MySQL: Qué es, tipos y cuándo usarlo




El particionado en MySQL es una técnica que permite dividir una tabla grande en partes más pequeñas (particiones), manteniendo la ilusión de que sigue siendo una única tabla.


Esto es clave cuando trabajamos con:

  • Grandes volúmenes de datos (millones o billones de filas)
  • Consultas que pueden beneficiarse de “leer menos datos”
  • Mantenimiento más eficiente (archivar, borrar, etc.)


Imaginemos una tabla de logs:

logs(id, fecha, usuario, accion)


Con millones de registros, consultas como:

SELECT * FROM logs WHERE fecha >= '2026-01-01';


terminan escaneando demasiados datos.


Con particionado, MySQL puede hacer partition pruning:

  • Solo accede a las particiones relevantes
  • Reduce I/O y mejora performance


Tipos de particionado en MySQL


 RANGE (por rango)

Ideal para fechas o valores ordenados.


CREATE TABLE logs (

  id INT,

  fecha DATE,

  mensaje VARCHAR(255)

)

PARTITION BY RANGE (YEAR(fecha)) (

  PARTITION p2023 VALUES LESS THAN (2024),

  PARTITION p2024 VALUES LESS THAN (2025),

  PARTITION pFuture VALUES LESS THAN MAXVALUE

);


Muy usado para:

  • Logs
  • Eventos
  • Datos históricos


LIST (por valores específicos)


CREATE TABLE usuarios (

  id INT,

  pais VARCHAR(50)

)

PARTITION BY LIST COLUMNS(pais) (

  PARTITION p_latam VALUES IN ('Argentina', 'Brasil'),

  PARTITION p_europa VALUES IN ('España', 'Francia')

);


Útil cuando tenés categorías bien definidas.


HASH (distribución uniforme)


CREATE TABLE pedidos (

  id INT,

  cliente_id INT

)

PARTITION BY HASH(cliente_id)

PARTITIONS 4;


MySQL distribuye automáticamente los datos.


KEY (similar a HASH pero interno)


CREATE TABLE sesiones (

  id INT,

  usuario_id INT

)

PARTITION BY KEY(usuario_id)

PARTITIONS 4;


Usa funciones hash internas de MySQL.


Limitaciones importantes

Antes de usar particionado, hay que tener en cuenta:

  • Todas las claves primarias deben incluir la columna de partición
  • No todas las engines soportan particionado (InnoDB sí)
  • No reemplaza índices (se complementan)
  • Puede complicar el diseño si no se usa bien


Cuándo usar particionado:

✔️ Tablas muy grandes (millones de filas)

✔️ Consultas filtradas por la columna de partición

✔️ Necesidad de borrar datos antiguos fácilmente


Cuándo NO usar particionado:

❌ Tablas pequeñas

❌ Consultas que no usan la columna de partición

❌ Como reemplazo de índices


miércoles, 13 de mayo de 2026

Kotlin 2.4.0


La versión 2.4.0 de Kotlin sigue consolidando muchas características que venían evolucionando desde releases anteriores.

Más que agregar “una gran feature”, esta versión termina de estabilizar varias piezas importantes del ecosistema.

El nuevo compilador K2 dejó de sentirse “experimental” y pasó a ser la base real del futuro de Kotlin.


¿Qué aporta?

  • Compilaciones más rápidas
  • Mejor análisis de tipos
  • Mensajes de error más claros
  • Infraestructura más simple para futuras features


K2 no es solamente una optimización, es prácticamente una reescritura del compilador.


Los Context Parameters siguen evolucionando y acercan a Kotlin a ideas similares a:

  • implicits de Scala
  • type classes funcionales
  • dependency injection implícita


Ejemplo:


context(Logger)

fun processOrder() {

    log("Processing order")

}


Esto permite escribir APIs mucho más declarativas.


Kotlin sigue empujando fuerte el desarrollo multiplataforma; en 2.4.0 hay mejoras importantes en:

  • compilación incremental
  • interoperabilidad con iOS
  • performance de Kotlin/Native
  • sharing de código entre plataformas


El garbage collector y el manejo de memoria continúan mejorando para Kotlin/Native. 


Esto impacta directamente en:

  • apps iOS
  • aplicaciones embebidas
  • performance general


Históricamente Kotlin/Native era uno de los puntos más débiles del ecosistema. Las últimas versiones muestran una mejora enorme.


También hay mejoras en:

  • IntelliJ IDEA
  • Gradle
  • debugging
  • análisis estático
  • tiempos de indexing


Muchas veces estas mejoras no aparecen en los titulares, pero son las que realmente cambian la experiencia diaria.


Lo más interesante de Kotlin 2.4.0 quizás no sea una feature puntual.

Es que muchas ideas que antes parecían experimentales ahora empiezan a sentirse “normales”:

  • K2
  • Multiplatform
  • Native
  • Context Parameters


Kotlin está entrando en una etapa mucho más madura del lenguaje.


domingo, 10 de mayo de 2026

Cómo usar EXPLAIN en MySQL para optimizar tus consultas


EXPLAIN te muestra el plan de ejecución de una consulta SQL.


En otras palabras, responde preguntas como:

  • ¿Qué tablas se recorren?
  • ¿En qué orden?
  • ¿Se están usando índices?
  • ¿Cuántas filas se estiman procesar?


EXPLAIN 

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Salida típica:


| id | select_type | table | type | possible_keys | key  | rows | Extra       |

| -- | ----------- | ----- | ---- | ------------- | ---- | ---- | ----------- |

| 1  | SIMPLE      | libro | ALL  | idx_titulo    | NULL | 1000 | Using where |


Qué podemos saber con esto, sin ser un erudito: 

type = ALL → Full Table Scan ❌

key = NULL → no está usando ningún índice


Esto significa que MySQL recorre toda la tabla.


Veamos agregar un indice: 

CREATE INDEX idx_titulo ON libro(titulo);


Volvemos a ejecutar:

EXPLAIN 

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Nueva salida:

| type | key        | rows |

| ---- | ---------- | ---- |

| ref  | idx_titulo | 1    |


✅ Ahora sí:

  • Usa índice
  • Escanea pocas filas
  • Mucho más eficiente


Veamos las columnas clave de EXPLAIN

type (MUY importante)

Indica cómo accede a la tabla:


| type   | Significado             |

| ------ | ----------------------- |

| ALL    | Full scan (malo) ❌      |

| index  | Scan de índice completo |

| ref    | Uso de índice 👍        |

| eq_ref | Uso óptimo 🚀           |

| const  | Mejor caso posible 💎   |


key

  • Índice que se está utilizando
  • Si es `NULL` → problema 😬


rows

  • Cantidad estimada de filas a procesar
  • Mientras menor, mejor


Extra

Algunos valores importantes:


| Extra           | Significado             |

| --------------- | ----------------------- |

| Using where     | Filtro aplicado         |

| Using index     | Index-only scan 🚀      |

| Using temporary | Tabla temporal ⚠️       |

| Using filesort  | Ordenamiento costoso ⚠️ |


Veamos un ejemplo con JOIN


EXPLAIN

SELECT l.titulo, a.nombre

FROM libro l

JOIN autor a ON l.autor_id = a.id

WHERE a.nombre = 'Cervantes';


👉 Cosas a observar:

  • Orden de las tablas
  • Índices en autor.nombre y libro.autor_id
  • Tipo de join (`ref`, `eq_ref`, etc.)


Problema típico: filesort

EXPLAIN

SELECT * 

FROM libro

ORDER BY fecha_publicacion;


Si ves: Using filesort


MySQL está ordenando en memoria (o peor, en disco)

Solución:

CREATE INDEX idx_fecha ON libro(fecha_publicacion);


EXPLAIN ANALYZE (MySQL 8+)


Mysql agrega el analyze que es propio de mysql, por lo menos no conozco en otras bases. (si conocen me dicen en los comentarios) Analyze corre la query y nos tira data más precisa. Tema que hay que esperar a que ejecute la query. 


EXPLAIN ANALYZE

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Que diferencia tiene con explain clave:


| EXPLAIN             | EXPLAIN ANALYZE |

| Estimaciones         | Ejecución real  |

| No ejecuta query   | Ejecuta query   |

| Rápido                   | Más preciso     |


Ejemplo:


-> Index lookup on libro using idx_titulo

(cost=0.35 rows=1)

(actual time=0.01..0.02 rows=1 loops=1)


Como conclusión, EXPLAIN no es opcional: es una herramienta esencial.


Te permite:

  • Entender cómo piensa MySQL
  • Detectar problemas de performance
  • Validar el uso de índices
  • Optimizar queries complejas


Un buen flujo de trabajo sería:


1. Escribir la query

2. Ejecutar EXPLAIN

3. Detectar problemas

4. Agregar índices / refactorizar

5. Validar con EXPLAIN ANALYZE


Nunca andar tirando índices a lo loco o trabajar a tientas. 

martes, 5 de mayo de 2026

Crear un mini lenguaje que compile a LLVM IR (paso a paso)


En el post anterior vimos qué es LLVM y por qué cambió la forma de construir compiladores.


Ahora vamos a lo interesante: crear un mini lenguaje propio y compilarlo a LLVM IR

Vamos a construir un lenguaje súper simple que permita esto:

sum(10, 20)


Y lo transforme en LLVM IR listo para compilar.

Nuestro “compilador” va a tener:

  • Parser (muy básico)
  • AST (árbol)
  • Generador de LLVM IR


Paso 1: Definir el lenguaje


Nuestro lenguaje soporta:

Función: sum(a, b)

Números enteros


Ejemplo válido:

sum(4, 5)


Paso 2: Representar el AST

En pseudocódigo:

java id="y0yqg3"

interface Expr {}


class Number implements Expr {

    int value;

}


class Sum implements Expr {

    Expr left;

    Expr right;

}


Paso 3: Parser (ultra simple)


Para simplificar, parseamos a mano:

java id="x7p0a1"

Expr parse(String input) {

    // sum(10,20)

    String inside = input.substring(4, input.length() - 1);

    String[] parts = inside.split(",");


    return new Sum(

        new Number(Integer.parseInt(parts[0])),

        new Number(Integer.parseInt(parts[1]))

    );

}


Sí, es naive, pero suficiente para entender el flujo


Paso 4: Generar LLVM IR

Acá está la magia 💣


java id="l6c0qw"

String generate(Expr expr) {

    if (expr instanceof Sum s) {

        return """

        define i32 @main() {

            %a = add i32 %d, %d

            ret i32 %a

        }

        """.formatted(

            ((Number)s.left).value,

            ((Number)s.right).value

        );

    }

    throw new RuntimeException("Unsupported");

}


Resultado

Entrada:

sum(10, 20)


Salida:

llvm id="0a8v8l"

define i32 @main() {

  %a = add i32 10, 20

  ret i32 %a

}


Ya es LLVM IR válido


Paso 5: Ejecutarlo

Guardás el archivo como main.ll y usás:


bash id="3e7twz"

lli main.ll


o lo compilás con:


bash id="z4c9yb"

llc main.ll


Aunque el ejemplo es simple, reproduce el flujo real:

1. Texto → AST

2. AST → IR

3. IR → código ejecutable


Exactamente lo que hacen lenguajes como Rust o compiladores como Clang

Lo difícil NO es generar código máquina.

Lo difícil es definir bien el lenguaje y su semántica.


LLVM te resuelve:

  • optimización
  • portabilidad
  • generación de código



SELECT FOR UPDATE en MySQL


Cuando trabajamos con sistemas concurrentes (varios usuarios o procesos accediendo a los mismos datos), uno de los problemas más comunes es la inconsistencia de datos.


Ahí es donde entra en juego una herramienta clave de MySQL:

SELECT ... FOR UPDATE


Esta sentencia que:

1. Lee filas de una tabla

2. Las bloquea para escritura

3. Hasta que la transacción finalice (COMMIT o ROLLBACK)


Esto garantiza que nadie más pueda modificar esas filas mientras vos trabajás con ellas.


Veamos un ejemplo: 


START TRANSACTION;


SELECT * 

FROM cuentas 

WHERE id = 1

FOR UPDATE;


UPDATE cuentas 

SET saldo = saldo - 100 

WHERE id = 1;


COMMIT;


En este caso:

Se bloquea la fila con id = 1

Nadie más puede modificarla hasta el COMMIT


¿Por qué es importante? Imaginá este escenario sin bloqueo:

1. Proceso A lee saldo = 100

2. Proceso B lee saldo = 100

3. Ambos descuentan 50

4. Resultado final: ❌ saldo = 50 (incorrecto)


Con FOR UPDATE:

1. Proceso A bloquea la fila

2. Proceso B espera

3. Se ejecuta A completamente

4. Luego B trabaja con datos actualizados

✔️ Resultado correcto


¿Cómo funciona internamente?

Ojo, Solo funciona con motores como InnoDB

Usa bloqueo a nivel de fila (row-level locking)

Otros SELECT FOR UPDATE:

  • Quedan esperando
  • Otros SELECT normales, pueden leer (dependiendo del isolation level)


Para no cagarla podemos usar SKIP LOCKED


SELECT * FROM tareas

WHERE estado = 'pendiente'

FOR UPDATE SKIP LOCKED;


✔️ Ignora filas bloqueadas

✔️ Ideal para workers concurrentes

Ojo, no sé si es tan aplicable, si queremos modificar todas las filas queremos modificar todas, no solo las no loqueadas.  


NOWAIT


SELECT * FROM cuentas

WHERE id = 1

FOR UPDATE NOWAIT;


❌ Falla inmediatamente si la fila está bloqueada

✔️ Útil cuando no querés esperar


Cosas a tener en cuenta:

  • Siempre usar dentro de una transacción
  • Puede generar deadlocks
  • Usar índices para evitar locks innecesarios
  • No funciona bien con tablas sin InnoDB



VisualVM vs .NET Tooling


¿Por qué en Java hay “una herramienta” y en .NET hay muchas?

Cuando venís del mundo Java, es muy común preguntarte: ¿Dónde está el VisualVM de .NET?


La respuesta corta es: no existe uno solo.

La respuesta interesante es: no existe por diseño.


En el ecosistema Java, herramientas como VisualVM se volvieron estándar porque la JVM expone un modelo bastante unificado:

  • JMX (Java Management Extensions)
  • Heap dumps
  • Thread dumps
  • GC metrics


Todo eso se puede consumir desde una sola herramienta.

¿Qué ofrece VisualVM?

  • Profiling de CPU
  • Análisis de memoria (heap)
  • Monitoreo de threads
  • Plugins

Resultado: una experiencia “tipo panel de control” donde ves todo.


En .NET moderno, el enfoque es distinto. En lugar de una herramienta central, tenés un ecosistema de herramientas especializadas.


Visual Studio (Profiler integrado)


Es lo más parecido a VisualVM:

  • CPU profiling
  • Memory profiling
  • Timeline
  • UI completa


Es la opción más “todo en uno”, pero:

❌ Es pesada

❌ No siempre usable en producción


CLI tools (el corazón real de .NET)


.NET adopta un enfoque más tipo Unix:

  • dotnet-counters → métricas en vivo
  • dotnet-trace → trazas de ejecución
  • dotnet-dump → dumps
  • dotnet-gcdump → GC
  • dotnet-stack → threads


Cada herramienta hace una cosa… pero la hace muy bien.

Esto permite:

  • Usarlas en producción
  • Automatizarlas
  • Integrarlas con pipelines


PerfView

  • Muy potente
  • Usado internamente por Microsoft
  • Basado en ETW (Event Tracing for Windows)


❌ Curva de aprendizaje alta

❌ UX poco amigable


Herramientas comerciales

  • dotTrace
  • ANTS Profiler
  • .NET Memory Profiler


Estas sí se sienten más como VisualVM:

✔️ UI amigable

✔️ Experiencia integrada

❌ Son pagas



sábado, 2 de mayo de 2026

Records vs Project Valhalla en Java


Java viene evolucionando fuerte en dos direcciones:

  • Java Records → escribir menos código
  • Project Valhalla → ejecutar más rápido


A primera vista parecen competir… pero en realidad se complementan.

  • Usá Records → claridad, simplicidad, APIs
  • Usá Valhalla (Value Types) → rendimiento, memoria
  • Usá ambos → lo ideal en sistemas complejos


Records: el rey de la simplicidad

record User(String name, int age) {}


✔ Inmutables

✔ Menos boilerplate

✔ equals, hashCode, toString automáticos


¿Cuándo usar Records?

DTOs / APIs


record ProductDTO(String name, double price) {}


Perfecto para:

  • REST APIs
  • serialización JSON
  • comunicación entre capas


Modelos simples

record Money(double amount, String currency) {}


Cuando te importa más la legibilidad que el rendimiento


Lógica de negocio

  • servicios
  • respuestas intermedias


El overhead de objetos no suele ser un problema


Limitación clave, un record:

  • vive en el heap
  • tiene identidad
  • usa referencias


Valhalla: el rey del rendimiento

Ejemplo conceptual:


value class Point {

    int x, y;

}



✔ Sin identidad

✔ Sin overhead de objeto

✔ Datos contiguos en memoria


¿Cuándo usar Value Types?

Grandes volúmenes de datos


value class Point {

    int x, y;

}


List<Point>


Mucho más eficiente que objetos tradicionales


Simulaciones

  • físicas
  • partículas
  • coordenadas


Miles o millones de instancias


Alto rendimiento

  • trading
  • analytics
  • cálculos intensivos


Menos GC = mejor performance


¿Qué cambia realmente?

Sin Valhalla:

List<Point> // lista de referencias


Con Valhalla:

[x1, y1, x2, y2, x3, y3]


Datos planos → mejor cache → más velocidad


Cuándo NO usar Valhalla

  • Entidades (`User`, `Order`)
  • Objetos con identidad
  • Integración con frameworks clásicos


Si necesitás identidad → no es value type

Lo mejor: combinarlos

Acá está la clave real 👇


Caso 1: Record + Value Type


value class Point {

    int x, y;

}


record Circle(Point center, double radius) {}


Tenés:

API clara (record)

datos eficientes (value)


Caso 2: separación por capas


// API

record PointDTO(int x, int y) {}


// Core

value class Point {

    int x, y;

}


Separás:

  • interfaz → legible
  • core → performante


Caso 3: colecciones grandes


value class Price {

    double amount;

}


List<Price>


Sin boxing → sin referencias → 🔥


Futuro: value records

Se viene algo así:

value record Point(int x, int y) {}


Combina:

  • simplicidad (record)
  • eficiencia (value type)


Conclusión, no es una pelea, es una estrategia:

  • Records → hacen feliz al desarrollador
  • Valhalla → hace feliz a la JVM



Java vs C#: Records y Value Types vs Records y Structs


Durante años, C# llevó ventaja en expresividad y control de memoria.

Pero con Java Records y Project Valhalla, Java está alcanzando… y en algunos aspectos, intentando superarlo.


👉 La pregunta es:

 ¿Java está copiando a C#… o lo está mejorando?


Empecemos por records: empate técnico

En C#

record Person(string Name);


En Java

record Person(String name) {}


✔ Inmutables

✔ Comparación por valor

✔ Menos boilerplate


Conclusión: Empate total — ambos lenguajes convergieron al mismo concepto


Value Types vs Structs

En C#: struct


struct Point {

    public int X;

    public int Y;

}


✔ Tipo por valor

✔ Generalmente en stack

✔ Muy eficiente


Problemas:

Boxing (se convierte en objeto)

Copias implícitas

Comportamiento a veces confuso


 En Java: Value Types (Valhalla)


value class Point {

    int x, y;

}


✔ Sin identidad

✔ Sin overhead de objeto

✔ Puede ser “flattened”


Y lo más importante: No cambia su naturaleza según el contexto


Diferencia clave

C# → tipo híbrido (a veces valor, a veces objeto)

Java → tipo consistente (siempre value type)


Punto para Java (a nivel diseño)


Memoria y layout

  • Stack vs Heap
  • Depende del contexto
  • Puede generar copias innecesarias


 Java (Valhalla)

  • Flattening automático
  • Mejor locality
  • Optimización por la JVM


Ejemplo mental:

En java esto: 

List<Point>


Podría ser:

[x1, y1, x2, y2, x3, y3]


Mucho más eficiente que referencias



Generics (el golpe fuerte de Java)


C#

List<int> 


Soportado desde hace años


Java (hoy)

List<Integer>  (boxing)


Java (con Valhalla)

List<int> ✔

List<Point> ✔


Sin boxing y sin referencias


Este es uno de los mayores avances de Java


Complejidad del modelo mental


En C#

  • class vs struct
  • boxing/unboxing
  • copias implícitas
  • Puede ser confuso


En Java

  • class vs value class
  • sin identidad vs con identidad
  • Más simple conceptualmente


Ecosistema y madurez

C#

✔ Ya está en producción

✔ Frameworks adaptados

✔ Casos reales


 Java (Valhalla)

⚠️ En desarrollo

⚠️ APIs en evolución

⚠️ Falta adopción


Hoy no podés usarlo en producción estándar



¿Quién lo hizo mejor?


Hoy: C#

Porque:

  • ya funciona
  • es estable
  • está probado


 A futuro: Java (posiblemente)

Porque:

  • evita errores históricos (boxing, copias)
  • diseño más consistente
  • mejor integración con la JVM



HTTP 418: I'm a teapot


Si alguna vez viste el código HTTP 418, probablemente pensaste: “¿Esto es real o me están trolleando?”

Spoiler: ambas cosas.


¿Qué significa el error 418?

El código HTTP 418 – "I'm a teapot" es un código de error del cliente (4xx) que, literalmente, significa:

 “Soy una tetera y no puedo hacer café” 


La idea es simple:

El cliente hace una request (ej: “haceme café” ☕)

El servidor responde:

  “No puedo, soy una tetera”


Este código nace en 1998 en el RFC 2324, llamado:

Hyper Text Coffee Pot Control Protocol (HTCPCP)


Sí, un protocolo para controlar cafeteras por internet… y sí, fue publicado el 1 de abril (April Fools). 


La especificación decía cosas como:

  • Método HTTP: BREW
  • Headers para azúcar o leche
  • Y este glorioso error 418

 ¿Es un chiste o es real?

Las dos:

  • Es parte “oficial” del ecosistema HTTP (aunque reservado/no usado formalmente) 
  • No tiene uso serio en producción
  • Pero muchos frameworks lo incluyen igual


Ejemplos reales:

  • Java / Spring: podés devolver 418
  • .NET: `StatusCodes.Status418ImATeapot`
  • Node / Go / Python también lo soportan 


¿Se usa en la vida real?

No debería… pero igual aparece:

  • Easter eggs en APIs
  • Testing de errores
  • Bloqueo de bots
  • Mensajes humorísticos para developers


Incluso hay devs que lo usan para decir: “Tu request es absurda”


Dejo link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/418

Proyecto Valhalla en Java: Tipos de Valor y el Futuro del Rendimiento


Cuando hablamos de la evolución de Java, uno de los proyectos más interesantes (y menos comprendidos) es Project Valhalla.


Si alguna vez sentiste que Java es “pesado” por culpa de los objetos… este proyecto apunta directamente a eso.

Project Valhalla es una iniciativa dentro de OpenJDK cuyo objetivo principal es introducir:

Tipos de valor (Value Types / Inline Classes)

Esto permite representar datos sin el costo de los objetos tradicionales.

En Java, casi todo es un objeto… y eso tiene consecuencias:


Integer x = 10;


Esto implica:

  • Heap allocation
  • Indirección (punteros)
  • Presión sobre el GC
  • Mala localización en memoria (cache-unfriendly)


Incluso algo simple como una lista de enteros:


List<Integer>


Es en realidad:

List -> referencias -> objetos Integer


¿Qué propone Valhalla?


Valhalla introduce un nuevo tipo de clases: Clases inline (value classes)


Ejemplo conceptual:


value class Point {

    int x;

    int y;

}


Esto permite:

  • Sin identidad (no == por referencia)
  • Sin overhead de objeto
  • Layout compacto en memoria


¿Por qué esto es importante?


Mejora de rendimiento

  • Menos uso de heap
  • Mejor uso de CPU cache
  • Menos GC


Estructuras más eficientes


Ejemplo:

List<Point>


Con Valhalla podría ser:

[ x1, y1, x2, y2, x3, y3 ]


👉 En lugar de:

[ ref -> Point, ref -> Point, ref -> Point ]


Conceptos clave de Valhalla


Value Objects

  • No tienen identidad, la identidad esta dada por su propio valor
  • Son inmutables (conceptualmente)
  • Se comparan por contenido


Flattening

El JVM puede “aplanar” estructuras:


class Line {

    Point p1;

    Point p2;

}


En memoria:

[x1, y1, x2, y2]


Specialized Generics (futuro)

Uno de los grandes problemas actuales:

List<int> ❌

List<Integer> ✅ (pero lento)


Valhalla busca permitir:

List<int> ✅


Sin boxing


Cambios importantes a tener en cuenta

  • No todo será automáticamente value type
  • Cambia el modelo mental (menos identidad, más datos)
  • Impacta librerías y frameworks


Project Valhalla aún está en desarrollo activo.

No es parte estable de Java todavía, pero ya hay:

  • Prototipos en OpenJDK
  • Features en incubación


Veamos un ejemplo: 


 Antes (Java actual)


class Complex {

    double re;

    double im;

}


  • Objeto en heap
  • Referencias


Con Valhalla (ideal)


value class Complex {

    double re;

    double im;

}


  • Datos contiguos
  • Sin overhead




Project Valhalla busca algo muy ambicioso:

Combinar lo mejor de OOP con la eficiencia de lenguajes de bajo nivel


En otras palabras:

  • Mantener la simplicidad de Java
  • Reducir el costo de abstracción


En C# tenemos el struct que es muy similar a lo que busca Valhalla.