dotnet/runtime

System.IO.Compression: ZipArchive loads entire file in memory on .Dispose

Open

#1,543 opened on Sep 13, 2016

View on GitHub
 (6 comments) (10 reactions) (0 assignees)C# (5,445 forks)batch import
area-System.IO.Compressionenhancementhelp wantedtenet-performance

Repository metrics

Stars
 (17,886 stars)
PR merge metrics
 (Avg merge 12d 11h) (661 merged PRs in 30d)

Description

When you open a ZipArchive in Update mode, the entire zip file will be loaded in memory when the .Dispose method is invoked.

This is because .Dipose calls .WriteFile, which:

  • Calls LoadLocalHeaderExtraFieldAndCompressedBytesIfNeeded for all entries, which loads the compressed data into memory for those entries
  • Sets the size of the .zip archive to 0, by calling _archiveStream.SetLength(0);
  • Writes out all entries one by one.

As a result:

  • A lot of memory is used, the compressed data for each entry is loaded into memory
  • A lot of unnecessary disk I/O is performed, because all entries are written out again, even if they were not modified.

An alternative may be to incrementally update the zip archive, and only update entries which changes.

Contributor guide