Быстрое и эффективное обновление

Я разрабатываю обновление для игрового клиента, так что игрокам не придется загружать весь клиент, когда он будет обновлен.

Теперь создание стандартного обновления не очень сложно, но оно довольно медленное с большими файлами.

Клиент составляет около 1,5 ГБ несжатого и имеет ~ 250 файлов. Файлы на сервере обновлений gzip-сжаты и загружаются через HTTP.

Программа обновления работает следующим образом: получить список патчей с сервера → сравнить файлы из списка патчей с локальными файлами (crc32/filesize) → если отсутствует/неправильный файлize/hash - это не то же самое → скачать gzip сжатый файл с сервера → распаковать файл

Самые трудоемкие части обновления: генерирование хэшей crc32 для каждого файла/загрузка больших файлов

Я подумал о некоторых вещах, которые могли бы ускорить его:

  • Rsync-like diff updater - это ускорит загрузку, поскольку оно будет получать только часть файла, а не просто загружать весь файл. Это было бы полезно, потому что обычно обновление клиента не влияет на многие части больших файлов. Но я предполагаю, что для этого будет какой-то перебор.

  • Улучшение сжатия - Gzip экономит около ~ 200 МБ, когда клиент сжат. Я не пробовал использовать некоторые другие методы сжатия, но я предполагаю, что bzip2, lzma или еще сэкономит больше места и ускорит загрузку. По иронии судьбы они замедляли декомпрессию файлов.

  • Другой метод проверки файлов. На данный момент я использую реализацию С# crc32, потому что она была быстрее, чем стандартная реализация С# md5. Есть ли более быстрые алгоритмы, которые могут определить, является ли файл одинаковым?

  • Система версий - на самом деле это ничего не ускорит, но программа обновления не должна будет вычислять все хэши. И с дополнительной "ремонтной" -функцией он может просто проверять все файлы против фактической версии, если пользователь хочет.

Какое из этих решений я должен использовать или есть какие-либо подходы, которые я не перечислял, которые я должен использовать вместо этого?

Ответ 1

Сжатие отдельных файлов

Вместо загрузки всего пакета вы можете загружать только новые или измененные файлы.

Хранить хеши как на клиенте, так и на сервере

Предварительно вычисляя ваши хэши, вы можете сэкономить много времени. Ваш шаг сравнения хэша становится отличием одного файла, который хранит хэши для всех ваших файлов. Это функционально то же самое, что и система управления версиями, но "версии" немного сложнее обмануть. Пользователю легко открыть простой текстовый файл версий и установить номера в следующую версию, чтобы пропустить патчи. Если вы хотите предотвратить такое поведение, хеши немного более безопасны.

Распараллеливать

После выполнения diff вашего хэш файла вы можете отправить свой запрос на сервер для списка файлов, которые необходимо загрузить. Затем ваш загрузчик может последовательно передавать каждый файл, и по мере их получения дополнительные потоки могут распаковывать и перемещать загруженные файлы.

Ответ 2

Я делал это в прошлом, и это действительно зависит от конкретной реализации и желаемых параметров. Некоторые вещи, которые мы сделали:

  • Разрешить пользователю выбирать предпочтение "полной" проверки для обновления каждый раз. Если нет какой-либо озабоченности в плане безопасности, нет никакой причины для сравнения каждого хеша.
  • При полном сканировании сначала выполняйте свои хэши как в текстовом документе, так и в XML-документе, если это необходимо. Я нашел, что XML может быть полезен для сопоставления с сервером только для получения необходимых файлов.
  • Если это сработает для вас, вы всегда можете выполнять хэши только по "именам" файлов, а не по содержимому. Что я имею в виду? Hash the Directory.GetFiles() результат по сравнению с ожидаемым результатом, чтобы увидеть, нужно ли вам больше погружаться в отсутствующие файлы. Это, очевидно, не будет работать, если вы обеспокоены фальсификацией файлов и на самом деле нуждаетесь в хеше содержимого.

Ответ 3

Другими параметрами являются хранение дельтах того, что было изменено вместо полных файлов. Затем вы вытаскиваете только то, что нужно, чтобы "обновить" файл до новой версии. Посмотрите http://xdelta.org/