Threads and messagemanagerlock


#1

i’ve got an app that does some processing and then wants to repaint a canvas. i’m doing my processing in a seperate thread from the ui thread which means i must call messagemanagerlock when i wish to paint my component.

it seems that creating a messagemanagerlock takes a bit of time as my thread seems to kick down to about 30% cpu utilization when it gets to the part where it begins to paint pixels. but i can get that cpu usage to kick up to 100% (and make the processing/painting clearly much faster) by simply wiggling my mouse in the window or interacting with any other components.

i’m running on a 1.7gz pentium-m based laptop running windows xp.


#2

So you’re getting the lock and then doing a repaint()?


#3

yeah, here’s what i’m doing in my run() routine:

...

while (!tracerEngine->RenderTiles() && !threadShouldExit())
{
	MessageManagerLock *mmLock;
			
	mmLock = new MessageManagerLock;
			
	canvas->repaint();

	delete mmLock;
}
...

i used a pointer to MessageManagerLock just so i could be explicit about creating a destroying the lock.

i tried the following as well:

while (!tracerEngine->RenderTiles() && !threadShouldExit())
{
        const MessageManagerLock mmLock;
        canvas->repaint();
}

but this actually gets me somewhere about 15-20% of the cpu (as opposed to 25-30% using the explicit new/delete technique). not sure if that’s getting the same amount of rendering done in fewer cpu cycles or if it’s blocking longer. i don’t see how it’d be any different, but it seems to be.

(a side note, in your mmlock sample, you say mmLock goes out of scope but how does that happen? don’t you need braces to define your scope? i’m a total c++ newbie which is also why i gravitated towards the more explicit method of new’ing and delete’ing.)

the RenderTiles() routine uses setPixelAt() to make changes to an Image that is then used in my canvas component’s paint() method via a drawImageAt() call.

depending on the speed of the RenderTiles() routine, i get more or less cpu usage – the faster the routine, the less usage i get implying a constant time hang-up somewhere.

i suppose the problem could also be in the drawImageAt routine… but given the ability to speed up the processing by simply moving the mouse around, it seems to be related to messaging. [edit: actually, now that i think about it – the drawImageAt routine is called in a separate thread so i don’t think it’d be capable of slowing down the render thread.)

btw, i notice the drawImageAt routine calls the more complex drawImage routines (the ones that can scale). is there a more direct way to get an image to your component in a 1:1 fashion?

edit: addendum - stowing any of the juce windows causes an even more extreme slowdown - taking 30% down to 10-12%. i can wiggle my mouse in a still open window and get it up to 80% or so…

i will try this on my 3.0ghz p4 with hyperthreading later to see how it likes it. also, this is a debug build at the moment.

thanks!


#4

okay i just tried adding some timing code to see what’s going on…

Time timeManager;
int64 renderTotal = 0;
int64 overheadTotal = 0;

		renderTotal -= timeManager.getHighResolutionTicks();

		while (!tracerEngine->RenderTiles() && !threadShouldExit())
		{
			MessageManagerLock *mmLock;

			overheadTotal -= timeManager.getHighResolutionTicks();
	
			mmLock = new MessageManagerLock;
			
			canvas->repaint();

			delete mmLock;

			overheadTotal += timeManager.getHighResolutionTicks();
		}
		
		renderTotal += timeManager.getHighResolutionTicks();

the result is that the overheadTotal is about 80% of the renderTotal in the case where i just let it go without playing with my mouse… assuming i coded that time stuff correctly…

doing mouse donuts while rendering causes the overhead to drop to about 13%. which is still pretty high (tho i might have not started my gyrations till a few iterations into the thing).


#5

i’ve worked around this issue by implementing a timer class into my canvas container window. every second it repaints the canvas. i’m curious if i need to then implement some pixel locking or if it’s fine to have one thread be an exclusive writer and another thread be an exclusive reader…


#6

hmm. This is interesting…

Before the message asks windows to dispatch a message, it takes the message lock - so what’s happening is that when there’s no message currently pending, windows sits and waits for one, while still holding the message lock.

What I’ll do is to change it to only take the lock once a message arrives. I think that’ll sort it out.

But for stuff like this I’d never use a message lock anyway - if instead you use an AsyncUpdater, it’ll be a bit more efficient too. The thread can call triggerAsyncUpdate() without needing to lock anything, and in handleAsyncUpdate() you’d do the repaint().


#7

AsyncUpdater, eh? okay. i’ll give it a gander. thanks!


#8