Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf fixes copy from dotutils and MSBuildStructuredLog #10792

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ e is FormatException ||
(e is EndOfStreamException && _readStream.BytesCountAllowedToReadRemaining <= 0))
{
hasError = true;

int localSerializedEventLength = serializedEventLength;
Exception localException = e;
string ErrorFactory() =>
ResourceUtilities.FormatResourceStringStripCodeAndKeyword("Binlog_ReaderMismatchedRead",
_recordNumber, serializedEventLength, e.GetType(), e.Message) + (_skipUnknownEvents
_recordNumber, localSerializedEventLength, localException.GetType(), localException.Message) + (_skipUnknownEvents
? " " + ResourceUtilities.GetResourceString("Binlog_ReaderSkippingRecord")
: string.Empty);

Expand All @@ -255,9 +256,11 @@ string ErrorFactory() =>

if (result == null && !hasError)
{
int localSerializedEventLength = serializedEventLength;
BinaryLogRecordKind localRecordKind = recordKind;
string ErrorFactory() =>
ResourceUtilities.FormatResourceStringStripCodeAndKeyword("Binlog_ReaderUnknownType",
_recordNumber, serializedEventLength, recordKind) + (_skipUnknownEvents
_recordNumber, localSerializedEventLength, localRecordKind) + (_skipUnknownEvents
? " " + ResourceUtilities.GetResourceString("Binlog_ReaderSkippingRecord")
: string.Empty);

Expand All @@ -266,9 +269,10 @@ string ErrorFactory() =>

if (_readStream.BytesCountAllowedToReadRemaining > 0)
{
int localSerializedEventLength = serializedEventLength;
string ErrorFactory() => ResourceUtilities.FormatResourceStringStripCodeAndKeyword(
"Binlog_ReaderUnderRead", _recordNumber, serializedEventLength,
serializedEventLength - _readStream.BytesCountAllowedToReadRemaining);
"Binlog_ReaderUnderRead", _recordNumber, localSerializedEventLength,
localSerializedEventLength - _readStream.BytesCountAllowedToReadRemaining);

HandleError(ErrorFactory, _skipUnknownEventParts, ReaderErrorType.UnknownEventData, recordKind);
}
Expand Down Expand Up @@ -1437,9 +1441,9 @@ private void SetCommonFields(BuildEventArgs buildEventArgs, BuildEventArgsFields
}
}

private IEnumerable? ReadPropertyList()
private IList<DictionaryEntry>? ReadPropertyList()
{
var properties = ReadStringDictionary();
IDictionary<string, string>? properties = ReadStringDictionary();
if (properties == null || properties.Count == 0)
{
return null;
Expand Down Expand Up @@ -1530,7 +1534,7 @@ private ITaskItem ReadTaskItem()
return taskItem;
}

private IEnumerable? ReadProjectItems()
private IList<DictionaryEntry>? ReadProjectItems()
{
IList<DictionaryEntry>? list;

Expand Down Expand Up @@ -1612,7 +1616,7 @@ private ITaskItem ReadTaskItem()
return list;
}

private IEnumerable? ReadTaskItemList()
private IList<ITaskItem>? ReadTaskItemList()
{
int count = ReadInt32();
if (count == 0)
Expand Down
24 changes: 11 additions & 13 deletions src/Build/Logging/BinaryLogger/Postprocessing/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,30 +59,28 @@ public static long SkipBytes(this Stream stream, long bytesCount, byte[] buffer)

public static byte[] ReadToEnd(this Stream stream)
{
if (stream.TryGetLength(out long length))
{
using BinaryReader reader = new(stream, Encoding.UTF8, leaveOpen: true);

return reader.ReadBytes((int)length);
}

using var ms = new MemoryStream();
MemoryStream ms = stream.TryGetLength(out long length) && length <= int.MaxValue ? new((int)length) : new();
stream.CopyTo(ms);
return ms.ToArray();
byte[] buffer = ms.GetBuffer();
return buffer.Length == ms.Length ? buffer : ms.ToArray();
}

public static bool TryGetLength(this Stream stream, out long length)
{
try
{
length = stream.Length;
return true;
if (stream.CanSeek)
{
length = stream.Length;
return true;
}
}
catch (NotSupportedException)
{
length = 0;
return false;
}

length = 0;
return false;
}

public static Stream ToReadableSeekableStream(this Stream stream)
Expand Down
49 changes: 48 additions & 1 deletion src/Build/Logging/BinaryLogger/Postprocessing/SubStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Shared;

namespace Microsoft.Build.Logging
Expand Down Expand Up @@ -40,14 +42,59 @@ public SubStream(Stream stream, long length)

public override long Position { get => _position; set => throw new NotImplementedException(); }

public override void Flush() { }
public override void Flush() => _stream.Flush();
public override Task FlushAsync(CancellationToken cancellationToken) => _stream.FlushAsync(cancellationToken);
public override int Read(byte[] buffer, int offset, int count)
{
count = Math.Min((int)Math.Max(Length - _position, 0), count);
int read = _stream.Read(buffer, offset, count);
_position += read;
return read;
}

public override int ReadByte()
{
if (Length - _position > 0)
{
int value = _stream.ReadByte();
if (value >= 0)
{
_position++;
return value;
}
}

return -1;
}

public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
count = Math.Min((int)Math.Max(Length - _position, 0), count);
#pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
int read = await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
#pragma warning restore CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
_position += read;
return read;
}

#if NET
public override int Read(Span<byte> buffer)
{
buffer = buffer.Slice(0, Math.Min((int)Math.Max(Length - _position, 0), buffer.Length));
int read = _stream.Read(buffer);
_position += read;
return read;
}

public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
buffer = buffer.Slice(0, Math.Min((int)Math.Max(Length - _position, 0), buffer.Length));
int read = await _stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
_position += read;
return read;
}
#endif

public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException();
public override void SetLength(long value) => throw new NotImplementedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Shared;

namespace Microsoft.Build.Logging
Expand Down Expand Up @@ -75,6 +77,11 @@ public override void Flush()
_stream.Flush();
}

public override Task FlushAsync(CancellationToken cancellationToken)
{
return _stream.FlushAsync(cancellationToken);
}

public override int Read(byte[] buffer, int offset, int count)
{
if (_position + count > _maxAllowedPosition)
Expand All @@ -87,6 +94,61 @@ public override int Read(byte[] buffer, int offset, int count)
return cnt;
}

public override int ReadByte()
{
if (_position + 1 <= _maxAllowedPosition)
{
int value = _stream.ReadByte();
if (value >= 0)
{
_position++;
return value;
}
}

return -1;
}

public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (_position + count > _maxAllowedPosition)
{
count = (int)(_maxAllowedPosition - _position);
}

#pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
int cnt = await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
#pragma warning restore CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
_position += cnt;
return cnt;
}

#if NET
public override int Read(Span<byte> buffer)
{
if (_position + buffer.Length > _maxAllowedPosition)
{
buffer = buffer.Slice(0, (int)(_maxAllowedPosition - _position));
}

int cnt = _stream.Read(buffer);
_position += cnt;
return cnt;
}

public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (_position + buffer.Length > _maxAllowedPosition)
{
buffer = buffer.Slice(0, (int)(_maxAllowedPosition - _position));
}

int cnt = await _stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
_position += cnt;
return cnt;
}
#endif

public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
Expand Down
Loading