Руководство по переходу на Lore VCS: решение проблемы «стоимостных бомб» Git LFS и конфликтов ассетов Unreal Engine
По мере роста проекта Git LFS превращается в катастрофу. Исправление нескольких строк исходного кода происходит мгновенно, но как только начинают добавляться гигабайтные арт-ассеты, при каждом коммите «песочные часы» крутятся десятками секунд. Из-за неэффективной структуры LFS, которая копирует и накапливает огромные файлы целиком, объем хранилища быстро превышает терабайты, а счета за пропускную способность показывают пугающие цифры.
Lore, выпущенная Epic Games с открытым исходным кодом, ставит работу с бинарными файлами во главу угла. Благодаря методу FastCDC, который разбивает файлы на блоки и устраняет дубликаты, система значительно сокращает размер пакетов и потребление трафика. Мы подготовили практическое руководство по миграции и оптимизации Lore, которое можно применить немедленно, даже если в вашей небольшой команде нет выделенных DevOps-специалистов.
1. Поэтапная миграция с Git LFS на Lore
Нет необходимости отказываться от истории коммитов исходного кода, накопленной в существующем Git-репозитории. Гибридная стратегия выглядит наиболее реалистично: оставить легкий код в Git, а тяжелые бинарные ассеты перенести в репозиторий Lore.
Приведенный ниже скрипт определяет список файлов, отслеживаемых Git LFS, создает симметричную структуру каталогов и переносит данные в Lore без потерь, сверяя SHA-256 хеши копий.
`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] Инициализация репозитория Lore и привязка к серверу..."
if [ ! -d "LOREREPODIR"];thenmkdir−p"LORE_REPO_DIR"
cd "LOREREPODIR"lorerepositorycreate"LORE_SERVER_URL"
else
cd "$LORE_REPO_DIR"
fi
echo "[2/5] Сбор списка файлов, отслеживаемых Git LFS..."
cd "GITREPODIR"LFSFILES=(git lfs ls-files -n | grep -E ".(uasset|umap|fbx|png|psd)$" || true)
if [ -z "$LFS_FILES" ]; then
echo "Нет файлов LFS для переноса."
exit 0
fi
echo "[3/5] Копирование файлов и создание манифеста для проверки..."
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] Отключение Git LFS и стейджинг в 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] Проверка целостности данных..."
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 "Обнаружен поврежденный файл: file"migrationerrors=((migration_errors + 1))
fi
fi
done < .lore_migration_manifest
if [ $migration_errors -eq 0 ]; then
echo "Миграция завершена. Все данные восстановлены со 100% целостностью."
rm .lore_migration_manifest
else
echo "Ошибка проверки: $migration_errors файлов имеют проблемы с целостностью."
exit 1
fi
fi
`
Откройте терминал и сохраните код выше в файл migrate.sh. После предоставления прав на выполнение командой chmod +x migrate.sh, отредактируйте переменные в соответствии с вашими локальными путями и запустите скрипт.
После завершения этой операции объем используемого удаленного облачного хранилища LFS немедленно сократится. Согласно опыту внедрения Epic Games, использование технологии дедупликации на уровне блоков позволяет снизить расходы на инфраструктуру на 50%.
2. Применение On-demand hydration в CI/CD пайплайнах
Пайплайны, которые при каждом цикле сборки заново скачивают сотни гигабайт игровых ассетов, являются главными врагами сетевых адаптеров и дискового ввода-вывода. Для ускорения времени сборки Lore поддерживает отложенное восстановление (On-demand Hydration) на основе виртуальной файловой системы.
На этапе первоначального клонирования копируются только цепочки метаданных и дерево каталогов в виде «оболочки», а необходимые бинарные фрагменты динамически стримятся и записываются на диск только тогда, когда компилятор считывает реальные ассеты в процессе подготовки (Cook).
`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: Подготовка 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 через Shared Cache
run: |
lore clone \
--bare \
--use-shared-store \
--shared-store-path "${{ env.SHARED_STORE_PATH }}" \
"${{ env.LORE_SERVER }}" \
"${{ env.WORKSPACE_PATH }}"
- name: Исключение ненужных исходников синематиков через фильтр представлений
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: Синхронизация на локальный диск только необходимых фрагментов
run: |
cd "${{ env.WORKSPACE_PATH }}"
lore sync
- name: Запуск Unreal Engine Cooker
run: |
cd "${{ env.WORKSPACE_PATH }}"
./RunUAT.sh BuildCookRun \
-project="$(pwd)/GameProject.uproject" \
-platform=Win64 \
-clientconfig=Development \
-cook -stage -pak -archive
`
Наилучший эффект достигается при наличии на сборочном сервере постоянного кэш-хранилища, такого как /var/lib/lore_shared_chunk_store. Сначала выполняется команда lore clone --bare для быстрой загрузки информации об индексах, затем в файле фильтра .lore/view оставляются только необходимые пути, и запускается lore sync. При такой структуре объем трафика, передаваемого на сборочные узлы, снижается более чем на 85%, а общее время сборки сокращается в среднем на 30%.
3. Предотвращение конфликтов ассетов с помощью системы блокировки файлов
Бинарные ассеты Unreal Engine, такие как .uasset или файлы уровней (maps), невозможно автоматически объединить в главной ветке, как обычный текстовый код. Если два художника одновременно изменят один и тот же ассет, возникнет ситуация, при которой тот, кто отправил изменения позже, перезапишет работу предшественника или приведет к нарушению целостности истории.
Lore предоставляет функцию блокировки (Lock), которая обеспечивает исключительное управление на основе неизменяемого реестра удаленного сервера.
`bash
Запрос права на единоличное редактирование конкретного файла 3D-модели персонажа
lore lock acquire Content/Characters/HeroMesh.uasset --branch main
Проверка состояния блокировки ресурсов в указанной папке
lore lock status Content/Characters/HeroMesh.uasset
Поиск всех файлов, заблокированных определенным пользователем в удаленном репозитории
lore lock query --branch main --owner developer_artist_03
Завершение работы, отправка изменений и снятие блокировки
lore lock release Content/Characters/HeroMesh.uasset --branch main
`
Необходимо установить правило, согласно которому художники перед работой с файлом должны занять блокировку командой lore lock acquire. После завершения редактирования, успешного коммита и отправки (push) на сервер, блокировка снимается с помощью lore lock release, передавая право доступа следующему специалисту.
Если геймдизайнеры и художники некомфортно чувствуют себя в терминале, вы можете настроить интеграцию с графическими инструментами вроде Anchorpoint, чтобы команды блокировки выполнялись простым нажатием правой кнопки мыши по пути к файлу.
4. Руководство по настройке кэша в зависимости от характеристик оборудования
Чтобы избежать узких мест при вводе-выводе файлов, необходимо адаптировать настройки клиента под спецификации рабочей среды.
Настройка локального клиента в зависимости от мощности ПК
- Высокопроизводительные системы (NVMe SSD, 32GB RAM и более, многоядерный CPU): Допускаются прямые вычисления на основе маппинга памяти через механизм отображения виртуальной памяти ОС. Для устранения задержек синхронизации увеличивается количество параллельных потоков загрузки и продлевается срок хранения кэша на диске.
- Бюджетные и рабочие станции художников (SATA SSD или HDD, 16GB RAM и менее): Метод маппинга памяти отключается для предотвращения сбоев движка из-за нехватки ОЗУ. Включаются флаги
--direct-file-write и --direct-file-io для прямой записи на диск, а интервал планировщика сборки мусора увеличивается, чтобы избежать внезапных блокировок диска во время работы.
Анализ производительности при выборе алгоритма сжатия
Согласно протоколу принятия архитектурных решений Lore (ADR-00016), установка стандарта Zstandard Level 6 в качестве базового движка сжатия является наиболее сбалансированной с точки зрения эффективности.
| Тип алгоритма сжатия |
Итоговое сжатие данных (%) |
Скорость сжатия (MiB/s) |
Скорость распаковки (MiB/s) |
Портативность и особенности |
| LZ4 Default |
47.6% |
718.7 |
2494.5 |
Быстро, но большой расход места в хранилище |
| Zstd Level 1 |
34.5% |
602.0 |
1363.1 |
Разумный компромисс между скоростью и размером |
| Zstd Level 6 (рекомендуется) |
28.9% |
136.5 |
1284.9 |
Лучшая эффективность обработки при экономии места |
| Oodle Kraken 3 (Fast) |
28.2% |
95.6 |
1413.1 |
Требует проприетарную библиотеку Oodle от Epic Games |
| Oodle Kraken 6 (старый стандарт) |
23.9% |
2.2 |
1312.6 |
Скорость сильно падает при переносе гигабайтных данных |
Часто используемый ранее Oodle Kraken Level 6 был основной причиной увеличения времени ожидания коммита перед уходом художников домой, так как скорость обработки сжатия при сериализации на бэкенде падала до 2.2 MiB/s.
Напротив, Zstd Level 6 обеспечивает коэффициент сжатия, близкий к Oodle Kraken 6, но при этом скорость сжатия локальных блоков составляет 136.5 MiB/s, что примерно в 62 раза быстрее. Если у вас много зарубежных филиалов или сотрудников на удаленке, что создает проблемы с пропускной способностью, рекомендуем рассмотреть конфигурацию двухуровневой серверной топологии с настройкой прокси-серверов Edge-кэширования внутри локальной сети.