Skip to content

Conversation

@eerhardt
Copy link
Member

ManifestResourceStream is derived from UnmanagedMemoryStream. UnmanagedMemoryStream optimizes Read(Span), but only if the instance is concretely an UnmanagedMemoryStream. This is to protect in case the derived Stream overriddes Read(byte[], int, int) prior to the Read(Span) overload being introduced.

Optimize ManifestResourceStream by overriding Read(Span) and call ReadCore, so the Stream.Read(Span) logic of using a pooled byte[] buffer isn't used.

Benchmark

[MemoryDiagnoser]
public class ManifestResourceStreamBenchmark
{
    private Stream _stream;

    [GlobalSetup]
    public void Setup()
    {
        _stream = typeof(object).Assembly.GetManifestResourceStream("System.Private.CoreLib.Strings.resources");
    }

    [Benchmark]
    public void ReadAll()
    {
        Span<byte> buffer = stackalloc byte[1024];
        while (_stream.Read(buffer) != 0)
        {
        }
    }
}

Results

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1706 (21H1/May2021Update)
Intel Core i7-8700 CPU 3.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.300
  [Host]     : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
  Job-AASUSC : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
  Job-LHCSRL : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
Method Job Toolchain Mean Error StdDev Ratio Allocated
ReadAll Job-AASUSC \main\corerun.exe 66.06 ns 0.408 ns 0.362 ns 1.00 -
ReadAll Job-LHCSRL \pr\corerun.exe 42.82 ns 0.093 ns 0.078 ns 0.65 -

ManifestResourceStream is derived from UnmanagedMemoryStream. UnmanagedMemoryStream optimizes Read(Span<byte>), but only if the instance is concretely an UnmanagedMemoryStream. This is to protect in case the derived Stream overriddes Read(byte[], int, int) prior to the Read(Span<byte>) overload being introduced.

Optimize ManifestResourceStream by overriding Read(Span<byte>) and call ReadCore, so the Stream.Read(Span<byte>) logic of using a pooled byte[] buffer isn't used.
@eerhardt eerhardt requested a review from stephentoub May 16, 2022 21:44
@ghost ghost assigned eerhardt May 16, 2022
@ghost
Copy link

ghost commented May 16, 2022

Tagging subscribers to this area: @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

Issue Details

ManifestResourceStream is derived from UnmanagedMemoryStream. UnmanagedMemoryStream optimizes Read(Span), but only if the instance is concretely an UnmanagedMemoryStream. This is to protect in case the derived Stream overriddes Read(byte[], int, int) prior to the Read(Span) overload being introduced.

Optimize ManifestResourceStream by overriding Read(Span) and call ReadCore, so the Stream.Read(Span) logic of using a pooled byte[] buffer isn't used.

Benchmark

[MemoryDiagnoser]
public class ManifestResourceStreamBenchmark
{
    private Stream _stream;

    [GlobalSetup]
    public void Setup()
    {
        _stream = typeof(object).Assembly.GetManifestResourceStream("System.Private.CoreLib.Strings.resources");
    }

    [Benchmark]
    public void ReadAll()
    {
        Span<byte> buffer = stackalloc byte[1024];
        while (_stream.Read(buffer) != 0)
        {
        }
    }
}

Results

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1706 (21H1/May2021Update)
Intel Core i7-8700 CPU 3.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.300
  [Host]     : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
  Job-AASUSC : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
  Job-LHCSRL : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
Method Job Toolchain Mean Error StdDev Ratio Allocated
ReadAll Job-AASUSC \main\corerun.exe 66.06 ns 0.408 ns 0.362 ns 1.00 -
ReadAll Job-LHCSRL \pr\corerun.exe 42.82 ns 0.093 ns 0.078 ns 0.65 -
Author: eerhardt
Assignees: -
Labels:

area-System.Reflection

Milestone: -

@stephentoub stephentoub merged commit f63fdee into dotnet:main May 17, 2022
@eerhardt eerhardt deleted the ResourceStreamOptimization branch May 17, 2022 11:35
@ghost ghost locked as resolved and limited conversation to collaborators Jun 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants