-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Console for iOS and Android #37078
Conversation
Tagging subscribers to this area: @eiriktsarpalis |
Co-authored-by: campersau <buchholz.bastian@googlemail.com>
Co-authored-by: campersau <buchholz.bastian@googlemail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a significant amount of code duplication between iOS and Android, maybe there could be a way to share that code?
Also I think this implementation won't handle the following correctly:
Console.Write ("A\na");
Console.Write ("B\nb");
Console.WriteLine ("C");
I think it will show up as:
A
a
B
b
C
when it should be:
A
aB
bC
@rolfbjarne fixed to print they way you described Console.Write ("A\na");
Console.Write ("B\nb");
Console.WriteLine ("C"); prints
|
{ | ||
// we found a new line, append content from accumulator if it's not empty | ||
accumulator.Append(sliceWithNl); | ||
printer(accumulator.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are lots of strings created. Would it be possible to pass ReadOnlySpans around instead?
private static void AccumulateNewLines(StringBuilder accumulator, ReadOnlySpan<char> buffer, Action<string> printer) | ||
{ | ||
int lineStartIndex = 0; | ||
for (int i = 0; i < buffer.Length; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always walk the entire buffer.
I think a more performant algorithm would be to walk the buffer backwards, and if you find a newline character, you can print everything up to that character (prepending anything in the buffer), and then put the rest in the buffer. This would be much faster for Console.WriteLine statements, since it would only check the last character in the buffer.
for (int i = buffer.Length - 1; i >= 0; i--) {
if (buffer[i] == '\n') {
if (accumulator.Length > 0) {
printer (accumulator + buffer.Slice(0, i + 1));
accumulator.Clear();
} else {
printer (buffer.Slice(0, i + 1));
}
if (i < buffer.Length - 1) {
// there's text after the last newline, add it to the accumulator
accumulator.Append(buffer.Slice(i + 1));
}
return;
}
}
// no newlines found, add the entire buffer to the accumulator
accumulator.Append(buffer);
Debug.Assert(ConsolePal.OutputEncoding == Encoding.Unicode); | ||
Debug.Assert(bufferSpan.Length % 2 == 0); | ||
|
||
ReadOnlySpan<char> charSpan = MemoryMarshal.Cast<byte, char>(bufferSpan); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't necessarily be two-byte aligned. Is that ok?
@EgorBo could you please respond to the most recent review comments and solve the merge conflict? Thanks! |
@adamsitnik I'll, but the xamarin ios/android stuff was postponed to 6.0 |
Will re-open it once we pass 5.0.0 milestone to keep amount of active PRs smaller. |
Fixes #36440 for both iOS and Android
We have to accumulate content written via Write and flush it only when
\n
is found.Also, fix the iOS sample.