views:

387

answers:

4

We have an application that has one or more text console windows that all essentially represent serial ports (text input and output, character by character). These windows have turned into a major performance problem in the way they are currently code... we manage to spend a very significant chunk of time in them.

The current code is structured by having the window living its own little life, and the main application thread driving it across "SendMessage()" calls. This message-passing seems to be the cause of incredible overhead. Basically, having a detour through the OS feels to be the wrong thing to do.

Note that we do draw text lines as a whole where appropriate, so that easy optimization is already done.

I am not an expert in Windows coding, so I need to ask the community if there is some other architecture to drive the display of text in a window than sending messages like this? It seems pretty heavyweight.

Note that this is in C++ or plain C, as the main application is a portable C/C++/some other languages program that also runs on Linux and Solaris.

We did some more investigations, seems that half of the overhead is preparing and sending each message using SendMessage, and the other half is the actual screen drawing. The SendMessage is done between functions in the same file...

So I guess all the advice given below is correct: * Look for how much things are redrawn * Draw things directly * Chunk drawing operations in time, to not send every character to the screen, aiming for 10 to 20 Hz update rate.

Can you accept ALL answers?

+1  A: 

You should try profiling properly, but in lieu of that I would stop worrying about the SendMessage, which almost certainly not your problem, and think about the redrawing of the window itself.

You describe these are 'text console windows', but then say you have multiple of them - are they actually Windows Consoles? Or are they something your application is drawing?

If the latter, then I would be looking at measuring my paint code, and whether I'm invalidating too much of a window on each update.

Will Dean
+1  A: 

Are the output windows part of the same application? It almost sounds like they aren't...

If they are, you should look into the Observer design pattern to get away from SendMessage(). I've used it for the same type of use case, and it worked beautifully for me.

If you can't make a change like that, perhaps you could buffer your output for something like 100ms so that you don't have so many out-going messages per second, but it should also update at a comfortable rate.

Ryan Fox
+1  A: 

I agree with Will Dean that the drawing in a console window or a text box is a performance bottleneck by itself. You first need to be sure that this isn't your problem. You say that you draw each line as a whole, but even this could be a problem, if the data throughput is too high.

I recommend that you don't use the SendMessage to pass data from the main application to the text window. Instead, use some other means of communication. Are these in the same process? If not, you could use shared memory. Even a file in the disk could do in some circumstances. Have the main application write to this file and the text console read from it. You could send a SendMessage notification to the text console to inform it to update the view. But do not send the message whenever a new line arrives. Define a minimum interval between two subsequent updates.

kgiannakakis
A: 

Are the output windows part of the same application? It almost sounds like they aren't...

Yes they are, all in the same process.

I did not write this code... but it seems like SendMessage is a bit heavy for this all in one application case.

You describe these are 'text console windows', but then say you have multiple of them - are they actually Windows Consoles? Or are they something your application is drawing?

Our app is drawing them, they are not regular windows consoles.

Note that we also need to get data back when a user types into the console, as we quite often have interactive serial sessions. Think of it as very similar to what you would see in a serial terminal program -- but using an external application is obviously even more expensive than what we have now.

If you can't make a change like that, perhaps you could buffer your output for something like 100ms so that you don't have so many out-going messages per second, but it should also update at a comfortable rate.

Good point. Right now, every single character output causes a message to be sent.

And when we scroll the window up when a newline comes, then we redraw it line-by-line.

Note that we also have a scrollback buffer of arbitrary size, but scrolling back is an interactive case with much lower performance requirements.

jakobengblom2