我正在尝试构建一个页面,该页面根据用户个人资料的浏览次数对用户进行排名。由于该页面可能会获得大量点击,因此我缓存了已排序的用户,并在每次配置文件获得视图时使该缓存无效。由于每天只有 9 个用户和约 200 次页面浏览量,我的应用程序超过了 Heroku 的 512mb 内存上限。New Relic 证实了这一点,向我展示了用户列表花费了过多的时间:
Slowest Components Duration %
-----------------------------------------------
UsersController#index 2,125 ms 80%
users/index.html.erb 506 ms 19%
Memcache get 20 ms 1%
User#find 18 ms 1%
layouts/_header.html.erb 1 ms 0%
User#find_by_sql 0 ms 0%
一些阅读告诉我,ActiveRecord 在请求后显然不会将内存交还给操作系统。看UsersController#index
,我可以看到如果分配的内存User.order
没有被释放,这可能会导致问题。
UserController#index:
require 'will_paginate/array'
class UsersController < ApplicationController
PER_PAGE = 20
def index
@users = Rails.cache.read("users")
if @users.nil?
# .all is used to force the query to happen now, so that the result set is cached instead of the query
@users = User.order("views DESC").all
Rails.cache.write("users", @users)
end
@users = @users.paginate(page: params[:page], per_page: PER_PAGE)
if params[:page].nil? || params[:page] == "1"
@rank = 1
else
@title = "Page #{params[:page]}"
@rank = (params[:page].to_i - 1) * PER_PAGE + 1
end
end
end
index.html.erb
<% @users.each do |user| %>
image_tag user.profile_picture, alt: user.name
<h3><%= @rank %></h3>
<p><%= user.name %></p>
<p><%= user.views %></p>
<% @rank += 1 %>
<% end %>
<%= will_paginate %>
我不知道我应该如何解决这个问题。我想一次可能只将一页用户拉入内存,但只有 9 个用户,这并不会真正改变任何东西,因为每页最多应该列出 20 个用户。每次请求后我是否必须手动@users
从内存中清除,或者我的方法UsersController#index
是错误的?
任何帮助将不胜感激。