Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Avoid unnecessary Span to ReadOnlySpan casts (#34646)
Browse files Browse the repository at this point in the history
In a bunch of places we're creating a Span only to then cast it (generally implicitly) to a ReadOnlySpan.  While the JIT is generally able to do the RightThing(tm), we can avoid the unnecessary IL and pressure on the JIT by just creating a ReadOnlySpan to begin with.
  • Loading branch information
stephentoub committed Jan 17, 2019
1 parent 31a9af8 commit ab92553
Show file tree
Hide file tree
Showing 24 changed files with 49 additions and 41 deletions.
6 changes: 3 additions & 3 deletions src/Common/src/Interop/FreeBSD/Interop.Process.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ internal static unsafe int[] ListAllPids()
throw new Win32Exception(SR.CantGetAllPids);
}

Span<kinfo_proc> list = new Span<kinfo_proc>(entries, numProcesses);
var list = new ReadOnlySpan<kinfo_proc>(entries, numProcesses);
pids = new int[numProcesses];
idx = 0;
// walk through process list and skip kernel threads
Expand Down Expand Up @@ -357,7 +357,7 @@ static public unsafe ProcessInfo GetProcessInfoById(int pid)
throw new ArgumentOutOfRangeException(nameof(pid));
}

Span<kinfo_proc> process = new Span<kinfo_proc>(kinfo, count);
var process = new ReadOnlySpan<kinfo_proc>(kinfo, count);

// Get the process information for the specified pid
info = new ProcessInfo();
Expand Down Expand Up @@ -417,7 +417,7 @@ public unsafe static proc_stats GetThreadInfo(int pid, int tid)
}
else
{
Span<kinfo_proc> list = new Span<kinfo_proc>(info, count);
var list = new ReadOnlySpan<kinfo_proc>(info, count);
for(int i = 0; i < list.Length; i++)
{
if (list[i].ki_tid == tid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ private static unsafe int AlpnServerSelectCallback(IntPtr ssl, out byte* outp, o
{
for (int i = 0; i < protocolList.Count; i++)
{
Span<byte> clientList = new Span<byte>(inp, (int)inlen);
var clientList = new Span<byte>(inp, (int)inlen);
while (clientList.Length > 0)
{
byte length = clientList[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal static byte[] ConvertAlpnProtocolListToByteArray(List<SslApplicationPro
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
buffer[offset++] = (byte)(protocol.Protocol.Length);
protocol.Protocol.Span.CopyTo(new Span<byte>(buffer).Slice(offset));
protocol.Protocol.Span.CopyTo(buffer.AsSpan(offset));
offset += protocol.Protocol.Length;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static unsafe IPAddress GetIPAddress(this Interop.Sys.IPAddress nativeIPA
else
{
return new IPAddress(
new Span<byte>(nativeIPAddress.Address, Interop.Sys.IPv6AddressBytes),
new ReadOnlySpan<byte>(nativeIPAddress.Address, Interop.Sys.IPv6AddressBytes),
(long)nativeIPAddress.ScopeId);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ private static void ValidateParameters(ECDomainParameters? keyParameters, in Alg
keyParameters.Value.Encode(writer);
if (!writer.TryEncode(verify, out int written) ||
written != algIdParameters.Length ||
!algIdParameters.SequenceEqual(verify.AsSpan(0, written)))
!algIdParameters.SequenceEqual(new ReadOnlySpan<byte>(verify, 0, written)))
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Common/tests/Performance/Perf.Marvin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ private static IEnumerable<object[]> EnumerateRandomByteArrayTestCases()
[MemberData(nameof(EnumerateRandomByteArrayTestCases))]
public void Add(int iterations, byte[] data)
{
Span<byte> otherData = new byte[] { 1, 2, 3 };
var bytes = new Span<byte>(data);
ReadOnlySpan<byte> otherData = new byte[] { 1, 2, 3 };
var bytes = new ReadOnlySpan<byte>(data);
foreach (var iteration in Benchmark.Iterations)
{
using (iteration.StartMeasurement())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ sealed internal partial class SqlDelegatedTransaction : IPromotableSinglePhaseNo
{
// Get the server-side Global Transaction Id from the PromotedDTCToken
// Skip first 4 bytes since they contain the version
private Guid GetGlobalTxnIdentifierFromToken() => new Guid(_connection.PromotedDTCToken.AsSpan(_globalTransactionsTokenVersionSizeInBytes, 16));
private Guid GetGlobalTxnIdentifierFromToken() => new Guid(new ReadOnlySpan<byte>(_connection.PromotedDTCToken, _globalTransactionsTokenVersionSizeInBytes, 16));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ long allocationSize

// We could continue to do pointer math here, chose to use Span for convenience to
// make sure we get the other members in the right place.
Span<byte> data = new Span<byte>(buffer).Slice(headerSize);
Span<byte> data = buffer.AsSpan(headerSize);
s_eaNameString.AsSpan().CopyTo(data);
data = data.Slice(s_eaNameString.Length);
transactionContext.AsSpan().CopyTo(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public unsafe int StreamPutBytesImpl(byte* buf, int bufsz)
_stream.Write(buffer, 0, bufsz);
ArrayPool<byte>.Shared.Return(buffer);
#else
Span<byte> buffer = new Span<byte>(buf, bufsz);
var buffer = new ReadOnlySpan<byte>(buf, bufsz);
_stream.Write(buffer);
#endif
return bufsz;
Expand Down
13 changes: 3 additions & 10 deletions src/System.Drawing.Common/src/System/Drawing/Image.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,16 +383,9 @@ internal unsafe static void EnsureSave(Image image, string filename, Stream data
return;
}

Span<Guid> guids;
if (dimensions < 16)
{
Guid* g = stackalloc Guid[dimensions];
guids = new Span<Guid>(g, dimensions);
}
else
{
guids = new Span<Guid>(new Guid[dimensions]);
}
Span<Guid> guids = dimensions < 16 ?
stackalloc Guid[dimensions] :
new Guid[dimensions];

fixed (Guid* g = &MemoryMarshal.GetReference(guids))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public unsafe void Write(byte* pv, uint cb, uint* pcbWritten)
_dataStream.Write(buffer, 0, checked((int)cb));
ArrayPool<byte>.Shared.Return(buffer);
#else
Span<byte> buffer = new Span<byte>(pv, checked((int)cb));
var buffer = new ReadOnlySpan<byte>(pv, checked((int)cb));
_dataStream.Write(buffer);
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public override int Read(Span<byte> buffer)
}
}

lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer, out int bytesConsumed, out int bytesWritten);
lastResult = _decoder.Decompress(new ReadOnlySpan<byte>(_buffer, _bufferOffset, _bufferCount), buffer, out int bytesConsumed, out int bytesWritten);
if (lastResult == OperationStatus.InvalidData)
{
throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData);
Expand Down Expand Up @@ -153,7 +153,7 @@ private async ValueTask<int> FinishReadAsyncMemory(Memory<byte> buffer, Cancella
}

cancellationToken.ThrowIfCancellationRequested();
lastResult = _decoder.Decompress(_buffer.AsSpan(_bufferOffset, _bufferCount), buffer.Span, out int bytesConsumed, out int bytesWritten);
lastResult = _decoder.Decompress(new ReadOnlySpan<byte>(_buffer, _bufferOffset, _bufferCount), buffer.Span, out int bytesConsumed, out int bytesWritten);
if (lastResult == OperationStatus.InvalidData)
{
throw new InvalidOperationException(SR.BrotliStream_Decompress_InvalidData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ private static ReadOnlySpan<T> GetFirstSpanSlow(object startObject, int startInd
{
// Negative start and negative end index == string
ReadOnlySpan<char> spanOfChar = ((string)startObject).AsSpan(startIndex & ReadOnlySequence.IndexBitMask, endIndex - startIndex);
return MemoryMarshal.CreateSpan(ref Unsafe.As<char, T>(ref MemoryMarshal.GetReference(spanOfChar)), spanOfChar.Length);
return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<char, T>(ref MemoryMarshal.GetReference(spanOfChar)), spanOfChar.Length);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public HeaderField this[int index]
}
}

public void Insert(Span<byte> name, Span<byte> value)
public void Insert(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{
int entryLength = HeaderField.GetLength(name.Length, value.Length);
EnsureAvailable(entryLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ public void Decode(ReadOnlySpan<byte> data, HeaderCallback onHeader)
{
OnString(nextState: State.Ready);

var headerNameSpan = new Span<byte>(_headerName, 0, _headerNameLength);
var headerValueSpan = new Span<byte>(_headerValueOctets, 0, _headerValueLength);
var headerNameSpan = new ReadOnlySpan<byte>(_headerName, 0, _headerNameLength);
var headerValueSpan = new ReadOnlySpan<byte>(_headerValueOctets, 0, _headerValueLength);

onHeader(headerNameSpan, headerValueSpan);

Expand Down Expand Up @@ -328,7 +328,7 @@ public void CompleteDecode()
private void OnIndexedHeaderField(int index, HeaderCallback onHeader)
{
HeaderField header = GetHeader(index);
onHeader(new Span<byte>(header.Name), new Span<byte>(header.Value));
onHeader(new ReadOnlySpan<byte>(header.Name), new ReadOnlySpan<byte>(header.Value));
_state = State.Ready;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal struct HeaderField
// http://httpwg.org/specs/rfc7541.html#rfc.section.4.1
public const int RfcOverhead = 32;

public HeaderField(Span<byte> name, Span<byte> value)
public HeaderField(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{
// TODO: We're allocating here on every new table entry.
// That means a poorly-behaved server could cause us to allocate repeatedly.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ public static unsafe IPPacketInformation GetIPPacketInformation(Interop.Winsock.
public static unsafe IPPacketInformation GetIPPacketInformation(Interop.Winsock.ControlDataIPv6* controlBuffer)
{
IPAddress address = controlBuffer->length != UIntPtr.Zero ?
new IPAddress(new Span<byte>(controlBuffer->address, Interop.Winsock.IPv6AddressLength)) :
new IPAddress(new ReadOnlySpan<byte>(controlBuffer->address, Interop.Winsock.IPv6AddressLength)) :
IPAddress.IPv6None;

return new IPPacketInformation(address, (int)controlBuffer->index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ public virtual T this[params int[] indices]
{
throw new ArgumentNullException(nameof(indices));
}
var span = new Span<int>(indices);
var span = new ReadOnlySpan<int>(indices);
return this[span];
}

Expand All @@ -655,7 +655,7 @@ public virtual T this[params int[] indices]
{
throw new ArgumentNullException(nameof(indices));
}
var span = new Span<int>(indices);
var span = new ReadOnlySpan<int>(indices);
this[span] = value;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/System.Private.Xml/src/System/Xml/NameTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ private static bool TextEquals(string str1, char[] str2, int str2Start, int str2
}
private static int ComputeHash32(char[] key, int start, int len)
{
ReadOnlySpan<byte> bytes = MemoryMarshal.AsBytes(key.AsSpan(start, len));
ReadOnlySpan<byte> bytes = MemoryMarshal.AsBytes(new ReadOnlySpan<char>(key, start, len));
return Marvin.ComputeHash32(bytes, Marvin.DefaultSeed);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Globalization;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;

namespace System.Xml.Serialization
{
Expand All @@ -32,11 +33,18 @@ public static string MakePascal(string identifier)
{
identifier = MakeValid(identifier);
if (identifier.Length <= 2)
{
return CultureInfo.InvariantCulture.TextInfo.ToUpper(identifier);
}
else if (char.IsLower(identifier[0]))
return string.Concat(char.ToUpperInvariant(identifier[0]).ToString(), identifier.AsSpan(1));
{
char upper = char.ToUpperInvariant(identifier[0]);
return string.Concat(MemoryMarshal.CreateReadOnlySpan(ref upper, 1), identifier.AsSpan(1));
}
else
{
return identifier;
}
}

/// <devdoc>
Expand All @@ -46,11 +54,18 @@ public static string MakeCamel(string identifier)
{
identifier = MakeValid(identifier);
if (identifier.Length <= 2)
{
return CultureInfo.InvariantCulture.TextInfo.ToLower(identifier);
}
else if (char.IsUpper(identifier[0]))
return string.Concat(char.ToLower(identifier[0]).ToString(), identifier.AsSpan(1));
{
char lower = char.ToLower(identifier[0]);
return string.Concat(MemoryMarshal.CreateReadOnlySpan(ref lower, 1), identifier.AsSpan(1));
}
else
{
return identifier;
}
}

/// <devdoc>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ private unsafe AsnWriter WritePkcs8PrivateKey()
continue;
}

return RSAKeyFormatHelper.WritePkcs8PrivateKey(rented.AsSpan(0, pkcs1Size));
return RSAKeyFormatHelper.WritePkcs8PrivateKey(new ReadOnlySpan<byte>(rented, 0, pkcs1Size));
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ internal static CngKey Import(
if (keyBlob == null)
throw new ArgumentNullException(nameof(keyBlob));

return Import(keyBlob.AsSpan(), curveName, format, provider);
return Import(new ReadOnlySpan<byte>(keyBlob), curveName, format, provider);
}

internal static CngKey Import(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private static AsymmetricAlgorithm DecodeRsaPublicKey(byte[] encodedKeyValue)
RSA rsa = RSA.Create();
try
{
rsa.ImportRSAPublicKey(encodedKeyValue.AsSpan(), out _);
rsa.ImportRSAPublicKey(new ReadOnlySpan<byte>(encodedKeyValue), out _);
return rsa;
}
catch (Exception)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ private static RSA BuildRsaPublicKey(byte[] encodedData)
RSA rsa = new RSAOpenSsl();
try
{
rsa.ImportRSAPublicKey(encodedData.AsSpan(), out _);
rsa.ImportRSAPublicKey(new ReadOnlySpan<byte>(encodedData), out _);
}
catch (Exception)
{
Expand Down

0 comments on commit ab92553

Please sign in to comment.