Ruby:冻结数组中的字符串是否也应单独冻结?

时间:2015-11-18 10:22:37

标签: ruby-on-rails arrays ruby string

Ruby 2.2.3,Rails 4.2.1

我有大量的字符串数组,我将其定义为常量,以便在整个应用程序中使用。它们是各种ISO国家代码,语言代码,这类东西,所以有两到四个字符,每个字符都有数百个唯一值。

不同的数组是这些的集合,因此NORTH_AMERICA_COUNTRY_CODES可能是十几个国家代码的数组,AFRICA_COUNTRY_CODES可能是大约60个数组。其中许多重叠(例如,各个版本的英联邦国家)。

数组用于与其他任意国家代码数组进行比较,用于逻辑,例如"从非洲减去这个国家/地区列表"。

所以我想知道,当我生成这些常量时,我​​应该冻结数组中的字符串,而不是:

WORLD_COUNTRIES = Countries.pluck(:country_code).freeze

......也许......

WORLD_COUNTRIES = Countries.pluck(:country_code).map{|c| c.freeze}.freeze

有没有办法量化潜在的好处?

我考虑使用符号数组而不是字符串数组,但是这些数组一起使用的任意数组存储在PostgreSQL文本数组中,似乎我需要将这些列序列化,或者覆盖getter和setter方法,用于更改字符串数组和符号数组之间的值。啊。

修改

测试结果,其中我试图对三种情况进行基准测试:

  1. 将冻结的未冻结字符串数组与未冻结的未冻结字符串数组进行比较
  2. 将冻结的冻结字符串数组与未冻结的未冻结字符串数组进行比较
  3. 将冻结的符号数组与未冻结的符号数组进行比较(如果我咬了一下子弹并在此处完全符号化)。
  4. 感谢对方法论或解释的任何想法。我不确定前两个结果之间的相似性是否表明它们在所有方面都是相同的,但我会热衷于任何可以直接指向内存分配差异的内容。

    脚本:

    require 'benchmark'
    
    country_list             = ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"] 
    FROZEN_ARRAY             = country_list.dup.freeze
    puts FROZEN_ARRAY.size
    FROZEN_ARRAY_AND_STRINGS = country_list.dup.map{|x| x.freeze}.freeze
    FROZEN_ARRAY_AND_SYMBOLS = country_list.dup.map{|x| x.to_sym}.freeze
    comp_s                   = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA)
    comp_sym                 = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA).map{|x| x.to_sym}
    
    
    Benchmark.bm do |x|
      x.report("frozen string"  )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
      x.report("unfrozen string")  { 10000.times {|i| c = (FROZEN_ARRAY             & comp_s.dup) }}
      x.report("symbols"        )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
    end
    
    
    Benchmark.bmbm do |x|
      x.report("frozen string"  )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
      x.report("unfrozen string")  { 10000.times {|i| c = (FROZEN_ARRAY             & comp_s.dup) }}
      x.report("symbols"        )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
    end
    

    结果:

    2.2.3 :001 > require 'benchmark'
     => false 
    2.2.3 :002 > 
    2.2.3 :003 >   country_list             = ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"] 
     => ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"] 
    2.2.3 :004 > FROZEN_ARRAY             = country_list.dup.freeze
     => ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"] 
    2.2.3 :005 > puts FROZEN_ARRAY.size
    252
     => nil 
    2.2.3 :006 > FROZEN_ARRAY_AND_STRINGS = country_list.dup.map{|x| x.freeze}.freeze
     => ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"] 
    2.2.3 :007 > FROZEN_ARRAY_AND_SYMBOLS = country_list.dup.map{|x| x.to_sym}.freeze
     => [:AD, :AE, :AF, :AG, :AI, :AL, :AM, :AN, :AO, :AQ, :AR, :AS, :AT, :AU, :AW, :AX, :AZ, :BA, :BB, :BD, :BE, :BF, :BG, :BH, :BI, :BJ, :BL, :BM, :BN, :BO, :BQ, :BR, :BS, :BT, :BV, :BW, :BY, :BZ, :CA, :CC, :CD, :CF, :CG, :CH, :CI, :CK, :CL, :CM, :CN, :CO, :CR, :CS, :CU, :CV, :CW, :CX, :CY, :CZ, :DE, :DJ, :DK, :DM, :DO, :DZ, :EC, :EE, :EG, :EH, :ER, :ES, :ET, :FI, :FJ, :FK, :FM, :FO, :FR, :GA, :GB, :GD, :GE, :GF, :GG, :GH, :GI, :GL, :GM, :GN, :GP, :GQ, :GR, :GS, :GT, :GU, :GW, :GY, :HK, :HM, :HN, :HR, :HT, :HU, :ID, :IE, :IL, :IM, :IN, :IO, :IQ, :IR, :IS, :IT, :JE, :JM, :JO, :JP, :KE, :KG, :KH, :KI, :KM, :KN, :KP, :KR, :KW, :KY, :KZ, :LA, :LB, :LC, :LI, :LK, :LR, :LS, :LT, :LU, :LV, :LY, :MA, :MC, :MD, :ME, :MF, :MG, :MH, :MK, :ML, :MM, :MN, :MO, :MP, :MQ, :MR, :MS, :MT, :MU, :MV, :MW, :MX, :MY, :MZ, :NA, :NC, :NE, :NF, :NG, :NI, :NL, :NO, :NP, :NR, :NU, :NZ, :OM, :PA, :PE, :PF, :PG, :PH, :PK, :PL, :PM, :PN, :PR, :PS, :PT, :PW, :PY, :QA, :RE, :RO, :RS, :RU, :RW, :SA, :SB, :SC, :SD, :SE, :SG, :SH, :SI, :SJ, :SK, :SL, :SM, :SN, :SO, :SR, :SS, :ST, :SV, :SX, :SY, :SZ, :TC, :TD, :TF, :TG, :TH, :TJ, :TK, :TL, :TM, :TN, :TO, :TR, :TT, :TV, :TW, :TZ, :UA, :UG, :UM, :US, :UY, :UZ, :VA, :VC, :VE, :VG, :VI, :VN, :VU, :WF, :WS, :YE, :YT, :YU, :ZA, :ZM, :ZW] 
    2.2.3 :008 > comp_s                   = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA)
     => ["AD", "AT", "BE", "CY", "EE", "FI", "FR", "DE", "ES", "GR", "IE", "IT", "LU", "LV", "MC", "ME", "MT", "NL", "PT", "SI", "SK", "SM", "VA"] 
    2.2.3 :009 > comp_sym                 = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA).map{|x| x.to_sym}
     => [:AD, :AT, :BE, :CY, :EE, :FI, :FR, :DE, :ES, :GR, :IE, :IT, :LU, :LV, :MC, :ME, :MT, :NL, :PT, :SI, :SK, :SM, :VA] 
    2.2.3 :010 > 
    2.2.3 :011 >   
    2.2.3 :012 >   Benchmark.bm do |x|
    2.2.3 :013 >       x.report("frozen string"  )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
    2.2.3 :014?>     x.report("unfrozen string")  { 10000.times {|i| c = (FROZEN_ARRAY             & comp_s.dup) }}
    2.2.3 :015?>     x.report("symbols"        )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
    2.2.3 :016?>   end
           user     system      total        real
    frozen string  0.190000   0.000000   0.190000 (  0.194141)
    unfrozen string  0.170000   0.010000   0.180000 (  0.174675)
    symbols  0.080000   0.000000   0.080000 (  0.081507)
     => [#<Benchmark::Tms:0x007f810c3aca70 @label="frozen string", @real=0.1941408810671419, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.1899999999999995, @total=0.1899999999999995>, #<Benchmark::Tms:0x007f810c82b538 @label="unfrozen string", @real=0.1746752569451928, @cstime=0.0, @cutime=0.0, @stime=0.010000000000000009, @utime=0.16999999999999993, @total=0.17999999999999994>, #<Benchmark::Tms:0x007f810af2cfa0 @label="symbols", @real=0.08150708093307912, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.08000000000000007, @total=0.08000000000000007>] 
    2.2.3 :017 > 
    2.2.3 :018 >   
    2.2.3 :019 >   Benchmark.bmbm do |x|
    2.2.3 :020 >       x.report("frozen string"  )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
    2.2.3 :021?>     x.report("unfrozen string")  { 10000.times {|i| c = (FROZEN_ARRAY             & comp_s.dup) }}
    2.2.3 :022?>     x.report("symbols"        )  { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
    2.2.3 :023?>   end
    Rehearsal ---------------------------------------------------
    frozen string     0.180000   0.000000   0.180000 (  0.183846)
    unfrozen string   0.200000   0.000000   0.200000 (  0.196311)
    symbols           0.080000   0.000000   0.080000 (  0.082794)
    ------------------------------------------ total: 0.460000sec
    
                          user     system      total        real
    frozen string     0.160000   0.000000   0.160000 (  0.167051)
    unfrozen string   0.170000   0.000000   0.170000 (  0.171601)
    symbols           0.080000   0.000000   0.080000 (  0.078746)
     => [#<Benchmark::Tms:0x007f811022a388 @label="frozen string", @real=0.1670510449912399, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.16000000000000014, @total=0.16000000000000014>, #<Benchmark::Tms:0x007f811022a4c8 @label="unfrozen string", @real=0.17160122003406286, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.16999999999999993, @total=0.16999999999999993>, #<Benchmark::Tms:0x007f8108eb1c58 @label="symbols", @real=0.07874645793344826, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.08000000000000007, @total=0.08000000000000007>] 
    2.2.3 :024 > 
    2.2.3 :025 >   
    2.2.3 :026 >   
    

1 个答案:

答案 0 :(得分:1)

由于您处理的是少量值,并且由于符号的性能优势在您的测试中很明显,因此请使用符号。

顺便说一句,您可以使用map(&:to_sym)代替map {|x| x.to_sym}