Debugging, Profiling, & Style Guidelines in Matlab
by Matt Dunham
Contents
Intro
Matlab code is very flexible, particularly with respect to its dynamic typing, however, this can also lead to enormous headaches when it comes time to debug a crashing program. You may have overwritten or misspelled an important variable without knowing it, or inadvertently expanded the size of your matrix, and Matlab will happily continue executing without warning until your program grinds to a halt. Trying to discover the original problem that started dozens of lines before or in another function is not always easy.
In this section, we describe a number of tools and techniques that can help as well as ways to assess the speed of your code and find potential bottlenecks. We finish by discussing a few stylistic points and best practices that can make your code more readable and less prone to bugs in the first place.
Useful Functions
dbstop, dbquit, dbclear, dbstep, dbstep nlines, dbstep in, dbstep out, dbcont, dbstatus, keyboard, workspace, tic, toc, profile on, profile off, profile viewer
M-lint Warnings & Errors
Matlab automatically checks for certain problems and suggests fixes as you edit your m-files. The problem code is underlined in red much like word processors underline misspelled words. It is worthwhile paying attention to these as they can often point out problems before you run your code and frequently suggest ways to speed up execution. The suggestions appear when you hover your mouse over the underlined text, and you can quickly find these spots by looking for the red markers to the right of the document. The warnings and errors M-lint warns you about can be set under File->Preferences->M-lint.
In newer versions of Matlab, you can generate a full M-lint html report by going to Tools->Save and Show M-lint Report. You can also bring up a file dependency report or compare two versions of a file from the Tools drop down menu.
Stop! if Errors/Warnings…
If your program is crashing or displaying cryptic warnings, it is very useful to have it automatically halt execution right at the point where it ran into trouble. Select Debug –> Stop if Errors/Warnings to turn this on.
Break Points
Break points can be set at any line in the document that executes code by pressing just right of the line number. A small circle will appear and will turn red when the file is saved.
These can be temporarily disabled by right clicking on them and selecting disable. To clear them all, type dbclear all or press the equivalent tool bar button.
You can set a condition on the breakpoints so that it is only triggered if a variable takes on a certain value, by right clicking on the variable and selecting ‘Set/Modify Condition’.
Once your code has stopped at a breakpoint, you can step one line at a time, continue on until the next break point, or exit debug mode completely using the tool bar buttons at the top of the editor.
The step in and step out buttons, let you enter into, or leave a function called at the current line.
There are function equivalents to these commands if you prefer, namely dbstep, dbstep nlines, dbstep in, dbstep out, dbcont, and dbquit. The dbstop() function can be used to set breakpoints and the dbstatus() function displays all of the breakpoints currently set. You can save these into a variable as in s = dbstatus(), clear the breakpoints and then reset them at a later point with dbstop(s).
When you are in debug mode, the command window prompt will look slightly different: it will have a k in front.
The keyboard() function can also be used to stop execution of a program, temporarily relinquishing control back to the command window. Simply add the line keyboard anywhere in your file to stop at that point. To return execution, type return.
Variable Stacks
Once execution has stopped because of a break point or keyboard() command, you can inspect the current values of the variables in the workspace window. Type workspace at the command prompt if it is not already open. If your program contains or calls multiple functions, you can move among the variable stacks from the top of this window, (next to where it says Stack:). This is particularly useful if your program stopped in a third party function and you want to return to your function’s stack to see what went wrong. You can also view the base workspace from here.
You can also execute commands at the command prompt while execution has stopped, and assign new values to existing variables.
Run Configurations
Each m-file has one or more run configurations associated with it as seen in the image below. These can be used to setup tests for your function by specifying test input values and other validation code. You can reach this window by selecting Debug –> Run Configuration for yourfile.m–> Edit Run Configuration…. Add new configurations with the + button and edit the code to execute on the right. These can then be run from the Debug drop down menu or from the run button in the editor.
Profiling & Timing Code
We have already seen the tic() and toc() functions, which can be used to time how long your code takes to run. Simply run tic() before your code and toc() after. Matlab, however, has a much more powerful framework, called profiling, which gives you a detailed report about how long was spent executing each subfunction. You can use this report to find bottlenecks that you might be able to improve.
You can turn on profiling with the profile on command and turn it off again with profile off. Once profiling is on, execute your code, and then type profile viewer to see the report.
The report shows a breakdown of all the functions called from your function, the number of times they were called, and the total time spent executing them. Self-time, denoted by a dark blue band, is the the time spent within a function not including how long was spent in functions called from here. This is really the statistic you should pay attention to.
Style Guidelines
There is a lot of Matlab code floating around and too much of it is totally unreadable. It does not have to be this way. Readable code is easier to use, maintain, debug, and extend, and can often serve to communicate your ideas, particularly when they are mathematical in nature. What makes one piece of code more readable than another is somewhat subjective, but there are fairly uncontentious and straightforward heuristics we can nevertheless employ. We describe a few here. Many of these suggestions are from Richard Johnson’s Matlab Programming Style Guidelines available here.
Layout
Taking the time to organize and layout your m-file well, can help you find bugs later and jump to the code you are looking for much faster.
Use indentation to denote scope, indenting the code in function bodies, and further indenting the code within loops, switch statements, try/catch blocks as well as nested functions.
Include spaces around operators like ||, &&, ==, etc and consider breaking long commands into multiple lines by using ellipses, (…). Keep lines to less than say 80 characters long and be consistent throughout.
Align variables and values by equal signs and commas to show parallel structure.
plot(Xequal,f(Xequal), ‘o’ ,’MarkerFaceColor’ , ‘g’…
,’MarkerEdgeColor’ , ‘k’…
,’LineWidth’ , 2 …
,’MarkerSize’ , 10);
Matlab programmers seem to love packing as much into a single line of code as possible. When you can not think of an informative name for a temporary variable, passing values from one function directly to another via composition is not a bad approach. It is certainly better than having variables with names like temp1 and temp2 floating around. However, this approach can be taken to extremes too. If you find yourself squinting at a line of your own code, trying to decipher its purpose for more than a few seconds, consider breaking it into multiple commands.
Comments
The easiest way to make your program more readable is to document it well, however, this is no substitute for well written code, which should ’speak’ for itself. If you find yourself commenting many lines of code, consider adding greater structure, by writing subfunctions for instance. Subfunctions with well chosen names self document their behavior and help to abstract the details.
Assume programmers reading your code want to know how it actually works and will not be satisfied by assurances in the comments. Make it as easy as possible for them, (and yourself) to verify the correctness of your program.
Comments should be written directly below function headers as this is where the Matlab help functions look in calls to help() and doc(): lookfor() searches only the first line of comments in a function, and so this should be particulary concise and informative. The same applies to class definitions.
It is very important to describe the inputs and outputs to your function as well as any expectations or preconditions. Does your function work with unstandardized data, or missing values? What can the user of your function expect as output so long as the preconditions are met?
Provide examples of all of the important ways in which your function can be called. If you have 6 optional parameters, you do not have to show all 6 factorial possibilities, but include enough, (say 6), so that the user can reasonably extrapolate as to what a particular combination will do. Consider writing a separate function or script to demonstrate certain functionality in context. Separate advanced or infrequently used options and comment on these below the rest. When in doubt, follow the style of built in Matlab functions.
Consider using process_options() written by Mark Paskin, when a function takes many inputs. This allows users to call your function with the inputs specified in any order they like, preceded by a string name as in the following. myfunc(‘niterations’,3,’maxdepth’,5,’verbose,’true)
We describe _process_options in more depth here.
Variable Names
It should go without saying that variable names should be meaningful and informative; part of this, however, is a matter of convention. Here are some suggestions.
- Short, single letter variables should only be used in one of three cases: where the structure of the algorithm is important, as in a mathematical derivation; for local temporary variables such as loop indices; or when well defined conventions exist. In all of these cases, document their meaning through comments.
- Use lower case variable names when there is only one word, or when one of two words is very short as in isvalid, otherwise use camelCase.
- Capitalize constant variables whose values will not change.
- Prefix variables denoting a number of elements with the letter n as in nvalues for the number of values.
- Suffix variables storing indices with NDX as in dataNDX
- Prefix logical functions with is as in isfinite().
- Use i,j,k for loop variables.
- Do not use any magic numbers, i.e. constant values appearing out of nowhere. Rather, assign these values to variables with descriptive names and use these instead.
- Be consistent with pluralization for non-scalar data, i.e. pick one of value(j) or values(j) and use that convention throughout.
- Resuse variables names only when the data is related and even then, with caution. It can be very confusing when a variable you have been tracing through a program suddenly changes role.
See the section on Functions for more suggestions.
Popularity: 1% [?]
Related Posts
Comments
2 Comments on Debugging, Profiling, & Style Guidelines in Matlab
-
Adam Kay on
Thu, 22nd Jul 2010 15:38
-
Li-aung Yip ("Lewis") on
Wed, 1st Sep 2010 03:20
Using i,j and J for loop variables is NOT recommended as the document saids,they are used for complex numbers and redefinig them will cause major issues,be more careful Admin!!!
[Reply]
Using i or j for loop variables is a Bad Idea, since i and j are already used for the imaginary unit.
If you use them for anything else, they will be redefined to mean something other than “square root of -1″, which will play havoc with any calculations involving complex numbers.
[Reply]
Tell me what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!
Include MATLAB code in your comment by doing the following:
<pre lang="MATLAB">
%insert code here
</pre>


















































