Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 453f76d

Browse files
committed
Eliminate closure allocation in ZipArchiveEntry
Also a couple of boolean fields removed from `WrappedStream` and their usage replaced with `_isDisposed` flag.
1 parent 211499a commit 453f76d

File tree

2 files changed

+52
-42
lines changed

2 files changed

+52
-42
lines changed

src/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -643,17 +643,21 @@ private CheckSumAndSizeWriteStream GetDataCompressor(Stream backingStream, Boole
643643
Boolean isIntermediateStream = true;
644644

645645
Boolean leaveCompressorStreamOpenOnClose = leaveBackingStreamOpen && !isIntermediateStream;
646-
CheckSumAndSizeWriteStream checkSumStream =
647-
new CheckSumAndSizeWriteStream(compressorStream, backingStream, leaveCompressorStreamOpenOnClose,
648-
(Int64 initialPosition, Int64 currentPosition, UInt32 checkSum) =>
649-
{
650-
_crc32 = checkSum;
651-
_uncompressedSize = currentPosition;
652-
_compressedSize = backingStream.Position - initialPosition;
646+
var checkSumStream = new CheckSumAndSizeWriteStream(
647+
compressorStream,
648+
backingStream,
649+
leaveCompressorStreamOpenOnClose,
650+
this,
651+
onClose,
652+
(Int64 initialPosition, Int64 currentPosition, UInt32 checkSum, Stream backing, ZipArchiveEntry thisRef, EventHandler closeHandler) =>
653+
{
654+
thisRef._crc32 = checkSum;
655+
thisRef._uncompressedSize = currentPosition;
656+
thisRef._compressedSize = backing.Position - initialPosition;
653657

654-
if (onClose != null)
655-
onClose(this, EventArgs.Empty);
656-
});
658+
if (closeHandler != null)
659+
closeHandler(thisRef, EventArgs.Empty);
660+
});
657661

658662
return checkSumStream;
659663
}
@@ -701,12 +705,13 @@ private Stream OpenInWriteMode()
701705
(object o, EventArgs e) =>
702706
{
703707
//release the archive stream
704-
_archive.ReleaseArchiveStream(this);
705-
_outstandingWriteStream = null;
708+
var entry = (ZipArchiveEntry)o;
709+
entry._archive.ReleaseArchiveStream(entry);
710+
entry._outstandingWriteStream = null;
706711
});
707712
_outstandingWriteStream = new DirectToArchiveWriterStream(crcSizeStream, this);
708713

709-
return new WrappedStream(_outstandingWriteStream, (object o, EventArgs e) => _outstandingWriteStream.Dispose());
714+
return new WrappedStream(baseStream: _outstandingWriteStream, closeBaseStream: true);
710715
}
711716

712717
private Stream OpenInUpdateMode()
@@ -720,14 +725,13 @@ private Stream OpenInUpdateMode()
720725
_currentlyOpenForWrite = true;
721726
//always put it at the beginning for them
722727
UncompressedData.Seek(0, SeekOrigin.Begin);
723-
return new WrappedStream(UncompressedData,
724-
(object o, EventArgs e) =>
728+
return new WrappedStream(UncompressedData, this, thisRef =>
725729
{
726730
//once they close, we know uncompressed length, but still not compressed length
727731
//so we don't fill in any size information
728732
//those fields get figured out when we call GetCompressor as we write it to
729733
//the actual archive
730-
_currentlyOpenForWrite = false;
734+
thisRef._currentlyOpenForWrite = false;
731735
});
732736
}
733737

src/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,34 @@ internal class WrappedStream : Stream
1111
#region fields
1212

1313
private readonly Stream _baseStream;
14-
private readonly EventHandler _onClosed;
15-
private Boolean _canRead, _canWrite, _canSeek;
16-
private Boolean _isDisposed;
1714
private readonly Boolean _closeBaseStream;
1815

16+
// Delegate that will be invoked on stream disposing
17+
private readonly Action<ZipArchiveEntry> _onClosed;
18+
19+
// Instance that will be passed to _onClose delegate
20+
private readonly ZipArchiveEntry _zipArchiveEntry;
21+
private Boolean _isDisposed;
22+
1923
#endregion
2024

2125
#region constructors
2226

23-
internal WrappedStream(Stream baseStream, Boolean canRead, Boolean canWrite, Boolean canSeek, EventHandler onClosed)
24-
: this(baseStream, canRead, canWrite, canSeek, false, onClosed)
27+
internal WrappedStream(Stream baseStream, Boolean closeBaseStream)
28+
: this(baseStream, closeBaseStream, null, null)
2529
{ }
2630

27-
internal WrappedStream(Stream baseStream, Boolean canRead, Boolean canWrite, Boolean canSeek, Boolean closeBaseStream, EventHandler onClosed)
31+
private WrappedStream(Stream baseStream, Boolean closeBaseStream, ZipArchiveEntry entry, Action<ZipArchiveEntry> onClosed)
2832
{
2933
_baseStream = baseStream;
34+
_closeBaseStream = closeBaseStream;
3035
_onClosed = onClosed;
31-
_canRead = canRead;
32-
_canSeek = canSeek;
33-
_canWrite = canWrite;
36+
_zipArchiveEntry = entry;
3437
_isDisposed = false;
35-
_closeBaseStream = closeBaseStream;
3638
}
3739

38-
internal WrappedStream(Stream baseStream, EventHandler onClosed)
39-
: this(baseStream, true, true, true, onClosed)
40+
internal WrappedStream(Stream baseStream, ZipArchiveEntry entry, Action<ZipArchiveEntry> onClosed)
41+
: this(baseStream, false, entry, onClosed)
4042
{ }
4143

4244
#endregion
@@ -68,11 +70,11 @@ public override long Position
6870
}
6971
}
7072

71-
public override bool CanRead { get { return _canRead && _baseStream.CanRead; } }
73+
public override bool CanRead { get { return !_isDisposed && _baseStream.CanRead; } }
7274

73-
public override bool CanSeek { get { return _canSeek && _baseStream.CanSeek; } }
75+
public override bool CanSeek { get { return !_isDisposed && _baseStream.CanSeek; } }
7476

75-
public override bool CanWrite { get { return _canWrite && _baseStream.CanWrite; } }
77+
public override bool CanWrite { get { return !_isDisposed && _baseStream.CanWrite; } }
7678

7779
#endregion
7880

@@ -145,14 +147,11 @@ protected override void Dispose(bool disposing)
145147
if (disposing && !_isDisposed)
146148
{
147149
if (_onClosed != null)
148-
_onClosed(this, null);
150+
_onClosed(_zipArchiveEntry);
149151

150152
if (_closeBaseStream)
151153
_baseStream.Dispose();
152154

153-
_canRead = false;
154-
_canWrite = false;
155-
_canSeek = false;
156155
_isDisposed = true;
157156
}
158157
base.Dispose(disposing);
@@ -317,10 +316,11 @@ internal class CheckSumAndSizeWriteStream : Stream
317316

318317
//this is the position in BaseBaseStream
319318
private Int64 _initialPosition;
320-
319+
private readonly ZipArchiveEntry _zipArchiveEntry;
320+
private readonly EventHandler _onClose;
321321
// Called when the stream is closed.
322-
// parameters are initialPosition, currentPosition, checkSum
323-
private readonly Action<Int64, Int64, UInt32> _saveCrcAndSizes;
322+
// parameters are initialPosition, currentPosition, checkSum, baseBaseStream, zipArchiveEntry and onClose handler
323+
private readonly Action<Int64, Int64, UInt32, Stream, ZipArchiveEntry, EventHandler> _saveCrcAndSizes;
324324

325325
#endregion
326326

@@ -329,10 +329,14 @@ internal class CheckSumAndSizeWriteStream : Stream
329329
/* parameters to saveCrcAndSizes are
330330
* initialPosition (initialPosition in baseBaseStream),
331331
* currentPosition (in this CheckSumAndSizeWriteStream),
332-
* checkSum (of data passed into this CheckSumAndSizeWriteStream)
332+
* checkSum (of data passed into this CheckSumAndSizeWriteStream),
333+
* baseBaseStream it's a backingStream, passed here so as to avoid closure allocation,
334+
* zipArchiveEntry passed here so as to avoid closure allocation,
335+
* onClose handler passed here so as to avoid closure allocation
333336
*/
334-
public CheckSumAndSizeWriteStream(Stream baseStream, Stream baseBaseStream,
335-
Boolean leaveOpenOnClose, Action<Int64, Int64, UInt32> saveCrcAndSizes)
337+
public CheckSumAndSizeWriteStream(Stream baseStream, Stream baseBaseStream, Boolean leaveOpenOnClose,
338+
ZipArchiveEntry entry, EventHandler onClose,
339+
Action<Int64, Int64, UInt32, Stream, ZipArchiveEntry, EventHandler> saveCrcAndSizes)
336340
{
337341
_baseStream = baseStream;
338342
_baseBaseStream = baseBaseStream;
@@ -342,6 +346,8 @@ public CheckSumAndSizeWriteStream(Stream baseStream, Stream baseBaseStream,
342346
_canWrite = true;
343347
_isDisposed = false;
344348
_initialPosition = 0;
349+
_zipArchiveEntry = entry;
350+
_onClose = onClose;
345351
_saveCrcAndSizes = saveCrcAndSizes;
346352
}
347353

@@ -458,7 +464,7 @@ protected override void Dispose(Boolean disposing)
458464
if (!_leaveOpenOnClose)
459465
_baseStream.Dispose(); // Close my super-stream (flushes the last data)
460466
if (_saveCrcAndSizes != null)
461-
_saveCrcAndSizes(_initialPosition, Position, _checksum);
467+
_saveCrcAndSizes(_initialPosition, Position, _checksum, _baseBaseStream, _zipArchiveEntry, _onClose);
462468
_isDisposed = true;
463469
}
464470
base.Dispose(disposing);

0 commit comments

Comments
 (0)