Skip to content

Override ReadAsync and WriteAsync methods on ConsoleStream. - #71971

Merged
eerhardt merged 3 commits into
dotnet:mainfrom
eerhardt:ConsoleStreams
Jul 12, 2022
Merged

Override ReadAsync and WriteAsync methods on ConsoleStream.#71971
eerhardt merged 3 commits into
dotnet:mainfrom
eerhardt:ConsoleStreams

Conversation

@eerhardt

Copy link
Copy Markdown
Member

The base Stream class implements these overloads by renting a buffer,
creating a ReadWriteTask, and copying data as necessary.

Instead, ConsoleStreams can just override these Async methods and synchronously
call the underlying OS API.

Benchmark

publicclassConsoleStreamsBenchmark{staticbyte[]_bytes=Encoding.ASCII.GetBytes("Hello, World!");staticStream_stream=Console.OpenStandardOutput();staticNativeMemoryManager_nativeMemoryManager=CreateNativeMemory();privateunsafestaticNativeMemoryManagerCreateNativeMemory(){byte*mem=(byte*)NativeMemory.Alloc((nuint)_bytes.Length);_bytes.AsSpan().CopyTo(newSpan<byte>(mem,_bytes.Length));returnnewNativeMemoryManager(mem,_bytes.Length);}[Benchmark]publicasyncTaskWriteToStream(){await_stream.WriteAsync(_bytes);}[Benchmark]publicasyncTaskWriteNativeMemoryToStream(){await_stream.WriteAsync(_nativeMemoryManager.Memory);}unsafeclassNativeMemoryManager:MemoryManager<byte>{privatebyte*_pointer;privateint_length;internalNativeMemoryManager(byte*pointer,intlength){_pointer=pointer;_length=length;}publicoverrideSpan<byte>GetSpan()=>newSpan<byte>(_pointer,_length);publicoverrideMemoryHandlePin(intelementIndex=0)=>default;publicoverridevoidUnpin(){}protectedoverridevoidDispose(booldisposing){}}}

Results

MethodJobToolchainMeanErrorStdDevRatioRatioSD
WriteToStreamJob-AMXSLA\main\corerun.exe6.221 us0.6849 us0.7888 us1.000.00
WriteToStreamJob-CRTAYW\pr\corerun.exe4.602 us0.6634 us0.7374 us0.740.08
WriteNativeMemoryToStreamJob-AMXSLA\main\corerun.exe6.549 us0.8117 us0.8685 us1.000.00
WriteNativeMemoryToStreamJob-CRTAYW\pr\corerun.exe4.575 us0.6448 us0.7426 us0.690.07

The base Stream class implements these overloads by renting a buffer,
creating a ReadWriteTask, and copying data as necessary.
Instead, ConsoleStreams can just override these Async methods and synchronously
call the underlying OS API.
Add tests to verify that input and output console streams behave correctly.
@ghostghost assigned eerhardtJul 11, 2022
@ghost

Copy link
Copy Markdown

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

Issue Details

The base Stream class implements these overloads by renting a buffer,
creating a ReadWriteTask, and copying data as necessary.

Instead, ConsoleStreams can just override these Async methods and synchronously
call the underlying OS API.

Benchmark

publicclassConsoleStreamsBenchmark{staticbyte[]_bytes=Encoding.ASCII.GetBytes("Hello, World!");staticStream_stream=Console.OpenStandardOutput();staticNativeMemoryManager_nativeMemoryManager=CreateNativeMemory();privateunsafestaticNativeMemoryManagerCreateNativeMemory(){byte*mem=(byte*)NativeMemory.Alloc((nuint)_bytes.Length);_bytes.AsSpan().CopyTo(newSpan<byte>(mem,_bytes.Length));returnnewNativeMemoryManager(mem,_bytes.Length);}[Benchmark]publicasyncTaskWriteToStream(){await_stream.WriteAsync(_bytes);}[Benchmark]publicasyncTaskWriteNativeMemoryToStream(){await_stream.WriteAsync(_nativeMemoryManager.Memory);}unsafeclassNativeMemoryManager:MemoryManager<byte>{privatebyte*_pointer;privateint_length;internalNativeMemoryManager(byte*pointer,intlength){_pointer=pointer;_length=length;}publicoverrideSpan<byte>GetSpan()=>newSpan<byte>(_pointer,_length);publicoverrideMemoryHandlePin(intelementIndex=0)=>default;publicoverridevoidUnpin(){}protectedoverridevoidDispose(booldisposing){}}}

Results

MethodJobToolchainMeanErrorStdDevRatioRatioSD
WriteToStreamJob-AMXSLA\main\corerun.exe6.221 us0.6849 us0.7888 us1.000.00
WriteToStreamJob-CRTAYW\pr\corerun.exe4.602 us0.6634 us0.7374 us0.740.08
WriteNativeMemoryToStreamJob-AMXSLA\main\corerun.exe6.549 us0.8117 us0.8685 us1.000.00
WriteNativeMemoryToStreamJob-CRTAYW\pr\corerun.exe4.575 us0.6448 us0.7426 us0.690.07
Author:eerhardt
Assignees:-
Labels:

area-System.Console

Milestone:-

Comment threadsrc/libraries/System.Console/src/System/IO/ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/IO/ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/IO/ConsoleStream.cs Outdated
Comment threadsrc/libraries/System.Console/src/System/IO/ConsoleStream.cs

@stephentoubstephentoub left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

@eerhardt

Copy link
Copy Markdown
MemberAuthor

The new "OpenStandardInput" tests need to be skipped on platforms that don't support standard input - like wasm, ios, and android. Fixing...

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @eerhardt !

@adamsitnik

Copy link
Copy Markdown
Member

/azp list

@azure-pipelines

Copy link
Copy Markdown

@adamsitnik

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@eerhardt

Copy link
Copy Markdown
MemberAuthor

All the runtime-extra-platforms failures are unrelated to System.Console.

Sign up for freeto 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.

3 participants

@eerhardt@adamsitnik@stephentoub