Performance and Best Practices for Fast Code
Memory: a double costs 8 bytes, so a 1000×1000 matrix takes 8 MB; single, integer classes and sparse storage reduce memory.
Concept
Vectorize element-wise work (Module 13).
Preallocate arrays that loops fill (zeros, ones, cell).
Use built-ins — they're compiled and optimized (sum, cumsum, sort, find, \).
Access memory in column order (MATLAB is column-major): loop over rows in the inner loop when working element by element on a matrix.
Solve, don't invert: A \ b beats inv(A) * b in speed and accuracy.
Avoid repeated work inside loops (move constant computations out, avoid growing strings or cells).
Measure with tic/toc, timeit (MATLAB, more reliable), and the Profiler (profile on; ...; profile viewer) to find hot spots.
Scale up: parfor and parfeval (Parallel Computing Toolbox), gpuArray (GPU), tall arrays for data larger than memory, MEX files and MATLAB Coder to generate C/C++ for critical parts.
Memory: a double costs 8 bytes, so a 1000×1000 matrix takes 8 MB; single, integer classes and sparse storage reduce memory.
Why It Matters
Measurement datasets grow to gigabytes and simulations run thousands of times in parameter sweeps; the same algorithm can differ 100× in run time depending on how it's written.
Syntax
tic; result = heavy(); t = toc;
profile on; run_analysis; profile viewer
y = zeros(1, n); for k = 1:n, y(k) = ...; endExample
29.1 Measuring the effect of vectorization, preallocation and backslash
N = 2e5;
x = rand(1, N);
tic; y1 = zeros(1, N); for k = 1:N, y1(k) = x(k) ^ 2 + 3 * x(k); end; tLoop = toc;
tic; y2 = x .^ 2 + 3 * x; tVec = toc;
fprintf('loop vs vectorized: same result %d, vectorized %.0fx faster\n', max(abs(y1 - y2)) < 1e-12, tLoop / tVec)
tic; s = []; for k = 1:2e4, s(end + 1) = k; end; tGrow = toc;
tic; s2 = zeros(1, 2e4); for k = 1:2e4, s2(k) = k; end; tPre = toc;
fprintf('growing vs preallocated: preallocated faster %d\n', tPre < tGrow)
A = rand(500);
tic; for k = 1:20, B = A(:, 1); end; tCol = toc; % column access: contiguous (column-major)
tic; for k = 1:20, B = A(1, :); end; tRow = toc;
fprintf('column slice and row slice both work; MATLAB stores arrays column by column\n')
M = hilb(10); % a badly conditioned matrix
b = M * ones(10, 1); % exact solution is all ones
x1 = inv(M) * b; x2 = M \ b;
fprintf('residual norm: inv(M)*b %.1e, M\\b %.1e\n', norm(M * x1 - b), norm(M * x2 - b))
v = 1:10;
fprintf('logical indexing picks evens: %s\n', mat2str(v(mod(v, 2) == 0)))
fprintf('memory of a 1000x1000 double matrix: %.1f MB\n', 1000 * 1000 * 8 / 1e6)Expected Result
Vectorization and preallocation each paid off, and on the badly conditioned hilb(10) system the backslash operator gave a residual about ten orders of magnitude smaller than inv(M)*b. The speed-up factors depend strongly on the interpreter and the machine: MATLAB's JIT compiler makes simple loops much faster than Octave does, so in MATLAB the loop/vectorized gap is usually smaller — but still worth closing in hot code.
loop vs vectorized: same result 1, vectorized 569x faster
growing vs preallocated: preallocated faster 1
column slice and row slice both work; MATLAB stores arrays column by column
residual norm: inv(M)*b 3.4e-05, M\b 4.7e-16
logical indexing picks evens: [2 4 6 8 10]
memory of a 1000x1000 double matrix: 8.0 MBCommon Mistakes
Optimizing without measuring.
Growing arrays in loops.
Using inv for solving systems.
Converting data types repeatedly inside loops.
Premature parfor on small tasks (overhead exceeds the gain).
Best Practices
Write clear code first, then profile and optimize the hot 10 %.
Keep vectorized code readable; comment non-obvious tricks.
Use timeit in MATLAB for reliable micro-benchmarks.
Interview Relevance
High for MATLAB roles: "how do you speed up MATLAB code?", "why preallocate?", "what is vectorization?", "how do you find bottlenecks?", "what is MEX / MATLAB Coder?".
Practice Questions
Profile a script and identify its slowest line.
Vectorize a double loop that computes a distance matrix.
Compare a for loop over rows vs over columns for summing a 5000×5000 matrix element by element.
Estimate the memory needed for 10 channels × 1 hour × 10 kHz of double samples.
Quick Quiz
Q1. (Multiple choice) Which is usually fastest for summing squares of 1e6 numbers? A) A for loop growing an array B) A preallocated loop C) sum(x.^2) D) arrayfun Answer: C.
Q2. (Predict the output) Memory of a 1000×1000 double matrix?
Answer: 8.0 MB (verified).
Q3. (True/False) A \ b is both faster and more accurate than inv(A) * b.
Answer: True (verified faster in the example; also numerically better).
Q4. (Find the bug) A loop builds a report with txt = [txt sprintf(...)] for 100 000 lines and is very slow.
Answer: The text grows each iteration; collect lines in a preallocated cell array and strjoin once, or write to a file incrementally.
Coding Challenge
Compute the pairwise Euclidean distance matrix of 500 random 2-D points without loops (implicit expansion), and print its size, its maximum and whether its diagonal is zero.
rng(3);
P = rand(500, 2);
D = sqrt((P(:, 1) - P(:, 1)') .^ 2 + (P(:, 2) - P(:, 2)') .^ 2);
fprintf('size %dx%d, max distance %.4f, zero diagonal: %d\n', size(D), max(D(:)), all(diag(D) == 0))