Rails’ symbols: don’t create them dynamically!

February 20, 2009

 
No Gravatar

Symbols are great, we use them in hashes all the time…but did you know, symbols aren’t part of Rails’ garbage collection? When you create them, the memory the use has been allocated permanently! Why is this bad? So if we create a handful of symobls…no biggie, but what if we’re dynamically creating lots and lots of them? Major faux pas!

This was brought to my attention last night when I was trying to create a hash with some dynamic symbols. See below:

 
## here is some data
 
>> hardware = Hardware.find(:all, :limit => 2)
=> [#<Hardware id: 1, name: "Bolts", description: "Lorem ipsum dolor sit amet, consectetur adipisicing...", photo_front_file_name: "144_replica_wheels_Closeout_30_percent_off_prices_l...", photo_front_content_type: "image/jpeg", photo_front_file_size: 80842, photo_angle_file_name: nil, photo_angle_content_type: nil, photo_angle_file_size: nil, created_at: "2009-02-19 11:04:48", updated_at: "2009-02-20 20:29:46">, #<Hardware id: 2, name: "Nuts", description: "Lorem ipsum dolor sit amet, consectetur adipisicing...", photo_front_file_name: nil, photo_front_content_type: nil, photo_front_file_size: nil, photo_angle_file_name: nil, photo_angle_content_type: nil, photo_angle_file_size: nil, created_at: "2009-02-19 11:04:48", updated_at: "2009-02-20 07:18:32">]
>> y hardware.first
--- !ruby/object:Hardware
attributes:
  name: Bolts
  updated_at: 2009-02-20 20:29:46
  photo_angle_file_size:
  photo_front_file_name: 144_replica_wheels_Closeout_30_percent_off_prices_listed_.jpg
  photo_front_file_size: "80842"
  id: "1"
  description: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  photo_angle_content_type:
  photo_front_content_type: image/jpeg
  created_at: 2009-02-19 11:04:48
  photo_angle_file_name:
attributes_cache: {}
 
=> nil
 
## don't do this
for hardware_item in hardware
 formatted[:#{hardware_item.name.downcase}] = hardware_item.description
end
 
>> formatted[:bolts]
=> "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
 
## this is better
for hardware_item in hardware
 formatted[hardware_item.name.downcase] = hardware_item.description
end
 
>> formatted['bolts']
=> "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  • brianlopez
    It should be noted that using/creating "dynamic" symbols is sometimes the *desired* behavior - say for turning a result set into a Ruby Hash.
    In this case, the number of symbols is tied to the number of columns/key names in the result set. And if the result set is large enough, it's actually *more* efficient to use symbols as they're only allocated once. Whereas if string keys were to be used, an incredible amount of memory (and later Garbage Collection) would have to occur on a result set of the same (albeit, large) size.
  • for a noob like me -
    #{hardware_item.name.downcase}
    is creating the symbol?

    And what's the difference between
    formatted["bolts"]
    and
    formatted[:bolts]
    ?
blog comments powered by Disqus