IÃ±aki Baz C. wrote:
I could use strings as keys instead of symbols, but I’ve checked that
getting a Hash entry is ~25% faster using Symbols.
The problem is that I could receive custom headers so for each one a
new Symbol would be created. An attacker could send lots of custom
headers to fill the server memory and cause a denial of service.
Perhaps this is solved in Ruby 1.9? any suggestion on it? Thanks a lot.
It’s not “solved” in 1.9, because this is intentional and necessary
The important property of a symbol is that it has the same id wherever
and whenever it is used in your program, and hence it can never be
garbage-collected. This is so that it can be used for looking up method
names - foo.bar is a shortcut for foo.send(:bar)
Using symbols for hash keys is a common idiom, but arguably is abuse of
the symbol table. It’s fine as long as all the keys are fixed symbol
constants in your program, but as you’ve observed, it causes huge
problems if your symbols are generated dynamically in response to user
data (especially from untrusted or potentially malicious sources)
The solution: use strings as keys, and beware premature optimisation.
Whilst you may have measured that “getting a Hash entry is 25% faster
using Symbols”, does this really make your whole application 25% faster?
I suspect not. Maybe it makes your whole application 0.25% faster. Maybe
it makes your application slower, as each incoming String has to be
converted into a Symbol.
In any case, although we all want things to go “as fast as possible”,
few applications have a specific acceptance criteria for CPU utilisation
or response time. If your application does have a specific performance
criterion that you must meet, then it might be better to consider a
different language, rather than mis-using what Ruby offers. Or including
all things like development costs, it may be more cost-effective to
choose faster hardware to meet the performance goal.