如果区分 普通关注 和 关注大 V 分别存两个 Set,这样可以省掉 求交集的一步
建议用代码块包起来
#3 楼 @prajnamas 试了一下挺好用的
viva la BACA!!!
#12 楼 @xiaoronglv 看了下时间。。。是来不了了。。。住松江略远
可以在 contoller 中用 view_context 对象来访问所有的 helper 方法
不知道极米投影仪行不行?
这不是和天面试的差不多╭(°A°`)╮
#1 楼 @jicheng1014 我也遇到这个问题,多谢
请问楼主 generate_authentication_token 中为什么要用 loop 呢?
哦,是要保证 token 的唯一性。。。
#19 楼 @vincent 我是直接本机 rake 的,没有用 dalli,ruby 2.2 + rails 4.2 数据如下:
       user     system      total        real
  1  0.750000   0.050000   0.800000 (  0.798077)
 1_  0.530000   0.060000   0.590000 (  0.595011)
 10  0.480000   0.050000   0.530000 (  0.527158)
 30  0.470000   0.040000   0.510000 (  0.513850)
 50  0.430000   0.080000   0.510000 (  0.515523)
100  0.490000   0.050000   0.540000 (  0.539221)
试了一下换 ruby 版本到 2.0.0 除了慢了(1 秒多),batch 依然更快
代码见 (https://gist.github.com/li-thy-um/c78ca3f5abb60d388951)
@vincent 说差异是由于 我 cache 在内存里没有用 memcached。
看 rails 源码 发现 read 比 read_muti 多了一个 修改 payload[:hit] 的操作
namespace :test do
  task cache: :environment do
     test_cache
    # test_cache_batch
    # test_read_in_batch
  end
end
def read_in_batch(total, batch_size)
  batch_size += 1 # 这里改了
  array = []
  total.times do |i|
    if (i + 1) % batch_size == 0 #这里改了
      Rails.cache.read_multi(*array)
      array = []
    else
      array << "user:#{i}:counter"
    end
  end
end
def test_cache_batch
  n = 10000
  n.times {|i| Rails.cache.write "user:#{i}:counter", i * i }
  Benchmark.bm do |x|
    x.report "  1" do
      read_in_batch n, 1
    end
    x.report " 10" do
      read_in_batch n, 10
    end
    x.report " 30" do
      read_in_batch n, 30
    end
    x.report " 50" do
      read_in_batch n, 50
    end
    x.report "100" do
      read_in_batch n, 100
    end
  end
end
def test_cache
  n = 10000
  n.times {|i| Rails.cache.write "user:#{i}:counter", i * i }
  Benchmark.bm do |x|
    x.report "  1" do
      n.times do |i|
        Rails.cache.read "user:#{i}:counter"
      end
    end
    x.report " 10" do
      read_in_batch n, 10
    end
    x.report " 30" do
      read_in_batch n, 30
    end
    x.report " 50" do
      read_in_batch n, 50
    end
    x.report "100" do
      read_in_batch n, 100
    end
  end
end
代码修正后: test_cache:
        user     system      total        real
  1  0.740000   0.100000   0.840000 (  0.834747)
 10  0.410000   0.050000   0.460000 (  0.465745)
 30  0.430000   0.060000   0.490000 (  0.491213)
 50  0.440000   0.060000   0.500000 (  0.498691)
100  0.420000   0.070000   0.490000 (  0.493613)
test_cache_batch:
       user     system      total        real
  1  0.460000   0.050000   0.510000 (  0.520317)
 10  0.440000   0.060000   0.500000 (  0.493935)
 30  0.450000   0.040000   0.490000 (  0.495721)
 50  0.410000   0.080000   0.490000 (  0.494678)
100  0.450000   0.060000   0.510000 (  0.509924)
结论:
后续:
其实上面的测试还是有问题,并没有读全部的 cache
然后改了 read_in_batch
def read_in_batch(total, batch_size)
  ids = (1..total).to_a
  while !ids.empty?
    batch = ids.pop(batch_size).map { |i| "user:#{i}:counter" }
    Rails.cache.read_multi(*batch)
  end
end
加了 2 和 3 两个 测试
test_cache
       user     system      total        real
  1  0.770000   0.060000   0.830000 (  0.828525)
  2  0.460000   0.090000   0.550000 (  0.551031)
  3  0.470000   0.060000   0.530000 (  0.537011)
 10  0.470000   0.060000   0.530000 (  0.533800)
 30  0.450000   0.070000   0.520000 (  0.509173)
 50  0.430000   0.080000   0.510000 (  0.509421)
100  0.450000   0.050000   0.500000 (  0.512080)
test_cache_batch
       user     system      total        real
  1  0.750000   0.110000   0.860000 (  0.862681)
  2  0.520000   0.060000   0.580000 (  0.577206)
  3  0.490000   0.060000   0.550000 (  0.546603)
 10  0.490000   0.040000   0.530000 (  0.536715)
 30  0.450000   0.070000   0.520000 (  0.528250)
 50  0.460000   0.090000   0.550000 (  0.545573)
100  0.450000   0.070000   0.520000 (  0.524905)
发现 只有 1 比较慢,2, 3 和其他基本稳定
跑 2w 条
test_cache
       user     system      total        real
  1  1.210000   0.140000   1.350000 (  1.354328)
  2  0.980000   0.120000   1.100000 (  1.098255)
  3  0.940000   0.140000   1.080000 (  1.078272)
 10  0.920000   0.120000   1.040000 (  1.054410)
 30  0.910000   0.130000   1.040000 (  1.036415)
 50  0.900000   0.120000   1.020000 (  1.023310)
100  0.940000   0.100000   1.040000 (  1.049659)
test_cache_batch
       user     system      total        real
  1  1.200000   0.170000   1.370000 (  1.381987)
  2  0.940000   0.160000   1.100000 (  1.099291)
  3  0.940000   0.140000   1.080000 (  1.088021)
 10  0.940000   0.110000   1.050000 (  1.053521)
 30  0.900000   0.140000   1.040000 (  1.044466)
 50  0.890000   0.130000   1.020000 (  1.028398)
100  0.920000   0.140000   1.060000 (  1.049393)
好像只是多了个常数
跑 4w 条
test_cache
       user     system      total        real
  1  2.440000   0.310000   2.750000 (  2.763401)
  2  1.900000   0.250000   2.150000 (  2.152947)
  3  1.870000   0.230000   2.100000 (  2.112615)
 10  1.750000   0.320000   2.070000 (  2.066013)
 30  1.780000   0.260000   2.040000 (  2.050358)
 50  1.770000   0.250000   2.020000 (  2.021323)
100  1.700000   0.300000   2.000000 (  2.014740)
test_cache_batch
       user     system      total        real
  1  2.060000   0.240000   2.300000 (  2.301558)
  2  1.870000   0.290000   2.160000 (  2.164925)
  3  1.890000   0.210000   2.100000 (  2.109823)
 10  1.770000   0.280000   2.050000 (  2.047593)
 30  1.850000   0.170000   2.020000 (  2.035191)
 50  1.800000   0.210000   2.010000 (  2.016329)
100  1.790000   0.230000   2.020000 (  2.027382)
好像这么写更好
def read_in_batch(total, batch_size)
  (1..total).each_slice(batch_size) do |slice| 
    batch = slice.map { |i| "user:#{i}:counter" }
    Rails.cache.read_multi(*batch)
  end
end
        #10 楼 @vincent 我测了一下,改 read_in_batch n, 1 以后,数据如下
       user     system      total        real
  1  0.010000   0.000000   0.010000 (  0.018565)
 10  0.230000   0.010000   0.240000 (  0.229515)
 30  0.020000   0.000000   0.020000 (  0.019327)
 50  0.020000   0.000000   0.020000 (  0.020574)
100  0.030000   0.000000   0.030000 (  0.032168)
用原方法,本机数据如下
       user     system      total        real
  1  0.770000   0.110000   0.880000 (  0.880746)
 10  0.010000   0.000000   0.010000 (  0.015449)
 30  0.020000   0.000000   0.020000 (  0.016035)
 50  0.030000   0.000000   0.030000 (  0.032530)
100  0.030000   0.000000   0.030000 (  0.025726)
和你的结果一致。
不知道怎么解释前一种情况,直觉上文中的解释说不通
都使用 read_in_batch 时:
去掉 1,“大时间”在 1, 2 行交错
       user     system      total        real
10  0.020000   0.000000   0.020000 (  0.011991)
 30  0.230000   0.010000   0.240000 (  0.235225)
 50  0.010000   0.000000   0.010000 (  0.017332)
100  0.030000   0.000000   0.030000 (  0.021796)
       user     system      total        real
 10  0.250000   0.000000   0.250000 (  0.258668)
 30  0.010000   0.000000   0.010000 (  0.012602)
 50  0.020000   0.000000   0.020000 (  0.020062)
100  0.020000   0.000000   0.020000 (  0.014228)
去掉 10 , “大时间”在 1, 2 行交错
       user     system      total        real
  1  0.270000   0.000000   0.270000 (  0.271896)
 30  0.010000   0.000000   0.010000 (  0.012453)
 50  0.010000   0.000000   0.010000 (  0.013926)
100  0.030000   0.000000   0.030000 (  0.028314)
       user     system      total        real
  1  0.020000   0.000000   0.020000 (  0.013825)
 30  0.180000   0.000000   0.180000 (  0.178828)
 50  0.010000   0.000000   0.010000 (  0.012010)
100  0.010000   0.000000   0.010000 (  0.012555)
        1 里面为啥不用 read_in_batch n, 1
学习了,就喜欢这种好文章。最近刷 leetcode109 Convert Sorted List to Binary Search Tree 发现一般递归算法会导致内存超标。对如何过毫无思路 T_T
@@x = " some other value"
这句把 @@x “拉”到了两个 class 的外面,这句之后 @@x 就属于 toplevel class variable 了。变成所有类共享了。
把他移到最上面可以发现输出变成 y 了
puts(eval("@mystr << @@x", ob1.getBinding)) #=> ob1 string y
puts(eval("@mystr << @@x", ob2.getBinding)) #=> ob2 string y
puts(eval("@mystr << @@x", ob3.getBinding)) #=> ob3 string y
解释器还会给出警告:
xxxxxx.rb:xx: warning: class variable access from toplevel
        已投 ( ゜- ゜) つロ 乾杯~