Solved

Windows Message Queue Saturation

Posted on 2008-10-27
14
998 Views
Last Modified: 2013-11-20
I am trying to add support for custom features to a piece of software. The code for these features is using a sdk from a third party driver (wacom driver for tablet devices). The software I am working on is very large, and I have noticed the previous programmers have chosen to send a lot of windows messages back in forth, instead say using a function call instead. So there are periods in the software where a lot of processing is going where the windows message queue is getting extremely backed up.

Now, the way the hardware works is that it sends packets whenever an event occurs (pen touched screen, button was pressed, etc). The hardware will also send a windows message upon packet arrival (this is how my code will know when to process packets and then flush them from the queue). So as you can guess, what is happening is a buffer overflow sitation in which packets are being sent, but are not properly flushed from the queue because the windows message associated with them is backed up in the windows message queue and is not reaching the code in time. I have already increased the packet buffer size to its limit.

So, this code is large, redesign is not possible. That leaves other options on the table. I have considered in the past making the class responsible for packet handling a user interface thread and setting up a separate message queue for handling packets but this did not work real well. I am open for advice at this point on what to do.
0
Comment
Question by:steenpat
  • 5
  • 5
  • 4
14 Comments
 
LVL 14

Expert Comment

by:wayside
ID: 22815969
Put the code that interfaces with the hardware into a separate exe, and have that exe fire the windows events to the main program. In essense, move the packet buffer from the driver into your program where you can have an unlimited buffer size.

You might also be able to condense out some of the events, for example if there are multiple pointer moves in a row, skip them. This will lower the message traffic to the main program as well.
0
 

Author Comment

by:steenpat
ID: 22816930
"Put the code that interfaces with the hardware into a separate exe, and have that exe fire the windows events to the main program. In essense, move the packet buffer from the driver into your program where you can have an unlimited buffer size."

Making a separate exe is an option, even though I'm not crazy about it. Wouldnt it be possible to somehow handle packets on a separate thread instead of making a new exe?
0
 
LVL 14

Expert Comment

by:wayside
ID: 22817028
> Wouldnt it be possible to somehow handle packets on a separate thread instead of making a new exe?

Well, you indicated that you tried this and it didn't work satisfactorily. What happened when you tried it?

You could try running the thread at an elevated priority, that would give it more cpu cycles.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22817482
>>>> Making a separate exe is an option,

Really? Why should the overhead of an additional process and the need of interprocess communication help to make performance issues smaller?

>>>> Well, you indicated that you tried this and it didn't work satisfactorily.
If somewhat doesn't work at the first approach, try somewhat completely different? Is that the message?

>>>> So as you can guess, what is happening is a buffer overflow sitation
No. A buffer overflow is when you write beyond buffer boundaries, not when a queue can't be processed in time.

You need to find out what is the bottle-neck. I actually doubt that your message queue can't respond in time but guess that you have some handlers (handler functions) which make some lengthy jobs (or even have waits) when being called from the message queue. Of course, the driver should use *new* memory for each packet. If the driver would use the same piece of memory for every write, you would need a realtime operation system to make that work. If using new memory, the only limitation is the (virtual) memory available and I really can't think that this can be a  issue in these days. The only important thing is that you keep your message pump fast. That implies that any handler function must return nearly at once and none does any lengthy operations, e. g. database queries or network communications. These parts either must be splitted into small pieces where the pieces were processed with a message queue timer or must be moved to threads.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22817504
>>>> You could try running the thread at an elevated priority
I don't agree again. Normaly the bottle-neck is the queue and not the threads. By giving (worker) threads a higher priority you would slow down the message pump.
0
 
LVL 14

Expert Comment

by:wayside
ID: 22817574
> No. A buffer overflow is when you write beyond buffer boundaries, not when a queue can't be processed in time.

My interpretation of the OP's post is that the packets are buffered in the *driver* until a Windows message is received and the packet then removed, and the driver (not being the OP's code) can only be configured to hold so many packets.

> Why should the overhead of an additional process and the need of interprocess communication help to make performance issues smaller?

Thus, by moving the handling of the driver messages to a separate exe that can respond to the driver in a timely way, the packets can be moved out of the driver and buffered in the exe, which can be virtually unlimited in size.

Besides, process overhead is not very large once the process has started.

> The only important thing is that you keep your message pump fast. That implies that any handler function must return nearly at once and none does any lengthy operations, e. g. database queries or network communications. These parts either must be splitted into small pieces where the pieces were processed with a message queue timer or must be moved to threads.

OK, I think this violates the "redesign is not possible" statement of the original poster.

> If somewhat doesn't work at the first approach, try somewhat completely different? Is that the message?

How does this contribute to helping the poster? I'm not trying to send any "message", I merely suggested an alternative, I didn't claim it was the only, or even the best, solution. What is your point?
0
 
LVL 14

Expert Comment

by:wayside
ID: 22818434
Can you poll the driver to see if there are any packets available?

If so you could set up a thread to poll for and retrieve the packets and put them in a buffer, and then have another thread which will process them. If you don't poll too often, the performance hit should be very small.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:steenpat
ID: 22821541
"Can you poll the driver to see if there are any packets available?"

That's actually another alternative. As I read in the documentation you can either poll for packets or wait for 'packet events' i.e. a WT_PACKET message.

"If so you could set up a thread to poll for and retrieve the packets and put them in a buffer, and then have another thread which will process them. If you don't poll too often, the performance hit should be very small."

I guess that is the catch because I would need to poll often for something as simple as setting the cursor on the screen based on where the pen is touching. I will definitely look into it though as it may be the only feasible alternative right now.

"My interpretation of the OP's post is that the packets are buffered in the *driver* until a Windows message is received and the packet then removed, and the driver (not being the OP's code) can only be configured to hold so many packets."

That's exactly right.
0
 

Author Comment

by:steenpat
ID: 22821908
"You need to find out what is the bottle-neck. I actually doubt that your message queue can't respond in time but guess that you have some handlers (handler functions) which make some lengthy jobs (or even have waits) when being called from the message queue"

I think you might actually have a point here too. I was thinking about it the other day, and it doesn't seem possible that the windows message queue is getting saturated; it seems possible though that the handler responsible for processing the WT_PACKET message is not being called in time to process the packets.

"That implies that any handler function must return nearly at once and none does any lengthy operations, e. g. database queries or network communications. These parts either must be splitted into small pieces where the pieces were processed with a message queue timer or must be moved to threads. "

Like wayside said redesign is not a feasible option. Although that would have a been a better idea from the start.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22822355
>>>> "My interpretation of the OP's post is that the packets are buffered in the *driver* until a Windows message is received and the packet then removed, and the driver (not being the OP's code) can only be configured to hold so many packets."
>>>> That's exactly right.

I recommended to make the message queue faster. Then, the time between sending the message (from the driver) and receiving (by queue) and retrieving (by your handler) would be smaller what should solve the problem.

>>>> Thus, by moving the handling of the driver messages to a separate exe that can respond to the driver in a timely way, the packets can be moved out of the driver and buffered in the exe, which can be virtually unlimited in size.

What are the advantages of a new exe over a thread which does the same?

>>>> How does this contribute to helping the poster?
Hmm. The poster asked you why to have a new exe instead of a new thread. You answered "you indicated that you tried this and it didn't work satisfactorily". I don't think that experts should answer a valid question like that. I think you better should have admitted here that the exe wasn't a good idea.

>>>> OK, I think this violates the "redesign is not possible" statement of the original poster.

If you go from message handling to callback or go from message handling to polling, it is a redesign, right?

If you move lengthy handling from the main thread to a worker thread to make the queue faster, it is a change in one handler function, but not a redesign.

I still think you first should find out why the queue is so slow and then remove the bottle-necks.
0
 

Author Comment

by:steenpat
ID: 22824787
>>>> OK, I think this violates the "redesign is not possible" statement of the original poster.

>>>> If you go from message handling to callback or go from message handling to polling, it is a redesign, right?

What wayside said by that is in reference to this:
>>>> That implies that any handler function must return nearly at once and none does any lengthy operations, e. g. database queries or network communications. These parts either must be splitted into small pieces where the pieces were processed with a message queue timer or must be moved to threads.

Of which he is right because there are sections in the software where a lot of processing is occuring and causing the bottleneck. For me to do what you ask not realistic in terms of the scope of this software.

>>>> I actually doubt that your message queue can't respond in time but guess that you have some handlers (handler functions) which make some lengthy jobs (or even have waits) when being called from the message queue.

Ok again on this point saying that is the case, as far as I know because it seems to me now that is what's happening, there are a million of these functions taking their time and for me to redesign so that each gets its own slice is just not a feasible choice, what is left?

>>>>> If you move lengthy handling from the main thread to a worker thread to make the queue faster, it is a change in one handler function, but not a redesign.

Ok, so by this you are saying to move the packet handler to its own thread or to move every lengthy operation to one worker thread?
0
 
LVL 14

Expert Comment

by:wayside
ID: 22825057
> What are the advantages of a new exe over a thread which does the same?

The new exe will not lose events because its access to messages will not be impeded by other message handlers in the program which are getting in the way.

Ultimately, this may not help the overall user experience that much, because the original program still needs to handle the events at some point, and if it is very busy handling other events then handling the new events might be (will be) delayed. But at least the events won't be dropped.

> If you move lengthy handling from the main thread to a worker thread to make the queue faster, it is a change in one handler function, but not a redesign.

For this to work, there would have to be no dependencies on the completion of the handler and the start of another handler, which is unlikely or the original designers would have used threads, or a lot of complicated synchronization would need to be added to make sure the dependencies were preserved. The switch from single-threaded to multi-threaded is a non-trivial change in architecture, and is unlikely to be as simple as moving a block of code into a thread.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22825371
>>>> The new exe will not lose events
But why should the thread loose events? If the message queue was too slow because of too much messages (or lengthy handling), the thread could peek the queue and pick the one and only message of interest. Or, if once a thread was invoked, the main thread could ignore further messages and the thread  uses any of the other ways to get packets from the driver.  

>>>> and is unlikely to be as simple as moving a block of code into a thread.
Though that is true, there is no alternative if lengthy things must be done. A Windows program must be responsive, and it can't block message processing in favor of some network communications or database queries, especially if there are messages with higher priority.

Another idea is to let the thread have its own (pseudo) window where it can run a separate message loop. Then, the driver could be forced to use that window for its notifications (though normally I am not a friend to let a worker thread make its own messaging).

But, again, first find out out what is wrong and then make a new concept based on the new insights. I often experienced that a wrong behavior was caused by a simple to change code I added in a hurry.

0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
ID: 22825906
>>>> Ok, so by this you are saying to move the packet handler to its own thread or to move every lengthy operation to one worker thread?

The second would be better. But if your analysis said it were too many of them, you may put aside that task for future, and move all the handling of the packets to a thread. Create a pseudo window in the thread - you may use AfxCreateThread which will do that afaik - and make the driver to send its packet notifications to the thread's window. Then, run a normal message loop or simpler something like

   while (PeekMessage(msg, ..., PM_REMOVE))
   {
         if (msg.message == WM_USER_PACKET)
             handleMessage();
   }
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now