Finding bugs can be a daunting task sometimes… Today I was stucked with an error that eventually turned out to be due to a very common mistake. To my defense, it was about a mechanism that is not really intuitive on a first look : drawnow.
In this post, I talk about Matlab calculation thread, Java thread and a very common problem : Why does this stupid call to graphic display is not executed in its time?
Let’s suppose you execute the following code :
figure(1); for i=1:1000 T(i)=cos(i); plot(T); end
First, I know I don’t preallocate. This is intentional.
This code will provide you with a figure with a cosinus curve in the end but you won’t see the plot “filling up” in front of you.
Some might say : it’s because it is calculated too fast by the computer!
In fact, no, here I intentionaly made my code very very bad. No preallocation and a call to graphics in a for loop. Double terrible. So why don’t we see the plot being slowly filled on the screen?
This is due to some very fundamental properties of how graphics and calculations are organized in Matlab and it is VERY important to understand this point.
For the most part, Matlab runs its calculation on a single calculation thread (it is not exactly true, most matrix calculations are multithreads now but that is hidden to you). BUT I am sure you have noticed that when you run a calculation and a GUI, sometimes the GUIs are still responsive. This is because the graphics in Matlab runs on a different thread, a Java thread called the Event Dispatch Thread (EDT). What all of this means?
The EDT is capable of sort of storing all you calls to graphics in a queue as you creates them BUT the Matlab calculation thread has always the priority so Mathworks allowed the calls in the EDT to be executed at certain precise moments. These moments are creating a new figure, use getframe, when you ask for keyboard input, … and going back to the Matlab prompt at the end of your function (which is what happened in our example). A complete list of these moment is available here.
Most of the time, this will be enough as you only cares of taking a look at this graphics when the calculation is finished. So for most users, they won’t even NOTICE that all of this is happening in the background.
However, sometimes, this is not enough. You WANT this figure to be updated and the EDT to be ‘flushed’. Your calculation is very long or you need it for your interface to behave properly. This is the role of drawnow as in this new version of the code :
figure(1); for i=1:1000 T(i)=cos(i); plot(T); drawnow; end
Here drawnow forces Matlab to stop its calculation thread to perform the demanded graphic displays. If you run this code, you will “see” the figure window filling up.
Of course, you should be very very conservative with drawnow. Only use it when needed. I am sure you will understand that stopping a calculation thread for display purposes is not going to make your calculation faster.
Sometimes, the play between the EDT and the calculation thread can be very very confusing. You made those calls to graphics but nothing happens and your computer is sort of stuck in a calculation instead of showing your graph. Most of the time your forgot (as I did) the nearby for loop that is capturing all of Matlab attention. Drawnow is to sort of refocus it on you and stop watching its beautifull calculations…