C
C#2y ago
VeQox

Whats the fastest way to write to the console [Answered]

[StructLayout(LayoutKind.Explicit)]
public struct CHAR_INFO
{
[FieldOffset(0)]
internal char UnicodeChar;
[FieldOffset(0)]
internal char AsciiChar;
FieldOffset(2)] //2 bytes seems to work properly
internal UInt16 Attributes;
}

[StructLayout(LayoutKind.Sequential)]
public struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
}

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteConsoleOutput(
IntPtr hConsoleOutput,
CHAR_INFO[] lpBuffer,
COORD dwBufferSize,
COORD dwBufferCoord,
ref SMALL_RECT lpWriteRegion
);

public static void WriteBuffer(CHAR_INFO[] buffer, short rows, short columns)
{
IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT lpBuffer = new SMALL_RECT() { Left = 0, Top = 0, Right = (short)(Console.BufferWidth - 1), Bottom = (short) (Console.BufferHeight - 1) };
if (hnd != INVALID_HANDLE_VALUE)
{
WriteConsoleOutput(hnd, buffer, new COORD() { X = columns, Y = rows }, new COORD() { X = 0, Y = 0 }, ref lpBuffer);
}
}
[StructLayout(LayoutKind.Explicit)]
public struct CHAR_INFO
{
[FieldOffset(0)]
internal char UnicodeChar;
[FieldOffset(0)]
internal char AsciiChar;
FieldOffset(2)] //2 bytes seems to work properly
internal UInt16 Attributes;
}

[StructLayout(LayoutKind.Sequential)]
public struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
}

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteConsoleOutput(
IntPtr hConsoleOutput,
CHAR_INFO[] lpBuffer,
COORD dwBufferSize,
COORD dwBufferCoord,
ref SMALL_RECT lpWriteRegion
);

public static void WriteBuffer(CHAR_INFO[] buffer, short rows, short columns)
{
IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT lpBuffer = new SMALL_RECT() { Left = 0, Top = 0, Right = (short)(Console.BufferWidth - 1), Bottom = (short) (Console.BufferHeight - 1) };
if (hnd != INVALID_HANDLE_VALUE)
{
WriteConsoleOutput(hnd, buffer, new COORD() { X = columns, Y = rows }, new COORD() { X = 0, Y = 0 }, ref lpBuffer);
}
}
This is what i currently have and it still caps at arround 30fps with 283x480 characters Now it caps and i cant figure out a more efficient way of doing this OhNoOhNoOhNo
38 Replies
Jester
Jester2y ago
only 30fps really? hmm my code is a little different but has +100fps easely <:PES_Think:639363477458255874>
VeQox
VeQox2y ago
what fontsize you got
Jester
Jester2y ago
normal font size but full screen console im also using the new terminal but ik not sure ig thats any faster
VeQox
VeQox2y ago
y, im a fontsize of 1 ..
VeQox
VeQox2y ago
Jester
Jester2y ago
you should probably not call getstdhandle every time you write
VeQox
VeQox2y ago
HmmNoted
Jester
Jester2y ago
you arent allocating a new char info array every write are you?
VeQox
VeQox2y ago
no no its all preallocated
Jester
Jester2y ago
bcuz allocating is slow, you should reuse the array good uhh are you sure its writing to the console thats slow and not something else?
VeQox
VeQox2y ago
well, its the only thing the programm does, everything needed is predone before
Jester
Jester2y ago
<:PES_Think:639363477458255874> personally i use CreateConsoleScreenBuffer and SetConsoleActiveScreenBuffer so replace the stdhandle with my own console buffer and then write to that, idk if that changes the speed
VeQox
VeQox2y ago
Hmm
Jester
Jester2y ago
is there a thread sleep in your code or something? how do you measure the fps
VeQox
VeQox2y ago
nope i keep count of the frames and divide by the ms/1000
Jester
Jester2y ago
with a stopwatch?
VeQox
VeQox2y ago
y
Jester
Jester2y ago
Hmm it's what it's and it's slow i do think it should be at least 60fps though thonk
VeQox
VeQox2y ago
well im writing about 4.075.200 characters to the buffer every second
Jester
Jester2y ago
well thats a lot to ask i guess
VeQox
VeQox2y ago
ik pepehands
Jester
Jester2y ago
write your own "console host" and render in there Clueless
VeQox
VeQox2y ago
im using the windows 10 terminal is there a performance peepoProgramming
Jester
Jester2y ago
<:PES_SadShrug:646092743378206760> its "easy" to write your colors to a buffer and then copy that buffer to a HDC buffer to draw that but WinGDI is getting slower every windows update bcuz the api is ancient
VeQox
VeQox2y ago
maxpain guess thats the only way ...
Jester
Jester2y ago
or spend a month learning directx and win32 to draw at 10 000 fps on the gpu trollface
VeQox
VeQox2y ago
prob gonna take me more than a month using pepecry
Jester
Jester2y ago
maybe a bitmapsource in wpf is fast and easy enough howieyes didnt i do that before thonk
Jester
Jester2y ago
ah here easy dont create a bitmap each frame, you can just write to it again or if you want to stay in the console. maybe just a lower resolution then
VeQox
VeQox2y ago
well, the challenge is to get it to work in the console, but since i cant exceed 30 frames and i dont wanna destroy my mental health learning directx y either that or cap fps meaning skipping 1 frame if the framerate is over 30 fps which is probably the only solution viable at this point 🤷‍♂️
Jester
Jester2y ago
maybe try this you also dont have to do that every write just once
VeQox
VeQox2y ago
1s let me try
Jester
Jester2y ago
also get the width and height of the console just once at the start and ignore resizing
VeQox
VeQox2y ago
did some testing, getting the handle outside with the width and height improved not alot maybe half a frame at the start it spiked 37fps but later went down to 33,4 fps where it stayed for the whole video
VeQox
VeQox2y ago
+ new terminal
VeQox
VeQox2y ago
pepecry guess its just gonna get down to me capping the frames of the video nontheless ty for the suggestions ❤️
Accord
Accord2y ago
✅ This post has been marked as answered!