es

Almacén direccionable por contenido

Cómo PCPM ahorra 70-90% de disco en soluciones multi-proyecto.

El almacén direccionable por contenido es la parte de PCPM que hace el trabajo pesado. Es la razón por la que un monorepo de 30 proyectos cabe en unos pocos cientos de megabytes en lugar de decenas de gigabytes.

Qué significa “direccionable por contenido”

Un almacén direccionable por contenido es una disposición de directorios donde la ruta de un fichero se deriva de su contenido. La receta habitual es:

  1. Calcular un hash de los bytes del fichero — sha256, en el caso de PCPM.
  2. Almacenar el fichero en <raíz>/<2-primeros-chars>/<resto-chars>/<nombre-fichero>.
  3. Para buscar un fichero, hasheas los bytes que tienes, derivas la ruta y lo lees.

La propiedad que obtienes gratis es la desduplicación: si dos ficheros tienen los mismos bytes, tienen el mismo hash, y tienen la misma ruta. El segundo no necesita una copia separada en disco.

PCPM lo usa para los ficheros .nupkg (archivos inmutables) y para los contenidos extraídos del paquete (lib/, runtimes/, etc.). La ruta del store en Windows es %LOCALAPPDATA%\pcpm\store; en Linux y macOS es ~/.local/share/pcpm/store.

El layout en disco

%LOCALAPPDATA%\pcpm\store\
  v1\
    8f\                            # 2 primeros chars del sha256
      8f3a4b5c6d7e…\               # resto de chars del sha256
        pkg.nupkg                  # el archivo inmutable
        extracted\
          newtonsoft.json\
            13.0.3\
              lib\
                net6.0\…           # contenidos lib/net6.0 del paquete
                netstandard2.0\…

Cada .nupkg distinto de tu grafo de dependencias se almacena exactamente una vez, sin importar cuántos proyectos dependan de él.

Una vez que un paquete está en el store, pcpm install lo hace visible para dotnet restore haciendo un hardlink del mismo en ~/.nuget/packages. Un hardlink es una entrada de directorio que apunta al mismo inodo en disco que otra. Dos rutas, un fichero, cero disco extra.

NTFS (Windows), APFS (macOS) y ext4 (Linux) soportan hardlinks, y PCPM los usa en los dos primeros. En Linux, donde la combinación estándar ext4 + libcs también se lleva bien con hardlinks, PCPM usa hardlinks. El fallback — cuando el origen y el destino están en volúmenes distintos, o cuando el sistema de ficheros no soporta hardlinks — es una copia de fichero normal.

El hardlink es invisible para la aplicación: dotnet restore ve un árbol ~/.nuget/packages/<id>/<version>/ normal. No hay nada personalizado en el lado del consumidor.

¿Cuánto disco ahorras?

Cifras aproximadas de un monorepo de 30 proyectos con 200 paquetes únicos:

LayoutDisco usado
~/.nuget/packages por defecto (sin PCPM)8.2 GB
PCPM, primera ejecución4.1 GB
PCPM, tras una restauración limpia4.1 GB
PCPM, tras añadir un proyecto que usa los mismos paquetes4.1 GB

El número de PCPM no crece con el número de proyectos. Añadir un proyecto 30 que use los mismos 200 paquetes añade cero bytes al store.

Por qué importa

El disco es la ganancia obvia, pero el beneficio más profundo es la velocidad de I/O. Restaurar un proyecto contra un store caliente está limitado por operaciones de metadatos: dotnet restore leyendo el lockfile, MSBuild recorriendo el grafo del proyecto, y el runtime abriendo los metadatos del ensamblado. El paso de copia-desde-red desaparece. En un runner de CI limpio con caché caliente, el wall-clock de pcpm install más dotnet restore está dominado por el segundo, no por el primero.

¿Qué hay en el lockfile?

pcpm.lock registra la versión resuelta y el hash de contenido de cada paquete. Esto es lo que hace que el store sea un “store” y no solo una caché: dado un lockfile, PCPM puede verificar que los bytes de cada entrada están presentes en el store, o descargar exactamente los que faltan.

El formato es un documento JSON estable:

{
  "version": 1,
  "packages": [
    {
      "id": "newtonsoft.json",
      "version": "13.0.3",
      "hash": "sha256:8f3a4b5c6d7e…",
      "dependencies": {  }
    }
  ]
}

pcpm ci valida los hashes contra el store y falla si falta algo. pcpm install re-resuelve el grafo y actualiza el lockfile; los hashes se reescriben solo si un bump transitivo cambió el contenido de un paquete.

Véase también