Skip to content

Commit

Permalink
perf fixes copy from dotutils and MSBuildStructuredLog (#10792)
Browse files Browse the repository at this point in the history
* adopt stream changes from dotutils

* adopt BuildEventArgsReader changes from BinlogViewer

* add ResourceUtilities methods without params, refactor

* refactor conditional compilation to debug method attribute
  • Loading branch information
JanProvaznik authored Oct 14, 2024
1 parent 360af78 commit b8aaabf
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 64 deletions.
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

0 comments on commit b8aaabf

Please sign in to comment.