Note that the lisp reader interns symbols, such that independent references to a given symbol give you the exact same lisp object, and consequently you're able to compare them with eq
(which only needs to compare the object addresses).
Conversely, independent strings are always different lisp objects, and therefore you have to compare their contents.
You would therefore expect the eq
comparison to win for performance.
Curiously enough (I'm certainly very surprised), some trivial testing with benchmark-run
is giving string=
the win by quite a margin. This seems very odd to me. YMMV?
Edit: So I just noticed this answer (and its comment) again, and felt inspired to see if I could recreate and explain the result.
n.b. Nothing is byte-compiled initially.
The first realisation was that my symbols were quote
d and the strings were not, and I immediately found that the quote
was responsible for bulk of the speed difference:
(benchmark-run 10000000
(string= "foo" "foo"))
is, for smallish strings, consistently quicker than:
(benchmark-run 10000000
(eq 'foo 'foo))
however, if we also quote the string:
(benchmark-run 10000000
(string= '"foo" '"foo"))
that almost evens things out entirely.
However, on average, unless the string is quite large, the string comparison still seems to win by a hair.
An alternative approach is to bind the objects to variables:
(let ((foo 'test)
(bar 'test))
(benchmark-run 10000000
(eq foo bar)))
(let ((foo "test")
(bar "test"))
(benchmark-run 10000000
(string= foo bar)))
Once again, I'm seeing the string comparison faster by a nose, on average.
After byte-compilation, I'm only seeing a consistent result for the let-bound variable cases, where eq
is consistently faster than string=
(taking about 2/3 of the time).
For the other examples I'm getting nonsensical (to me) outcomes like the quoted strings being quicker than the unquoted strings, which I can only guess is effectively noise from other aspects of the execution and/or benchmark-run
itself. There was enough variety between different runs of the same function to entirely obscure any differences between runs of different functions.
My conclusions are:
(a) eq
comparisons with a symbol can (somewhat counter-intuitively) be slower than a string comparison, if the symbol is quoted.
(b) Unless the strings are rather large, the practical differences are utterly negligible, and so I wouldn't bother converting one to the other for purely performance reasons.