Skip to content

Commit 2495266

Browse files
authored
Eliminate allocation in StreamAsIStream.Read. (#6632)
The native/managed interop layer will allocate a byte array to marshal a native buffer to the StreamDescriptor.Read delegate. By using Span<byte> and the corresponding overload of Stream.Read, we can read directly into the caller's buffer when CManagedStream::Read calls this delegate.
1 parent 1e0d0dd commit 2495266

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/StreamAsIStream.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System;
1111
using MS.Internal;
1212
using MS.Win32;
13+
using System.Buffers;
1314
using System.Reflection;
1415
using System.Collections;
1516
using System.Diagnostics;
@@ -27,7 +28,7 @@ namespace System.Windows.Media
2728
internal struct StreamDescriptor
2829
{
2930
internal delegate void Dispose(ref StreamDescriptor pSD);
30-
internal delegate int Read(ref StreamDescriptor pSD, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out]byte[] buffer, uint cb, out uint cbRead);
31+
internal delegate int Read(ref StreamDescriptor pSD, IntPtr buffer, uint cb, out uint cbRead);
3132

3233
internal unsafe delegate int Seek(ref StreamDescriptor pSD, long offset, uint origin, long* plibNewPostion);
3334
internal delegate int Stat(ref StreamDescriptor pSD, out System.Runtime.InteropServices.ComTypes.STATSTG statstg, uint grfStatFlag);
@@ -236,7 +237,7 @@ public int CopyTo(IntPtr /* IStream */ pstm, long cb, out long cbRead, out long
236237

237238
uint read = 0;
238239

239-
hr = Read(buffer, toRead, out read);
240+
hr = Read(buffer.AsSpan(0, (int) toRead), out read);
240241

241242
if (read == 0)
242243
{
@@ -289,7 +290,7 @@ public int LockRegion(long libOffset, long cb, uint dwLockType)
289290
return NativeMethods.E_NOTIMPL;
290291
}
291292

292-
public int Read(byte[] buffer, uint cb, out uint cbRead)
293+
public int Read(Span<byte> buffer, out uint cbRead)
293294
{
294295
cbRead = 0;
295296

@@ -300,7 +301,7 @@ public int Read(byte[] buffer, uint cb, out uint cbRead)
300301
Verify();
301302
ActualizeVirtualPosition();
302303

303-
cbRead = (uint) dataStream.Read(buffer, 0, (int) cb);
304+
cbRead = (uint) dataStream.Read(buffer);
304305
}
305306
catch (Exception e)
306307
{
@@ -596,9 +597,10 @@ internal static int LockRegion(ref StreamDescriptor pSD, long libOffset, long cb
596597
return (StreamAsIStream.FromSD(ref pSD)).LockRegion(libOffset, cb, dwLockType);
597598
}
598599

599-
internal static int Read(ref StreamDescriptor pSD, byte[] buffer, uint cb, out uint cbRead)
600+
internal static unsafe int Read(ref StreamDescriptor pSD, IntPtr buffer, uint cb, out uint cbRead)
600601
{
601-
return (StreamAsIStream.FromSD(ref pSD)).Read(buffer, cb, out cbRead);
602+
var span = new Span<byte>(buffer.ToPointer(), (int) cb);
603+
return (StreamAsIStream.FromSD(ref pSD)).Read(span, out cbRead);
602604
}
603605

604606
internal static int Revert(ref StreamDescriptor pSD)

0 commit comments

Comments
 (0)