Console.Writeline Slow

Console.WriteLine slow

You can use the OutputDebugString API function to send a string to the debugger. It doesn't wait for anything to redraw and this is probably the fastest thing you can get without digging into the low-level stuff too much.
The text you give to this function will go into Visual Studio Output window.


[DllImport("kernel32.dll")]
static extern void OutputDebugString(string lpOutputString);

Then you just call OutputDebugString("Hello world!");

Console.Writeline Effect on Performance

There may be two issues with Console.WriteLine in regards to performance:

  1. IO is not typically a "fast" operation.

  2. Calls to WriteLine are synchronized, i.e. if two threads want to write, one of them blocks on the WriteLine waiting for the other to finish writing.
    From MSDN on console:

I/O operations that use these streams are synchronized, which means
that multiple threads can read from, or write to, the streams.

That said, the only way to understand if the time spent on Console.WriteLine has an impact on the performance of your specific application is profiling it. Otherwise it's premature optimization.

Why is the speed of Console.WriteLine more inconsistent than Debug.WriteLine?

Luckily for us Microsoft has released the source code of the .NET platform here

A quick inspection shows that Debug.Writeline uses the Writeline method of the TraceInternal class. You can see an example here and the TraceInternal method here

As you can see there are a lot of stuff going on involving hooked TraceListeners, locks etc. So we can assume that Debug.WriteLine should be slower in general but only if there are any "extra" TraceListeners configured and of course other IDE parameters that in some way interfere with the Debug infrastructure.

The Console.WriteLine method uses the TextWriter.WriteLine method which is designed to be fast (at least as fast as possible, take a look at their comments).

About the inconsistency that you ask it isn't easy to answer (and IMO you should not try to answer) because of three reasons:

  1. When you are developing in a high level language or platform like
    .NET then you should not bother of how much time the "internals"
    take because you can not have any control on them. I mean that you
    cannot make the WriteLine methods faster unless you write your own
    "faster" versions but that beats the purpose of using a high level
    platform anyway. I hope you can see my point here.
  2. When you are using some methods (like WriteLine) in order to output
    the time some other code of yours took to execute then you should
    not bother how much time the output method takes to complete as long
    as the result is accurate. If for example the WriteLine takes 2 seconds to show you that the code you are measuring took 1ms to complete then the 1ms is what matters even though you waited 2 seconds to find it out. If the output method is too slow then you should change your measuring method, in your case, for example, it might be faster to have a counter variable in your loop and display (WriteLine) the result at the end of it.
  3. When you are developing software intended to run in multi tasking
    systems like windows you should not expect that the same code will
    always take the same time to execute every time simply because there
    are a ton of other (outside your app) parameters that can (and will)
    affect the overall performance of the system. That's why (and I am sure that you already know it) we have the restart option in a very easy to access place (LOL).

Nevertheless to finalize my answer the inconsistency of your timings depends on many factors that makes it worthless to find out why it happens. However, in your code I noticed that you are using the statement:

Dim Watch As Stopwatch = Stopwatch.StartNew()

inside the loop which is a bad thing to do because as you can see in the Stopwatch code here it creates a new instance every time which is a time consuming operation. I believe that if you have it outside of the loop like:

Dim Watch As Stopwatch = Stopwatch.StartNew()
For i As Integer = 1 To 1000
Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time1")
Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time2")
Next

You will get more "consistent" results but I haven't test it though. Moreover it might be wiser to use higher timing resolution like

Watch.ElapsedTicks

because it will give you more accurate results and because if you look at the source code here ElapsedMilliseconds uses a slightly different version (maybe slower) of ElapsedTicks to calculate the milliseconds.

Hope this helps.

Why is Console.WriteLine(i + ) faster than Console.WriteLine(i) in C#?

When I looked at source code, I saw this:

i + "" = String.Concat(object) which call obj.ToString()
There is one more String.Concat(object). So it is slower.

1st way) With Console.WriteLine it is simple:

    public static void WriteLine(String value)
{
Out.WriteLine(value);
}

https://referencesource.microsoft.com/#mscorlib/system/console.cs,5ac7c4fda643413b

Internaly it creates 1 buffer with value + '\r\n' and call .Write(char[], int, int) only once.

2nd way) When you call it with int, it is different.

    public virtual void WriteLine(int value) {
Write(value);
WriteLine();
}

https://referencesource.microsoft.com/#mscorlib/system/console.cs,82d5745bf4a5ecc6

That way it calls Write(char[], int, int) twice. And it can be that slowdown but I can't tell for sure. It is only the hint, where the problem can be.

EDIT:

Additionaly the 2nd way, it calls int.ToString(IFormatProvider) to get string representation of number where is another overhead that can slow it down a little because it can get the instance of that provider every time.
https://referencesource.microsoft.com/#mscorlib/system/globalization/numberformatinfo.cs,9c4284b5db21c23a

C# Something faster than Console.Write()?

There's basically two approaches: render less, and render faster.

Render less is usually more tricky, but also tends to be less intensive. The classic example would be Carmack's Keen games - the PC didn't have the guts to rerender the whole screen at once, so Carmack made sure only the parts of the screen that actually change get redrawn. In your case, this can be as simple as checking the new screen against the old screen (without using the Console methods, of course) - depending on the kind of game you're writing, this can save you a huge amount of work.

Render faster is usually easier. The usual approach in the olden days was to get direct access to the output buffer - instead of having the playfield in separate memory, you had it directly in the graphics card - which was quite capable of redrawing the entire screen as fast as needed, of course, since otherwise you wouldn't ever see much on your CRT screen. This option is still accessible as backward compatibility, so you can still use it if you code your application in, say, Turbo Pascal, but it's not really all that easily accessible in C#. There is an option in rendering the whole screen in a StringBuilder first, and then Console.Write that all at once. It's going to be quite a bit faster, but it's not exactly stellar. char[] will allow you an extra point of performance - you can represent your playfield directly as char[][] and then you don't have to recreate the StringBuilder every time you change something - you just have to Console.Write once for each playfield line.

And of course, you could simply write out the changes as soon as they occur; depending on the game you're writing, this can range all the way from "trivial with great results" to "pretty hard and not looking good". And since the buffer area of the console can be bigger than then window size, you could even draw it out to a hidden part of the buffer, and then use Console.MoveBufferArea to draw the whole change at once - this is usually called "backbuffering". I'm not sure if it will look good, though - the console window nowadays allows you to scroll in the buffer, which can be detriminal for your use case.

There's still ways to get much faster access to the console buffers, but not while staying fully in .NET - you'll need to use P/Invokes. A great answer on this topic is here - How can I write fast colored output to Console?. On modern systems, this is pretty much equivalent to using a back buffer and "drawing" it all at once - it's incredibly fast. And again, you can use the back buffer for your game data directly - it worked 20-30 years ago, and it still works today; it's good practice in playing around with limited resources. Can you write a game that only really uses the console text buffer for everything, or at least almost everything? It's pretty fun playing around with stuff like that; you can write a whole plethora of games like this, including games like Tetris or Lode Runner. Of course, this will only work on Windows, so if you want to support other systems, it's a lot trickier.

And finally, you can just write your own console (or better, use someone's already written and tested). It's a good practice if you want to go on to greater challenges over time, and it will allow you to play around with more powerful technologies over time. The typical example would be games like Dwarf Fortress - still text based, still console-like, but actually drawn graphically, using technologies like SDL. Not only is this vastly faster on modern systems (since you have no easy way to access the text buffers directly), it also opens up the option of changing over to graphical tiled game rather easily. It's yet another stepping stone on the stairway to cool stuff :))

Console.WriteLine speeds up my code?

After reading a very similar question with no answers I may have found the issue. In the comments section a user (ForguesR) made the following comment:

It is really a big guess : maybe because you are writing to IO your thread gets more processor time because WriteLine is synchronized and thus blocking other threads.

So I wanted to check if this was indeed the case so I changed SomeMainMethod to like the following:

NOTE: It is generally not advised to play around with thread priorities, this was only a workaround to test the theory. I would strongly advise against doing this in production code unless you are 100% sure you know what you are doing. Then probably still stay away from it.

private void SomeMainMethod()
{
System.Threading.ThreadPriority tp = System.Threading.ThreadPriority.Normal;
try
{
tp = System.Threading.Thread.CurrentThread.Priority;

System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
SomeMethod();
sw.Stop();
Console.WriteLine("Time for SomeMethod = {0}ms", sw.ElapsedMilliseconds);

sw.Reset();
sw.Start();
SomeOtherMethod();
sw.Stop();
Console.WriteLine("Time for SomeOtherMethod= {0}ms", sw.ElapsedMilliseconds);

//...
}
finally
{
System.Threading.Thread.CurrentThread.Priority = tp;
}
}

After making this change my code now runs consistently faster (~10ms) when the Console and Stopwatch lines are commented out. Therefore I believe his comment was probably correct, at least in my situation.



Related Topics



Leave a reply



Submit