17 puntos por GN⁺ 2025-12-27 | 1 comentarios | Compartir por WhatsApp
  • 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

 
GN⁺ 2025-12-27
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.py

    • Cuando antes trabajaba en proyectos de Haskell, una ventaja era poder seleccionar una comunidad de expertos más fácilmente que por el lenguaje en sí
      Rust también puede elegirse por una razón parecida: eleva el nivel de capacidad de su comunidad
    • Muchos proyectos de reescritura en Rust se benefician de este efecto halo
      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

    • Comparar una versión antigua de pip con la actual también podría servir como una especie de benchmark
      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 rkyv no es una técnica exclusiva de Rust
    También es posible en lenguajes de bajo nivel como C/C++

    • Aquí entendí “exclusivo de Rust” más bien como “imposible en Python”
      Lo de “no hay arranque del intérprete” va en el mismo sentido
    • Como en Python es difícil implementar zero-copy, sí reconozco que Rust hace esto seguro y fácil
    • Al final, esta discusión es una comparación entre Rust y Python
  • 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

    • El autor también llegó a HN con un artículo sobre SBOM y Lockfile
      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
    • En cambio, otra persona dijo que no notó ningún olor a LLM y le pareció natural
    • Yo ya cierro cualquier texto apenas le siento olor a AI
      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

    • En una empresa anterior, actualizar dependencias con poetry tomaba entre 5 y 30 minutos
      Y si fallaba, había que esperar otros 30 minutos; uv sí fue una experiencia realmente cómoda
    • Llevo más de 20 años usando Python, y pip install ocupó una parte importante del tiempo de despliegue
      Pasé mucho tiempo tratando de acelerarlo con caché
    • En mi app monolítica de trabajo, poetry install tarda 2 minutos y uv sync termina en segundos
      Ahorrarse 2 minutos en cada CI tiene un efecto acumulado grande
    • Incluso al ejecutar 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 trabajo
    • Como usuario veterano de Python, la velocidad de uv me parece un cambio de “calidad de vida
      Ahora 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.0
    La 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

    • No parece que uv ignore todos los límites superiores, sino solo el caso de 4.0
      Restricciones como python<3.0 siguen siendo importantes, así que en esos casos sí habría que bloquear
  • No 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?

    • En realidad, setup.py ya les resultaba incómodo a muchas personas
      Por 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
    • Porque las declaraciones estáticas eran más seguras y mejores para el rendimiento
      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 velocidad
    Habría estado mejor ver datos cuantitativos sobre cuánto tiempo ahorró cada punto
    Aun así, en general es un artículo bien ordenado