Table of Contents
Why Performance Matters for Beginners
As soon as your scripts start working, you will notice that some run quickly and others feel slow. You do not need to become a performance expert, but learning a few basic habits early will save you time and frustration when your data or simulations grow.
This chapter focuses on simple, practical performance tips that beginners can apply without advanced knowledge of optimization or algorithms. You will see patterns to avoid, and safer patterns to prefer instead.
Vectorization Instead of Unnecessary Loops
MATLAB is designed to work efficiently with whole vectors and matrices at once. This style is called vectorization. In many cases you can replace loops that process one element at a time with a single operation that acts on an entire array.
For example, suppose you want the square of each element in a vector x. A loop version might be
x = 1:1e5;
y = zeros(size(x));
for k = 1:numel(x)
y(k) = x(k)^2;
endA vectorized version is much simpler
x = 1:1e5;
y = x.^2;
The vectorized version is clearer and is usually faster, especially on large arrays. Many built in functions are already vectorized. Operations like +, -, .*, ./, .^, and functions like sin, exp, sqrt, and mean operate on arrays element by element when given arrays as inputs.
Loops are still useful and sometimes necessary, in particular for complex algorithms or when each iteration depends on the previous one. As a beginner, prefer vectorized operations when the task is naturally expressed as a whole array transformation, and keep loops for logic that truly needs step by step processing.
Preallocating Arrays Instead of Growing Them
A common beginner pattern is to start with an empty array and grow it inside a loop. This costs time because MATLAB has to allocate new memory and copy data each time the array size increases.
For example, this style is slow for large n
n = 1e5;
x = [];
for k = 1:n
x(end+1) = k^2;
end
Inside the loop, x becomes longer each iteration, and MATLAB must move data repeatedly.
A faster pattern is to allocate the final size of the array before the loop, then fill it
n = 1e5;
x = zeros(1, n); % preallocate as row vector
for k = 1:n
x(k) = k^2;
end
Use functions such as zeros, ones, nan, or false with the desired size. For a vector of length n, use zeros(1, n) or zeros(n, 1); for an m by n matrix, use zeros(m, n).
When you do need a loop, preallocation is one of the simplest and most effective performance improvements you can make.
Efficient Use of Logical Indexing and Conditions
Logical indexing lets you select or modify multiple elements in one operation, which is often both clear and efficient. For example, to set all negative elements of an array A to zero, a loop might be
for k = 1:numel(A)
if A(k) < 0
A(k) = 0;
end
endA more efficient style is
A(A < 0) = 0;
Here A < 0 creates a logical array, and MATLAB uses it to assign zero to all matching positions in a single step.
Logical expressions like &, |, and ~ work elementwise on arrays, and combining them with logical indexing is often faster than manual looping through indices.
Be aware that logical indexing creates intermediate arrays. For huge data sets you should still pay attention to memory use, but for beginner scale work logical indexing is generally efficient and readable.
Avoiding Repeated Work Inside Loops
If you must use a loop, avoid repeated computations that do not change from one iteration to the next. Every extra call or repeated calculation inside a large loop can slow things down.
Suppose you need sin(x) many times in a loop, and x does not change. A slow pattern is
for k = 1:10000
y(k) = someFunction( sin(x) );
endA better approach is
sx = sin(x); % compute once
for k = 1:10000
y(k) = someFunction( sx );
endThe same idea applies to size queries and indexing. For example, avoid
for k = 1:numel(A)
s = size(A, 2); % same every time
A(k) = A(k) / s;
endInstead compute values that stay constant before the loop
s = size(A, 2);
for k = 1:numel(A)
A(k) = A(k) / s;
endThis habit is simple but useful. It keeps loops tight and avoids needless repeated work.
Choosing Appropriate Data Types and Sizes
Performance is influenced by how much data you store and which data types you choose. Using smaller types when appropriate can reduce memory usage and sometimes improve speed.
For numeric data, the default type is double. For many tasks this is fine and you should not prematurely change types. However, there are cases where another type is more appropriate.
If you store large arrays of integers that represent categories or IDs, you can consider integer types such as uint8, uint16, or int32. For example, image data is frequently stored as uint8 values from 0 to 255 rather than double. This reduces memory by a factor of 8 compared to double for the same number of elements.
When you work with logical conditions and masks, prefer logical arrays created by comparisons, or by functions like false and true. For example
mask = false(1000, 1);uses only one bit per element conceptually, and is memory efficient compared to a numeric array.
As a beginner, do not convert all your data away from double just to chase performance. Instead, become aware that type and array size matter, and choose non default types when they match the meaning of the data and the requirements of the functions you use.
Using Built In Functions Instead of Manual Implementations
MATLAB comes with a large library of optimized functions that are usually implemented in lower level languages for speed. When possible, use them instead of writing your own slower versions in plain MATLAB.
For example, if you want the sum of all elements in an array A, you might write
s = 0;
for k = 1:numel(A)
s = s + A(k);
endThe built in function is simply
s = sum(A);
Similarly, functions like mean, std, max, min, sort, and many others are optimized and outperform equivalent loops written in MATLAB code.
When you face a task, it is worth checking briefly whether a built in function exists before implementing a custom loop. Reading documentation or using the search box in the help browser often reveals a function that does exactly what you need, and usually faster.
Reducing Unnecessary Output and Graphics
Printing large amounts of text to the Command Window or updating figures too frequently can slow your code. Output is relatively expensive compared to calculations.
If you have a loop that displays progress like this
for k = 1:1e5
fprintf('Iteration %d\n', k);
% computations
endyou will notice it runs slowly and floods the Command Window. A better approach is to print only occasionally, or to use a progress indicator that updates less frequently.
You can check performance impact by turning off verbose output temporarily and measuring how long the loop takes with and without displays.
Plots and graphics also cost time, especially if you repeatedly recreate figures or call plotting commands inside tight loops. As a beginner, follow these guidelines.
Create a figure once, then update existing plot data instead of creating new plots in every iteration when possible. For example, you can create a plot, keep the handle, and modify its properties inside a loop.
Avoid drawnow calls in each iteration unless you need real time updates. Each call forces MATLAB to refresh the figure, which can slow processing.
Batch computations together, then plot results at the end, rather than plotting every intermediate step, unless visualization at each step is truly needed.
Measuring Performance with Timing
Guessing about performance is often misleading. A simple and practical way to compare approaches is to measure how long they take. MATLAB provides the functions tic and toc for timing.
For example
tic
% code you want to time
A = rand(1000);
B = A^2;
elapsedTime = toc;
After toc runs, elapsedTime contains the elapsed time in seconds. You can compare two different implementations by timing each under similar conditions, for example
tic
y1 = methodOne(x);
t1 = toc;
tic
y2 = methodTwo(x);
t2 = toc;To get more stable measurements, you can run each method several times and look at typical values rather than a single run, because operating system and other processes can cause variation.
There are also more advanced tools such as the Profiler that show which lines of your code consume the most time. These will be covered elsewhere. For now, basic timing with tic and toc helps you test whether a change truly improves performance.
Working With Reasonable Data Sizes
Beginners sometimes try to load extremely large data sets into memory at once, which can make MATLAB slow or cause memory errors. Performance is not just about speed, but also about staying within available memory.
When you know data is very large, consider these simple strategies.
If possible, load only the variables or parts of files you need, not entire files. Some file formats and functions allow you to read selected columns or rows.
Process data in chunks. For example, when reading from a file, read a portion, process it, and write or store the result before reading the next portion, instead of holding everything in memory at once.
Avoid creating many large intermediate arrays if you can reuse one variable or compute values in place.
Think about whether you truly need full resolution or maximum precision. Sometimes down sampling or using a subset of data is enough for initial analysis or for prototyping.
These habits help you avoid performance problems when files and data grow beyond simple toy examples.
When to Worry About Performance
It is easy to spend too much time optimizing small scripts that already run fast. Early in a project, prioritize correctness and clarity. Only start to adjust for performance when you notice scripts taking longer than is comfortable, or when data sizes grow.
A good approach is to write clear code first, then measure timing to identify real bottlenecks. Apply basic techniques such as vectorization, preallocation, and use of built in functions to the parts that actually matter.
Over time, you will develop intuition about which patterns cost time, and you will naturally write code that is both readable and reasonably efficient.
Important things to remember:
Preallocate arrays before filling them in loops rather than growing them step by step.
Prefer vectorized operations and logical indexing over element by element loops when it fits the problem.
Use built in functions like sum, mean, and sort instead of writing manual equivalents.
Avoid excessive printing and repeated plotting inside tight loops, and measure performance with tic and toc instead of guessing.
Focus on correctness first, then optimize only the parts of your code that are actually slow.