เมื่อแอปพลิเคชัน Rails ยอมรับคำขอ ตัวควบคุมมักจะถามโมเดลสำหรับข้อมูลที่ร้องขอ จากนั้นโมเดลจะดึงข้อมูลจากฐานข้อมูลและส่งกลับไปยังคอนโทรลเลอร์ ในที่สุดคอนโทรลเลอร์ก็แสดงมุมมองซึ่งแสดงถึงข้อมูลในรูปแบบที่มนุษย์อ่านได้
ในบางสถานการณ์ การแสดงมุมมองเป็นการดำเนินการที่มีราคาแพง โดยเฉพาะอย่างยิ่งถ้ามุมมองต้องการแสดงข้อมูลจำนวนมาก เช่น เมื่อแสดงรายการของผลิตภัณฑ์ที่มีอยู่ทั้งหมดในร้านค้า เป็นต้น ในกรณีเช่นนี้ การแคชบางส่วนของมุมมองที่ส่งคืนสามารถเร่งความเร็วได้ โดยเฉพาะอย่างยิ่งเมื่อข้อมูลไม่เปลี่ยนแปลงบ่อยเกินไป
👋 และถ้าคุณชอบบทความนี้ ยังมีอีกมากที่เราเขียนเกี่ยวกับประสิทธิภาพของ Ruby (on Rails) ให้ดูที่รายการตรวจสอบการตรวจสอบประสิทธิภาพของ Ruby
การทดสอบการแคชในเครื่อง
การแคชจะถูกปิดในระหว่างการพัฒนาโดยค่าเริ่มต้น เพื่อให้แน่ใจว่าคุณจะได้รับคำตอบใหม่ๆ จากแอปของคุณอยู่เสมอ หากต้องการทดสอบการแคชในเครื่อง คุณจะต้องเปิดใช้ในการกำหนดค่าการพัฒนา
ใน Rails 5 คุณสามารถเปิดแคชชั่วคราวจากบรรทัดคำสั่งได้ การดำเนินการนี้จะใช้ที่เก็บหน่วยความจำ ซึ่งหมายความว่าส่วนย่อยที่แคชไว้จะถูกเก็บไว้ในหน่วยความจำในกระบวนการ Ruby ของเว็บเซิร์ฟเวอร์
$ rails dev:cache
Development mode is now being cached.
คุณสามารถเรียกใช้คำสั่งเดียวกันเพื่อปิดการแคชกลับได้
การแคชแฟรกเมนต์
สมมติว่าเรามีเพจที่แสดงสินค้าทั้งหมดในร้านค้าในหน้าเดียว ในการทำเช่นนั้น เรามีมุมมองดัชนีที่แสดงผลิตภัณฑ์
# app/views/products/index.html.erb
<table>
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Image url</th>
<th>Price</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @products.each do |product| %>
<%= render product %>
<% end %>
</tbody>
</table>
สำหรับแต่ละผลิตภัณฑ์ _product.html.erb
แสดงผลบางส่วน ซึ่งดูแลการแสดงแถวตารางพร้อมรายละเอียดของผลิตภัณฑ์
# app/views/products/_product.html.erb
<tr>
<td><%= product.title %></td>
<td><%= product.description %></td>
<td><%= product.image_url %></td>
<td><%= product.price %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
การขอเพจแบบโลคัลในโหมดการพัฒนาโดยมีผลิตภัณฑ์ 25 รายการในฐานข้อมูลใช้เวลาประมาณ 300 มิลลิวินาที ใช้เวลาเกือบทั้งหมดในการแสดงผลบางส่วน
เป็นไปได้มากว่าการตอบกลับจะเร็วขึ้นในการผลิต เนื่องจากสินทรัพย์ที่รวมเข้าด้วยกัน บันทึกน้อยลง และเว็บเซิร์ฟเวอร์ที่เร็วขึ้น แม้ว่าตัวเลขที่กำลังพัฒนาจะไม่ถูกต้อง แต่จะแสดงว่าคำขอของเราส่วนใดช้าที่สุด ดังนั้นเราจึงสามารถพยายามเร่งความเร็วได้
Started GET "/products" for ::1 at 2018-03-13 12:16:08 +0100
Processing by ProductsController#index as HTML
Rendering products/index.html.erb within layouts/application
Product Load (0.4ms) SELECT "products".* FROM "products"
Rendered products/_product.html.erb (1.4ms)
Rendered products/_product.html.erb (0.4ms)
Rendered products/_product.html.erb (0.4ms)
Rendered products/_product.html.erb (0.3ms)
Rendered products/_product.html.erb (0.5ms)
Rendered products/_product.html.erb (2.0ms)
Rendered products/_product.html.erb (0.9ms)
Rendered products/_product.html.erb (0.4ms)
Rendered products/_product.html.erb (0.5ms)
Rendered products/_product.html.erb (0.5ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.7ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.7ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.5ms)
Rendered products/_product.html.erb (0.7ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.9ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/_product.html.erb (0.5ms)
Rendered products/_product.html.erb (0.6ms)
Rendered products/index.html.erb within layouts/application (257.5ms)
Completed 200 OK in 295ms(Views: 290.4ms | ActiveRecord: 0.4ms)
เพื่อประหยัดเวลาในการแสดงผลบางส่วนเหล่านี้ เราสามารถใช้ การแคชส่วนย่อย ในตัวของ Rails ซึ่งเก็บส่วนหนึ่งของมุมมองที่แสดงเป็นส่วนย่อย สำหรับคำขอที่ตามมา ส่วนที่บันทึกไว้ล่วงหน้าจะใช้แทนการแสดงผลอีกครั้ง
ในการแคชแฟรกเมนต์ คุณต้องแรปมันในบล็อกโดยใช้ cache
ตัวช่วย
<table>
# ...
<tbody>
<% @products.each do |product| %>
<% cache(product) do %>
<%= render product %>
<% end %>
<% end %>
</tbody>
</table>
หากต้องการดูว่าการแคชผลิตภัณฑ์เหล่านี้เร่งการตอบสนองของเราหรือไม่ เราจะขอหน้าเว็บสองครั้ง คำขอที่สองควรดำเนินการเร็วกว่ามาก เนื่องจากผลิตภัณฑ์แต่ละรายการในมุมมองได้รับการแสดงผลล่วงหน้าและจัดเก็บไว้ในแคชแล้ว
Started GET "/products" for ::1 at 2018-03-13 12:17:29 +0100
Processing by ProductsController#index as HTML
Rendering products/index.html.erb within layouts/application
Product Load (0.4ms) SELECT "products".* FROM "products"
Rendered products/index.html.erb within layouts/application (21.2ms)
Completed 200 OK in 55ms (Views: 50.8ms | ActiveRecord: 0.4ms)
มันได้ผล! คำขอที่สองเร็วกว่าคำขอแรกมากกว่าห้าเท่า โปรดทราบว่าบันทึกไม่แสดงการแสดงผลบางส่วน เนื่องจากถูกโหลดจากแคชโดยตรง
แคชหมดอายุ
เมื่อเรียกใช้ cache
ตัวช่วยในตัวอย่างข้างต้น เราส่ง product
ออบเจ็กต์เป็น การพึ่งพาแคช . ซึ่งช่วยให้ผู้ช่วยรู้ว่าเนื้อหาของส่วนแคชขึ้นอยู่กับวัตถุผลิตภัณฑ์
ภายในอ็อบเจ็กต์ผลิตภัณฑ์มี #cache_key
เมธอด ซึ่งใช้ในการสร้างคีย์สำหรับส่วนแคช กุญแจสำหรับทั้งส่วนอาจมีลักษณะดังนี้:
views/products/42-20180302103130041320/75dda06d36880e8b0ae6cac0a44fb56d
คีย์แคชประกอบด้วยสองส่วน:
- "การดู/ผลิตภัณฑ์" เป็นแคช คลาส .
42
คือรหัสสินค้า20180302103130041320
คือวันที่ update_at ของผลิตภัณฑ์75dda06d36880e8b0ae6cac0a44fb56d
เป็นการสรุปของแผนผังต้นไม้
คีย์นี้จะเปลี่ยนแปลงทุกครั้งที่มีการอัปเดตผลิตภัณฑ์ หรือมีการเปลี่ยนแปลงใดๆ ในเทมเพลต เมื่อเป็นเช่นนั้น จะทำให้แคชพลาด ทำให้แฟรกเมนต์แสดงผลอีกครั้งและบันทึกแฟรกเมนต์ใหม่ เพื่อให้แน่ใจว่าชิ้นส่วนจะคงความสดแม้ส่วนประกอบจะเปลี่ยนไป
นอกเหนือจากการแคชส่วนย่อย
แม้ว่าส่วนย่อยของแคชที่กล่าวถึงในตัวอย่างนี้ให้การเร่งความเร็วเพียงเล็กน้อย แต่การแคชยังมีอะไรมากกว่าที่เราพูดถึงในวันนี้ การใช้กลยุทธ์อย่างการแคชตุ๊กตารัสเซียหรือวิธีการระดับล่าง เช่น การแคชผลลัพธ์การสืบค้นฐานข้อมูล จะทำให้การเร่งความเร็วเพิ่มขึ้นได้สำเร็จ
แน่นอน เราจะพูดถึงสิ่งเหล่านี้ในตอนต่อๆ ไปของ AppSignal Academy คุณต้องการเรียนรู้อะไรเป็นพิเศษไหม โปรดอย่าลังเลที่จะแจ้งให้เราทราบที่ @AppSignal แน่นอน เราอยากทราบว่าคุณชอบบทความนี้อย่างไร หรือหากคุณมีหัวข้ออื่นที่ต้องการทราบข้อมูลเพิ่มเติม