Guide de migration vers Lore VCS pour résoudre les problèmes de coûts de Git LFS et les conflits d'assets Unreal
Lorsque les projets grandissent, Git LFS devient un désastre. Modifier quelques lignes de code source se fait en un clin d'œil, mais dès que des assets artistiques de plusieurs gigaoctets entrent dans la danse, le sablier tourne pendant des dizaines de secondes à chaque commit. En raison de la structure inefficace de LFS qui copie et accumule des fichiers volumineux, la capacité de stockage dépasse rapidement le téraoctet et les factures de bande passante affichent des chiffres effrayants.
Lore, publié en open source par Epic Games, traite les fichiers binaires en priorité. Il utilise la méthode FastCDC, qui divise les fichiers en blocs pour éliminer les doublons, réduisant ainsi radicalement la taille des paquets et la bande passante nécessaire au transfert. Nous avons résumé ici les méthodes pratiques de migration et d'optimisation vers Lore, applicables immédiatement même pour les petites équipes sans ingénieurs DevOps dédiés.
1. Migration progressive de Git LFS vers Lore
Il n'est pas nécessaire d'abandonner l'historique des commits du code source accumulé dans votre dépôt Git existant. Une stratégie hybride consistant à laisser le code léger sur Git et à séparer uniquement les lourds assets binaires vers un dépôt Lore est une approche réaliste.
Le script ci-dessous identifie la liste des fichiers suivis par Git LFS, crée une structure de répertoire symétrique et transfère les données vers Lore sans perte en comparant les hash SHA-256 des copies.
`bash
#!/usr/bin/env bash
set -euo pipefail
GIT_REPO_DIR="HOME/projects/my−game−git"LOREREPODIR="HOME/projects/my-game-lore"
LORE_SERVER_URL="lore://127.0.0.1:41337/my-project"
echo "[1/5] Initialisation du dépôt Lore et liaison distante..."
if [ ! -d "LOREREPODIR"];thenmkdir−p"LORE_REPO_DIR"
cd "LOREREPODIR"lorerepositorycreate"LORE_SERVER_URL"
else
cd "$LORE_REPO_DIR"
fi
echo "[2/5] Collecte de la liste des fichiers suivis par Git LFS..."
cd "GITREPODIR"LFSFILES=(git lfs ls-files -n | grep -E ".(uasset|umap|fbx|png|psd)$" || true)
if [ -z "$LFS_FILES" ]; then
echo "Aucun fichier LFS à migrer."
exit 0
fi
echo "[3/5] Copie des fichiers et création du manifeste de vérification..."
echo "LFSFILES"∣whileread−rfilepath;doif[−f"filepath" ]; then
dest_dir="LOREREPODIR/(dirname "filepath")"mkdir−p"dest_dir"
cp -p "filepath""LORE_REPO_DIR/filepath"sourcehash=(openssl dgst -sha256 "$filepath" | awk '{print 2}')
echo "filepath:sourcehash">>"LORE_REPO_DIR/.lore_migration_manifest"
fi
done
echo "[4/5] Suppression de Git LFS et staging vers Lore..."
cd "GITREPODIR"echo"LFS_FILES" | while read -r filepath; do
git rm --cached "$filepath"
done
sed -i.bak -E 's/filter=lfs diff=lfs merge=lfs//g' .gitattributes
cd "LOREREPODIR"echo"LFS_FILES" | while read -r filepath; do
lore stage "$filepath"
done
lore commit -m "Migration: Transfer heavy assets from Git LFS to Lore"
lore push
echo "[5/5] Vérification de l'intégrité des données..."
lore repository verify state
lore repository verify fragment
if [ -f ".lore_migration_manifest" ]; then
migration_errors=0
while IFS=":" read -r file sha; do
if [ -f "file"];thencurrenthash=(openssl dgst -sha256 "$file" | awk '{print 2}')
if [ "sha" != "$current_hash" ]; then
echo "Fichier corrompu détecté: file"migrationerrors=((migration_errors + 1))
fi
fi
done < .lore_migration_manifest
if [ $migration_errors -eq 0 ]; then
echo "Migration terminée. Toutes les données ont été récupérées avec une intégrité à 100%."
rm .lore_migration_manifest
else
echo "Échec de la vérification: $migration_errors fichiers présentent des problèmes d'intégrité."
exit 1
fi
fi
`
Ouvrez un terminal et enregistrez le contenu ci-dessus sous le nom migrate.sh. Après avoir donné les droits d'exécution avec la commande chmod +x migrate.sh, il suffit de modifier les variables selon vos chemins locaux et de l'exécuter.
Une fois cette opération effectuée, l'utilisation du stockage LFS cloud distant diminue immédiatement. Selon les cas d'utilisation internes d'Epic Games, cette technologie de déduplication au niveau des blocs permet de réduire les coûts de maintenance de l'infrastructure de près de 50%.
2. Application de l'hydratation à la demande dans le pipeline CI/CD
Les pipelines qui retéléchargent des centaines de gigaoctets d'assets de jeu complets à chaque cycle de build sont la cause principale de la saturation des cartes réseau et des entrées/sorties disque. Lore prend en charge l'hydratation à la demande (On-demand Hydration) basée sur un système de fichiers virtuel pour réduire les temps de build.
Lors de l'étape initiale de clonage, seule la structure de la chaîne de métadonnées et l'arborescence des répertoires sont répliquées sous forme de coque. Lorsque le compilateur lit les assets réels pendant le processus de « Cook », seuls les blocs binaires nécessaires sont dynamiquement diffusés et écrits sur le disque.
`yaml
name: Game Project On-Demand Production Build
on:
push:
branches: [ release-candidate ]
env:
LORE_SERVER: "lore://10.0.1.50:41337/game-depot"
SHARED_STORE_PATH: "/var/lib/lore_shared_chunk_store"
WORKSPACE_PATH: "game_build_workspace"
jobs:
assemble-assets:
runs-on: self-hosted
steps:
- name: Préparation du Persistent Shared Store
run: |
if [ ! -d "env.SHAREDSTOREPATH"];thensudomkdir−p"{{ env.SHARED_STORE_PATH }}"
sudo chmod 777 "env.SHAREDSTOREPATH"loreshared−storecreate"{{ env.SHARED_STORE_PATH }}"
fi
- name: Sparse Bare Clone via Shared Cache
run: |
lore clone \
--bare \
--use-shared-store \
--shared-store-path "${{ env.SHARED_STORE_PATH }}" \
"${{ env.LORE_SERVER }}" \
"${{ env.WORKSPACE_PATH }}"
- name: Exclusion des sources cinématiques inutiles via les filtres de vue
run: |
cd "${{ env.WORKSPACE_PATH }}"
echo "+ /SourceCode/" > .lore/view
echo "+ /Config/" >> .lore/view
echo "+ /Content/Core_Assets/" >> .lore/view
echo "- /Content/Cinematic_RAW/" >> .lore/view
- name: Synchronisation uniquement des blocs nécessaires sur le disque local
run: |
cd "${{ env.WORKSPACE_PATH }}"
lore sync
- name: Exécution du Unreal Engine Cooker
run: |
cd "${{ env.WORKSPACE_PATH }}"
./RunUAT.sh BuildCookRun \
-project="$(pwd)/GameProject.uproject" \
-platform=Win64 \
-clientconfig=Development \
-cook -stage -pak -archive
`
Si vous préparez un stockage cache permanent comme /var/lib/lore_shared_chunk_store sur le serveur dédié aux builds, l'effet est maximisé. Après avoir rapidement récupéré les informations d'index avec la commande lore clone --bare, conservez uniquement les chemins nécessaires dans le fichier de filtrage .lore/view et lancez lore sync. Une fois cette structure en place, le trafic envoyé aux nœuds de build diminue de plus de 85 % par rapport à la normale. Le temps de build total est réduit d'environ 30 % en moyenne.
3. Prévention des conflits d'assets grâce au système de verrouillage de fichiers
Les assets binaires tels que les fichiers .uasset d'Unreal Engine ou les cartes de niveau ne peuvent pas être fusionnés automatiquement sur la branche principale comme le code texte. Si deux artistes modifient le même asset simultanément, le dernier à pousser écrase le travail du premier ou provoque des incohérences dans la chronologie.
Lore fournit directement une fonction de verrouillage (Lock) qui effectue un contrôle exclusif basé sur le grand livre immuable du serveur distant.
`bash
Demande de droit d'édition exclusif pour un fichier de modèle de personnage binaire spécifique
lore lock acquire Content/Characters/HeroMesh.uasset --branch main
Vérification de l'état de possession du verrou pour les ressources sous un dossier spécifique
lore lock status Content/Characters/HeroMesh.uasset
Recherche de tous les fichiers verrouillés par un utilisateur spécifique sur le dépôt distant
lore lock query --branch main --owner developer_artist_03
Libération des droits après avoir terminé le travail et poussé les modifications
lore lock release Content/Characters/HeroMesh.uasset --branch main
`
Vous devez établir des règles pour obliger les artistes à acquérir un verrou avec la commande lore lock acquire avant de toucher à un fichier. Une fois la modification terminée et le commit et le push correctement reflétés sur le distant, utilisez lore lock release pour libérer le verrou et le transmettre au prochain utilisateur.
Si les game designers et les artistes ne sont pas à l'aise avec les commandes de terminal, vous pouvez intégrer ces chemins dans des outils GUI de bureau comme Anchorpoint, afin que ces commandes de verrouillage puissent être exécutées simplement par un clic droit de la souris.
4. Guide de réglage du cache selon les spécifications matérielles
Vous devez ajuster les paramètres du client en fonction des spécifications de votre environnement de travail pour éviter les goulots d'étranglement des entrées/sorties de fichiers.
Réglage du client local par spécifications PC
- Systèmes haute performance (NVMe SSD, 32 Go RAM ou plus, CPU multi-cœurs) : Autorise les opérations directes basées sur le mappage mémoire via des techniques de mappage de mémoire virtuelle de l'OS. Pour éliminer les délais de synchronisation, augmentez le nombre maximal de threads de téléchargement en parallèle et prolongez la durée de conservation du cache disque.
- Systèmes grand public et artistiques (SATA SSD ou HDD, 16 Go RAM ou moins) : Désactivez la méthode de mappage mémoire pour éviter les crashs de moteur dus à l'épuisement de la mémoire. Activez les drapeaux
--direct-file-write et --direct-file-io pour écrire directement sur le disque, et augmentez l'intervalle de planification du garbage collection pour éviter les phénomènes d'accaparement inattendu du disque pendant le travail.
Analyse des performances selon le choix de l'algorithme de compression
Selon les résultats de la réunion de décision d'architecture de Lore (ADR-00016), définir la spécification Zstandard Level 6 comme moteur de compression par défaut offre le meilleur équilibre en termes d'efficacité.
| Type d'algorithme de compression |
Taux de compression final (%) |
Vitesse d'opération de compression (MiB/s) |
Vitesse de décompression (MiB/s) |
Portabilité et caractéristiques |
| LZ4 Default |
47.6% |
718.7 |
2494.5 |
Vitesse élevée mais gaspillage important d'espace de stockage |
| Zstd Level 1 |
34.5% |
602.0 |
1363.1 |
Bon compromis entre vitesse et conservation de l'espace |
| Zstd Level 6 (recommandé) |
28.9% |
136.5 |
1284.9 |
Maintient la meilleure efficacité de traitement par rapport à l'économie d'espace |
| Oodle Kraken 3 (Fast) |
28.2% |
95.6 |
1413.1 |
Nécessite la bibliothèque exclusive Oodle d'Epic Games |
| Oodle Kraken 6 (défaut précédent) |
23.9% |
2.2 |
1312.6 |
La vitesse diminue considérablement lors des transferts de plusieurs gigaoctets |
L'algorithme Oodle Kraken Level 6, fréquemment utilisé auparavant, voyait sa vitesse de traitement de compression descendre à 2,2 MiB par seconde lors du processus de sérialisation backend, ce qui était la cause principale de l'augmentation du temps d'attente avant les commits des artistes avant de quitter le travail.
En revanche, Zstd Level 6 offre un taux de compression proche de celui d'Oodle Kraken 6 tout en ayant une vitesse de compression des blocs de morceaux locaux de 136,5 MiB/s, soit environ 62 fois plus rapide. Si vous avez de nombreux bureaux à l'étranger ou des employés en télétravail avec des interférences de bande passante importantes, envisagez de configurer une topologie de serveur à deux couches avec des nœuds de cache proxy en périphérie au sein du réseau local.