Short answer: use str2func
.
Benchmark
The benchmark will evaluate the function for N
different values of x
.
f='a^x+exp(b)+sin(c*x)+d';
Ns = linspace(1, 1000, 20);
timeEval = zeros(size(Ns));
timeEvalHandle = zeros(size(Ns));
timeStr2func = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEval(i) = timeit(@() useEval(f, N));
timeEvalHandle(i) = timeit(@() useEvalHandle(f, N));
timeStr2func(i) = timeit(@() useStr2func(f, N));
end
figure
plot(Ns, timeEval, 'DisplayName', 'time eval');
hold on
plot(Ns, timeEvalHandle, 'DisplayName', 'time eval');
hold on
plot(Ns, timeStr2func, 'DisplayName', 'time str2func');
legend show
xlabel('N');
figure
plot(Ns, timeEval./timeStr2func, 'DisplayName', 'time_{eval}/time_{str2func}');
hold on
plot(Ns, timeEvalHandle./timeStr2func, 'DisplayName', 'time_{eval handle}/time_{str2func}');
legend show
xlabel('N');
figure
plot(Ns, timeEvalHandle./timeStr2func);
ylabel('time_{eval handle}/time_{str2func}')
xlabel('N');
function y = useEval(f, N)
a = 1; b = 2; c = 3; d = 4;
for x=1:N
y = eval(f);
end
end
function y = useEvalHandle(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = eval(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
function y = useStr2func(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = str2func(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
str2func
vs eval
(without function handle): The results show that even for evaluating the function once, it is around 50% faster to use str2func
than eval
(without function handle). For a large number of evaluations, str2func
may be around 100x faster (depending on the function you are evaluating).
str2func
vs eval
(with function handle): eval
is around 100% slower than str2func
for a single evaluation, but becomes are almost equally fast for a large number of evaluations (eval
is ~5% slower).
eval
with and without function handle: Note that for a single evaluation creating a function handle with eval
is ~50% slower than evaluating it directly.
Conclusion: str2func
is always faster than eval
.
eval
is undesirable for reasons more fundamental than performance – Friaseval
undesirable compared tostr2func
except for performance? – Cowlickeval
is undesirable. Namely, it's hard to debug, it can unexpectedly overwrite workspace data, it isn't compiled for future runs (that's the performance aspect) and strings which are created by concatenation as inputs toeval
can be hard to read. Can usually be avoided, so should be – Dinesenstr2func
, especially the last two items. – Cowlickstr2func
is an alternative toeval
, but I didn't understand why, what cause it be different? Why in that function Matlab can process and access variables rather than ineval
? – Eckardteval
andstr2func
do different things – Friaseval
and not tostr2func
. – Cowlick