pagy 和 kaminari gems 之间的性能究竟有什么区别,谁更好?

Elt*_*lab 4 pagination rubygems ruby-on-rails kaminari

  • 在我们的项目中,我们在所有内容的分页中都使用 Kaminari,它运行良好
  • 有一个名为“pagy”的新 gem,在他们在 Github 上的 gem repo 中,他们表示他们的性能比 kaminari 和 will-paginate 更好,但我不知道我们的项目是否真的更好地投入时间从 kaminari 转换为帕吉

所以我尝试将它与 kaminari 进行比较:

  • 我运行了相同的查询,该查询将加载每页 1 个框的所有框和 page: 2 ,并检查每个 gem 运行的查询,并检查所需的时间
2.5.1 :043 > pagy(Box.all, items: 1, page: 2)
   (2.0ms)  SELECT COUNT(*) FROM "boxes"
  Box Load (1.0ms)  SELECT  "boxes".* FROM "boxes" LIMIT $1 OFFSET $2  [["LIMIT", 1], ["OFFSET", 1]]
 => [#<Pagy:0x00007fd7e88073a8 @vars={:page=>2, :items=>1, :outset=>0, :size=>[1, 4, 4, 1], :page_param=>:page, :params=>{}, :anchor=>"", :link_extra=>"", :item_path=>"pagy.info.item_name", :cycle=>false, :count=>106}, @count=106, @items=1, @outset=0, @page=2, @last=106, @pages=106, @offset=1, @from=2, @to=2, @prev=1, @next=3>, #<ActiveRecord::Relation [#<Box id: "2fbf947f-c0d8-4c02-9c71-22d7deaaff2e", shipping_request_id: "7dab8aba-961a-4d28-80c8-20b2fb9a63b7", created_at: "2019-03-14 18:22:33", updated_at: "2019-03-14 18:22:33", external_uuid: "b44f08ec-ccbc-424c-b0aa-4cbcbe94cd74", inventory_id: 78, dimension: {"length"=>4.5, "width"=>5.5, "height"=>5.6, "unit"=>"cm"}, weight: 56.6, label_url: nil, warehouse_state: "processing", proforma_url: nil, barcode: "EXOBOX-B44F08EC", proforma_name: nil, tracking_url: "", private_tracking: true, external_shipment_id: nil, state: "preparing", tracking_history: [{"status"=>"preparing", "datetime"=>"2019-03-14 20:22:33 +0200", "active"=>true, "order"=>0}, {"status"=>"pending_pick_up", "datetime"=>"", "active"=>false, "order"=>1}, {"status"=>"picked_up", "datetime"=>"", "active"=>false, "order"=>2}, {"status"=>"en_route_to_destination", "datetime"=>"", "active"=>false, "order"=>3}, {"status"=>"delivered", "datetime"=>"", "active"=>false, "order"=>4}], parent_id: nil, tracking_number: "EXOTRACK-B44F08EC">]>] 
2.5.1 :044 > Box.all.page(2).per(1)
  Box Load (1.0ms)  SELECT  "boxes".* FROM "boxes" LIMIT $1 OFFSET $2  [["LIMIT", 1], ["OFFSET", 1]]
 => #<ActiveRecord::Relation [#<Box id: "2fbf947f-c0d8-4c02-9c71-22d7deaaff2e", shipping_request_id: "7dab8aba-961a-4d28-80c8-20b2fb9a63b7", created_at: "2019-03-14 18:22:33", updated_at: "2019-03-14 18:22:33", external_uuid: "b44f08ec-ccbc-424c-b0aa-4cbcbe94cd74", inventory_id: 78, dimension: {"length"=>4.5, "width"=>5.5, "height"=>5.6, "unit"=>"cm"}, weight: 56.6, label_url: nil, warehouse_state: "processing", proforma_url: nil, barcode: "EXOBOX-B44F08EC", proforma_name: nil, tracking_url: "", private_tracking: true, external_shipment_id: nil, state: "preparing", tracking_history: [{"status"=>"preparing", "datetime"=>"2019-03-14 20:22:33 +0200", "active"=>true, "order"=>0}, {"status"=>"pending_pick_up", "datetime"=>"", "active"=>false, "order"=>1}, {"status"=>"picked_up", "datetime"=>"", "active"=>false, "order"=>2}, {"status"=>"en_route_to_destination", "datetime"=>"", "active"=>false, "order"=>3}, {"status"=>"delivered", "datetime"=>"", "active"=>false, "order"=>4}], parent_id: nil, tracking_number: "EXOTRACK-B44F08EC">]> 
2.5.1 :045 > 
Run Code Online (Sandbox Code Playgroud)

他们也在运行相同的查询(不管从 box 查询中选择计数),所以我怎么能发现它们之间的区别,谁更好,感觉它们都是一样的,知道我们正在使用它们API项目

小智 9

优势的程度取决于您如何在 API 中使用分页。您打包到 API 响应中的分页信息越多,Pagy 就越方便。

从DB的角度来看,如果使用经典的需要计算集合计数的分页,在查询时间上是没有区别的。它不可能,因为所有分页 gem 都需要始终执行相同的 2 个查询:一个用于获取计数,另一个用于获取结果页面。

因此,在这种情况下,改进不在查询中...除非您的 API 不需要在响应中添加结果总数,例如,如果您只需要获取结果页面和上一个、下一个的链接等,那么您可以通过使用无数额外的 pagy 来完全避免计数查询,这可能是一个巨大的改进。

与其他 gem 相比,使用 Pagy 的一大优势是它不仅计算速度要快很多倍(根据设置,您可以轻松地使用 Kaminari 每次渲染浪费 20 毫秒),而且它使用了所需内存的一小部分其他宝石。这意味着它对服务器来说是一个很大的负载缓解,特别是如果你的应用程序是高流量的。在正常的 UI 条件下,它的效率比 Kaminari 高数百倍,即使在响应中分页信息最少的情况下,它在 API 条件下也应该高出数十倍。

有一个迁移指南应该可以使从遗留 gem 的迁移变得非常简单。如果您的 Kaminari 使用是标准的,则只需几分钟(主要是搜索和替换)。如果您修补了 Kaminari 或以奇怪的方式使用它(可能不是通过 API),您可能需要阅读更多 Pagy 文档或寻求实时支持

对于您的 API,您还可以查看额外标头,这些标头封装了 API 对分页的需求。

仅供参考:如果您将 ruby​​ 2.0+ 与 UI 助手一起使用,Pagy v3(即将推出)将进一步提高速度和亮度(明显更多)。它仍然缺少 API 的基准测试,但它肯定会额外改进标头。