Skip to content

Commit

Permalink
Merge pull request #61 from sveinungf/dev/loop-perf
Browse files Browse the repository at this point in the history
Minor optimizations
  • Loading branch information
sveinungf authored Jun 30, 2024
2 parents 9472b52 + b1b7f59 commit 5b0d342
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 75 deletions.
7 changes: 4 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
</PropertyGroup>
<ItemGroup>
<GlobalPackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.4.0-beta.1" />
<GlobalPackageReference Include="Meziantou.Analyzer" Version="2.0.158" />
<GlobalPackageReference Include="Meziantou.Analyzer" Version="2.0.159" />
<GlobalPackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.10.48" />
<GlobalPackageReference Include="PrimaryConstructorAnalyzer" Version="1.0.6" />
<GlobalPackageReference Include="Roslynator.Analyzers" Version="4.12.4" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.27.0.93347" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.28.0.94264" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
Expand All @@ -33,7 +34,7 @@
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="TngTech.ArchUnitNET.xUnit" Version="0.10.6" />
<PackageVersion Include="Verify.SourceGenerators" Version="2.2.0" />
<PackageVersion Include="Verify.Xunit" Version="25.0.3" />
<PackageVersion Include="Verify.Xunit" Version="25.0.4" />
<PackageVersion Include="xunit" Version="2.8.1" />
<PackageVersion Include="xunit.assert" Version="2.8.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.1" />
Expand Down
43 changes: 17 additions & 26 deletions SpreadCheetah/CellWriters/BaseCellWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,50 +68,41 @@ public bool TryAddRow(ReadOnlySpan<T> cells, uint rowIndex, RowOptions options)

private bool TryAddRowCells(IList<T> cells)
{
return TryGetSpan(cells, out var span)
? TryAddRowCellsForSpan(span)
: TryAddRowCellsForList(cells);
}

private static bool TryGetSpan(IList<T> cells, out ReadOnlySpan<T> span)
{
if (cells is T[] cellArray)
return cells switch
{
span = cellArray.AsSpan();
return true;
}

T[] cellArray => TryAddRowCellsForSpan(cellArray),
#if NET5_0_OR_GREATER
if (cells is List<T> cellList)
{
span = System.Runtime.InteropServices.CollectionsMarshal.AsSpan(cellList);
return true;
}
List<T> cellList => TryAddRowCellsForSpan(System.Runtime.InteropServices.CollectionsMarshal.AsSpan(cellList)),
#endif

span = [];
return false;
_ => TryAddRowCellsForList(cells)
};
}

private bool TryAddRowCellsForSpan(ReadOnlySpan<T> cells)
{
for (; State.Column < cells.Length; ++State.Column)
var writerState = State;
var column = writerState.Column;
while (column < cells.Length)
{
// Write cell if it fits in the buffer
if (!TryWriteCell(cells[State.Column]))
if (!TryWriteCell(cells[column]))
return false;

writerState.Column = ++column;
}

return TryWriteRowEnd();
}

private bool TryAddRowCellsForList(IList<T> cells)
{
for (; State.Column < cells.Count; ++State.Column)
var writerState = State;
var column = writerState.Column;
while (column < cells.Count)
{
// Write cell if it fits in the buffer
if (!TryWriteCell(cells[State.Column]))
if (!TryWriteCell(cells[column]))
return false;

writerState.Column = ++column;
}

return TryWriteRowEnd();
Expand Down
35 changes: 4 additions & 31 deletions SpreadCheetah/Helpers/CellRowHelper.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,19 @@
using SpreadCheetah.Worksheets;
using System.Buffers.Text;

namespace SpreadCheetah.Helpers;

internal static class CellRowHelper
{
public static bool TryWriteRowStart(uint rowIndex, SpreadsheetBuffer buffer)
{
var bytes = buffer.GetSpan();

if (RowStart.TryCopyTo(bytes)
&& Utf8Formatter.TryFormat(rowIndex, bytes.Slice(RowStart.Length), out var part2)
&& RowStartEndTag.TryCopyTo(bytes.Slice(RowStart.Length + part2)))
{
buffer.Advance(RowStart.Length + RowStartEndTag.Length + part2);
return true;
}

return false;
return buffer.TryWrite($"{RowStart}{rowIndex}{RowStartEndTag}");
}

public static bool TryWriteRowStart(uint rowIndex, RowOptions options, SpreadsheetBuffer buffer)
{
if (options.Height is not { } height)
return TryWriteRowStart(rowIndex, buffer);

var bytes = buffer.GetSpan();
var part1 = RowStart.Length;
var part3 = RowHeightStart.Length;
var part5 = RowHeightEnd.Length;

if (RowStart.TryCopyTo(bytes)
&& Utf8Formatter.TryFormat(rowIndex, bytes.Slice(part1), out var part2)
&& RowHeightStart.TryCopyTo(bytes.Slice(part1 + part2))
&& Utf8Formatter.TryFormat(height, bytes.Slice(part1 + part2 + part3), out var part4)
&& RowHeightEnd.TryCopyTo(bytes.Slice(part1 + part2 + part3 + part4)))
{
buffer.Advance(part1 + part2 + part3 + part4 + part5);
return true;
}

return false;
return options.Height is { } height
? buffer.TryWrite($"{RowStart}{rowIndex}{RowHeightStart}{height}{RowHeightEnd}")
: TryWriteRowStart(rowIndex, buffer);
}

private static ReadOnlySpan<byte> RowStart => "<row r=\""u8;
Expand Down
35 changes: 20 additions & 15 deletions SpreadCheetah/SpreadsheetBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal sealed class SpreadsheetBuffer(int bufferSize) : IDisposable

public void Dispose() => ArrayPool<byte>.Shared.Return(_buffer, true);
public Span<byte> GetSpan() => _buffer.AsSpan(_index);
private Span<byte> GetSpan(int start) => _buffer.AsSpan(_index + start);
public void Advance(int bytes) => _index += bytes;

public bool WriteLongString(ReadOnlySpan<char> value, ref int valueIndex)
Expand Down Expand Up @@ -54,31 +55,24 @@ public bool TryWrite(scoped ReadOnlySpan<byte> utf8Value)

public bool TryWrite([InterpolatedStringHandlerArgument("")] ref TryWriteInterpolatedStringHandler handler)
{
if (handler._success)
var pos = handler._pos;
if (pos != 0)
{
Advance(handler._pos);
Advance(pos);
return true;
}

return false;
}

[InterpolatedStringHandler]
public ref struct TryWriteInterpolatedStringHandler
#pragma warning disable CS9113 // Parameter is unread.
public ref struct TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, SpreadsheetBuffer buffer)
#pragma warning restore CS9113 // Parameter is unread.
{
private readonly SpreadsheetBuffer _buffer;
internal int _pos;
internal bool _success;

public TryWriteInterpolatedStringHandler(int literalLength, int formattedCount, SpreadsheetBuffer buffer)
{
_ = literalLength;
_ = formattedCount;
_buffer = buffer;
_success = true;
}

private readonly Span<byte> GetSpan() => _buffer._buffer.AsSpan(_buffer._index + _pos);
private readonly Span<byte> GetSpan() => buffer.GetSpan(_pos);

[ExcludeFromCodeCoverage]
public bool AppendLiteral(string value)
Expand All @@ -105,6 +99,17 @@ public bool AppendFormatted(int value)
return Fail();
}

public bool AppendFormatted(uint value)
{
if (Utf8Formatter.TryFormat(value, GetSpan(), out var bytesWritten))
{
_pos += bytesWritten;
return true;
}

return Fail();
}

public bool AppendFormatted(float value)
{
if (Utf8Formatter.TryFormat(value, GetSpan(), out var bytesWritten))
Expand Down Expand Up @@ -180,7 +185,7 @@ public bool AppendFormatted(CellWriterState state)

private bool Fail()
{
_success = false;
_pos = 0;
return false;
}
}
Expand Down

0 comments on commit 5b0d342

Please sign in to comment.