- El gestor de paquetes de Python uv muestra una velocidad de instalación más de 10 veces superior a la de pip, y esto no se debe simplemente a que esté escrito en Rust, sino a decisiones de diseño
- La clave que hizo posible esa velocidad son los estándares de metadatos estáticos (PEP 518, 517, 621, 658), que permiten identificar dependencias sin ejecutar código
- uv eliminó con decisión las funciones heredadas que mantiene pip (.egg, pip.conf, instalación en el Python del sistema, etc.), con lo que elimina rutas de código innecesarias
- Lo que aporta Rust incluye deserialización zero-copy, concurrencia sin locks y una estructura de binario único, pero eso representa solo una parte de la mejora total de velocidad
- En conjunto, el caso de uv muestra que los metadatos estandarizados y la eliminación de compatibilidad innecesaria son la clave de la innovación en rendimiento
Los estándares que hicieron posible la velocidad de uv
- La lentitud de pip no se debe a un problema de implementación, sino a que su antigua estructura basada en
setup.py obligaba a ejecutar código para conocer las dependencias
- Ejecutar
setup.py requería instalar dependencias de compilación, lo que provocaba un "problema del huevo y la gallina"
- Durante la instalación se producían ejecuciones de código arbitrario y fallos repetidos, lo que reducía la velocidad de instalación
- PEP 518 (2016) introdujo
pyproject.toml, lo que permitió declarar dependencias de compilación sin ejecutar código
- PEP 517 (2017) separó el frontend y el backend de compilación, eliminando la necesidad de que pip entendiera los detalles internos de setuptools
- PEP 621 (2020) estandarizó la tabla
[project], por lo que ahora se pueden verificar dependencias solo parseando TOML
- PEP 658 (2022) incorporó metadatos de paquetes directamente en la Simple Repository API, permitiendo obtener información de dependencias sin descargar wheels
- PyPI aplicó PEP 658 en mayo de 2023, y uv se lanzó en febrero de 2024, apareciendo como la primera herramienta en aprovechar por completo la nueva infraestructura estándar
- Igual que Rust con Cargo o JavaScript con npm, el ecosistema de Python también está migrando ahora a un empaquetado basado en metadatos estáticos
Las funciones que uv eliminó
- La velocidad de uv proviene de eliminar funciones innecesarias
- Sin soporte para
.egg: pip todavía lo procesa, pero uv lo excluye por completo
- Ignora
pip.conf: omite archivos de configuración, variables de entorno y toda la lógica de herencia
- Compilación de bytecode desactivada: no convierte
.py a .pyc, reduciendo el tiempo de instalación
- Entornos virtuales obligatorios: al no instalar directamente en el Python del sistema, elimina validaciones de permisos y código de seguridad
- Cumplimiento estricto de la especificación: rechaza paquetes incorrectos y reduce la lógica de manejo de excepciones
- Ignora el límite superior de
requires-python: al ignorar restricciones defensivas como python<4.0, reduce el backtracking en la resolución de dependencias
- Prioridad al primer índice: si encuentra el paquete en el primero de varios índices, se detiene de inmediato, lo que evita ataques de confusión de dependencias y reduce solicitudes de red
- Todos estos puntos son ejemplos de rutas de código que pip sí tiene que ejecutar y que uv elimina
Optimizaciones posibles sin Rust
- Una parte importante de la velocidad de uv proviene de optimizaciones de diseño independientes del lenguaje
- Usa solicitudes HTTP Range para descargar solo parcialmente el directorio central de los archivos wheel, evitando descargar el archivo completo
- Descargas en paralelo para obtener varios paquetes al mismo tiempo
- Usa caché global y hardlinks para que, aunque el mismo paquete se instale en varios entornos virtuales, no haya consumo adicional de espacio en disco
- Resolución independiente de Python: parsea directamente TOML y metadatos de wheel, y solo ejecuta Python cuando existe únicamente
setup.py
- Usa el algoritmo de resolución de dependencias PubGrub, más rápido que el enfoque de backtracking de pip y con explicaciones de error más claras
Lo que Rust sí aportó en la práctica
- Rust cumple un papel importante en ciertas optimizaciones de bajo nivel
- Deserialización zero-copy basada en rkyv, que usa directamente los datos en caché sin copiarlos
- Estructuras de concurrencia sin locks para implementar acceso paralelo de forma segura
- Sin inicialización del intérprete: uv es un binario estático único, por lo que elimina el costo de crear procesos de Python que sí tiene pip
- Representación comprimida de versiones como enteros
u64, lo que acelera comparaciones y operaciones de hash
- Estos elementos mejoran el rendimiento, pero no son la causa principal del aumento total de velocidad
Lección clave
- La velocidad de uv no se debe a Rust, sino a todo lo que decidió no hacer
- La estandarización de PEP 518·517·621·658 sentó la base para una gestión rápida de paquetes, y uv la materializó con eliminación de legado y supuestos modernos
- pip también podría implementar descargas en paralelo, caché global y resolución basada en metadatos, pero mantener 15 años de compatibilidad hacia atrás es un obstáculo
- Como resultado, pip está condenado a ser lento, y solo las herramientas que parten de nuevas premisas pueden lograr mejoras fundamentales de velocidad
- La lección para otros gestores de paquetes es que los metadatos estáticos, la exploración de dependencias sin ejecutar código y una estructura resoluble de antemano son imprescindibles
- Cargo y npm ya adoptan este enfoque, y los ecosistemas que necesitan ejecutar código para verificar dependencias son intrínsecamente lentos
1 comentarios
Comentarios de Hacker News
Creo que este artículo explicó bastante bien el rendimiento de uv desde varios ángulos
Que esté escrito en Rust ayuda, pero lo que jugó un papel mucho más grande fueron los esfuerzos de estandarización de la última década para sacar al ecosistema de Python de la dependencia de
setup.pyRust también puede elegirse por una razón parecida: eleva el nivel de capacidad de su comunidad
Pueden rediseñar mejor al volver a recorrer los errores del pasado, y a eso se suman las ventajas propias de Rust, como una especie de “golpe doble”
Coincido con la idea de que “uv no es rápido por estar hecho en Rust, sino porque hay muchas cosas que no hace”
Aun así, me parece pronto afirmar las causas de la velocidad sin benchmarks
El impacto de PEP 518, 517, 621 y 658 es grande, pero dudo cuánto aportó realmente la eliminación de compatibilidad
Tampoco se trata qué efecto tuvo la elección del lenguaje sobre la optimización
También es interesante que el parser de TOML de Cargo sea mucho más rápido que el de Python
En la práctica TOML solo se lee al momento de compilar, así que no pesa tanto, pero la adopción de wheel sí contribuyó a mejorar la velocidad
Referencias relacionadas: setup.py deprecated, wheels are faster
La deserialización zero-copy con
rkyvno es una técnica exclusiva de RustTambién es posible en lenguajes de bajo nivel como C/C++
Lo de “no hay arranque del intérprete” va en el mismo sentido
El contenido del artículo es bueno, pero el estilo pulido por LLM se siente demasiado artificial
Quizá algún día llegue una época en la que haya que restaurar a algo humano los textos arruinados por LLM
Parece ser un experto en seguridad de la cadena de suministro, pero ese texto también se sentía afectado por el estilo vago típico de los LLM
Me da pena que prompts fijos estén haciendo que todos los textos suenen parecidos, como si todo internet hablara con la misma voz
No entiendo del todo el entusiasmo por la velocidad de uv
Probablemente la mayoría de quienes usan Python ni siquiera pondrían la velocidad de instalación de paquetes entre sus 10 principales preocupaciones
Yo también uso Python todos los días y no siento tanto impacto
poetrytomaba entre 5 y 30 minutosY si fallaba, había que esperar otros 30 minutos; uv sí fue una experiencia realmente cómoda
pip installocupó una parte importante del tiempo de desplieguePasé mucho tiempo tratando de acelerarlo con caché
poetry installtarda 2 minutos yuv synctermina en segundosAhorrarse 2 minutos en cada CI tiene un efecto acumulado grande
uvx sometool, la creación del entorno virtual y la instalación de dependencias toman apenas unos segundos, y eso cambia por completo el flujo de trabajoAhora me cuesta volver a proyectos sin uv
Algunas técnicas de optimización de velocidad de uv parecen transferibles a pip
Por ejemplo: descargas en paralelo, generación diferida de
.pyc, ignorar eggs, chequeo de versión, etc.Pero uv maneja tan bien los venv que probablemente ya ni valga la pena tocar pip
Al final, el punto es que “no es solo gracias a Rust”, así que todavía hay margen para que pip sea más rápido
Los programadores que eligen un lenguaje rápido muchas veces ya tienen una mentalidad de optimización de rendimiento
Más que el lenguaje en sí, esa actitud suele definir el rendimiento
Es interesante por qué uv ignora el límite superior
python<4.0La mayoría de los paquetes lo configuró a la defensiva por miedo a que se rompieran en Python 4, cuando en realidad probablemente funcionarían bien
Esos límites superiores intentaban resolver problemas hipotéticos más que problemas reales
Restricciones como
python<3.0siguen siendo importantes, así que en esos casos sí habría que bloquearNo es casualidad que PEP 658 se implementara en 2023 y uv apareciera en 2024
El ecosistema ya estaba listo, y por eso una herramienta como uv se volvió posible
Pero me da curiosidad por qué los mantenedores de paquetes aceptaron este cambio
Incluso entre quienes estaban conformes con
setup.py, ¿qué los motivó a pasarse a pyproject.toml?setup.pyya les resultaba incómodo a muchas personasPor ejemplo, ni siquiera Requests sigue siendo todavía totalmente compatible con PEP 517/518/621
Después de año y medio, la versión minor seguía retrasada, y mientras tanto también hubo problemas de compilación
Aun así, sigue siendo una duda por qué pip no aprovecha eso lo suficiente
La frase “los caminos de código que no existen no tienen que esperar” no es precisa
Solo el código que no se ejecuta realmente ahorra tiempo
Por ejemplo, aunque no haya soporte para
.egg, si ya es un formato obsoleto, eso no necesariamente afecta la velocidadHabría estado mejor ver datos cuantitativos sobre cuánto tiempo ahorró cada punto
Aun así, en general es un artículo bien ordenado