আমরা এর আগে অ্যাপসিগন্যাল একাডেমিতে রেলে ফ্র্যাগমেন্ট ক্যাশিং দেখেছি। এটি তাদের ছোট ছোট টুকরো ক্যাশ করে ভিউগুলির কার্যক্ষমতাকে ব্যাপকভাবে উন্নত করে। আংশিক ক্যাশ করার সময়, অল্প খরচে আমাদের দৃষ্টিভঙ্গিতে অন্য কোথাও সেগুলি পুনরায় ব্যবহার করতে সক্ষম হওয়ার অতিরিক্ত সুবিধা রয়েছে৷
এটি ছোট সংগ্রহের জন্য ভাল কাজ করে, তবে বড় সংগ্রহগুলিতে সমস্যাগুলি দ্রুত দেখা দেয়। এই নিবন্ধে, আমরা কীভাবে রেল সংগ্রহের ক্যাশিং কাজ করে এবং কীভাবে আমরা একটি বড় সংগ্রহের রেন্ডারিং দ্রুত করতে এটি ব্যবহার করতে পারি তা দেখব৷
👋 এবং আপনি যদি এই নিবন্ধটি পছন্দ করেন তবে রুবি (রেলগুলিতে) পারফরম্যান্স সম্পর্কে আমরা আরও অনেক কিছু লিখেছি, আমাদের রুবি পারফরম্যান্স পর্যবেক্ষণ চেকলিস্টটি দেখুন৷
একটি সংগ্রহ রেন্ডার করা
আসুন একটি ছোট কন্ট্রোলার দিয়ে শুরু করি যা আমাদের ব্লগের সূচী পৃষ্ঠার জন্য শেষ 100টি পোস্ট লোড করে৷
class PostsController < ApplicationController
def index
@posts = Post.all.order(:created_at => :desc).limit(100)
end
end
এই পোস্টগুলিকে ভিউতে রেন্ডার করতে, আমরা @posts
লুপ করি ইনস্ট্যান্স ভেরিয়েবল।
<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<div class="posts">
<% @posts.each do |post| %>
<div class="post">
<h2><%= post.title %></h2>
<small><%= post.author %></small>
<div class="body">
<%= post.body %>
</div>
</div>
<% end %>
</div>
এই পৃষ্ঠার অনুরোধ করার পরে, আমরা দেখতে পাই যে পোস্টগুলি ডাটাবেস থেকে আনা হচ্ছে এবং দৃশ্যটি রেন্ডার করা হচ্ছে৷ ভিউ লেয়ারে মাত্র 32 মিলিসেকেন্ড খরচ করে, এই পৃষ্ঠাটি বেশ দ্রুত।
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index.html.erb within layouts/application
Post Load (1.5ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
Rendered posts/index.html.erb within layouts/application (19.4ms)
Completed 200 OK in 37ms (Views: 32.4ms | ActiveRecord: 2.7ms)
আংশিক সহ একটি সংগ্রহ রেন্ডার করা
এরপর, আমরা post
ব্যবহার করতে চাই উপাদান অন্য ভিউতে, তাই আমরা পোস্ট এইচটিএমএলকে একটি আংশিক তে স্থানান্তরিত করি।
<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<div class="posts">
<% @posts.each do |post| %>
<%= render post %>
<% end %>
</div>
<!-- app/views/posts/_post.html.erb -->
<div class="post">
<h2><%= post.title %></h2>
<small><%= post.author %></small>
<div class="body">
<%= post.body %>
</div>
</div>
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index.html.erb within layouts/application
Post Load (1.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
...
Rendered posts/_post.html.erb (0.1ms)
Rendered posts/_post.html.erb (0.1ms)
Rendered posts/index.html.erb within layouts/application (205.4ms)
Completed 200 OK in 217ms (Views: 213.8ms | ActiveRecord: 1.7ms)
ভিউ লেয়ারে 213 মিলিসেকেন্ড খরচ করে, আপনি দেখতে পাচ্ছেন যে রেন্ডারের সময় যথেষ্ট বৃদ্ধি পেয়েছে। কারণ প্রতিটি পোস্টের জন্য একটি নতুন ফাইল (আংশিক) লোড, কম্পাইল এবং রেন্ডার করা প্রয়োজন। আসুন সংক্ষেপে দেখি কিভাবে আমরা ফ্র্যাগমেন্ট ক্যাশিং এর মাধ্যমে রেন্ডার টাইম উন্নত করতে পারি।
ফ্র্যাগমেন্ট ক্যাশিং
ফ্র্যাগমেন্ট ক্যাশিং নিবন্ধে বর্ণিত হিসাবে, আমরা cache
ব্যবহার করব render
এর চারপাশে ভিউতে সাহায্যকারী কল এইভাবে, আমরা প্রতিটি পোস্টের জন্য আংশিক রেন্ডারিং ক্যাশে করব৷
<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<div class="posts">
<% @posts.each do |post| %>
<%= cache post do %>
<%= render post %>
<% end %>
<% end %>
</div>
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index_with_partial_caching.html.erb within layouts/application
Post Load (1.4ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
...
Read fragment views/posts/index.1ms)
Rendered posts/_post.html.erb (0.1ms)
Write fragment views/posts/index.1ms)
Read fragment views/posts/index.5ms)
Rendered posts/_post.html.erb (0.1ms)
Write fragment views/posts/index.1ms)
Rendered posts/index.html.erb within layouts/application (274.5ms)
Completed 200 OK in 286ms (Views: 281.4ms | ActiveRecord: 2.4ms)
প্রথম অনুরোধটি খুব বেশি দ্রুত হবে না, কারণ এটিকে এখনও প্রতিটি আংশিক প্রথমবার রেন্ডার করতে হবে এবং ক্যাশে স্টোরে সংরক্ষণ করতে হবে৷
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index.html.erb within layouts/application
Post Load (2.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
...
Read fragment views/posts/index.1ms)
Read fragment views/posts/index.1ms)
Rendered posts/index.html.erb within layouts/application (63.8ms)
Completed 200 OK in 78ms (Views: 75.5ms | ActiveRecord: 2.2ms)
পরবর্তী অনুরোধগুলিতে, আমরা দেখতে পাই যে দৃশ্যে ব্যয় করা সময় যথেষ্ট কম - 286 মিলিসেকেন্ড থেকে 78 মিলিসেকেন্ডে। তবুও, এটি এখনও আমাদের আসল কোডের তুলনায় অনেক ধীর - এটি প্রায় দ্বিগুণ ধীর।
দ্রষ্টব্য:আপনি যদি আপনার লগগুলিতে "পড়ুন/লিখুন" লাইনগুলি দেখতে না পান তবে আপনার বিকাশের পরিবেশে ফ্র্যাগমেন্ট ক্যাশে লগিং সক্ষম করতে ভুলবেন না, যা false
এ সেট করা আছে। Rails 5.1 এবং তার উপরে ডিফল্টরূপে:
# config/environments/development.rb
config.action_controller.enable_fragment_cache_logging = true
সংগ্রহ ক্যাশিং
Rails 5-এ, সংগ্রহ ক্যাশিং দ্রুত করার জন্য অনেক কাজ করা হয়েছিল। এই উন্নতিগুলি লাভ করতে, আমাদের ভিউ কোড পরিবর্তন করতে হবে৷ cache
কল করার পরিবর্তে আমরা নিজেরাই সাহায্যকারী, আমরা রেলকে একটি সম্পূর্ণ সংগ্রহ রেন্ডার করতে এবং একই সময়ে ক্যাশে করতে বলতে পারি৷
<!-- app/views/posts/index.html.erb -->
<h1>Posts</h1>
<div class="posts">
<%= render partial: :post, collection: @posts, cached: true %>
</div>
render @collection, cached: true
নোট করুন শর্টহ্যান্ড এই ক্যাশিং গতির উন্নতির জন্য কাজ করবে না।
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index.html.erb within layouts/application
Post Load (1.4ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
Rendered collection of posts/_post.html.erb [0 / 100 cache hits] (28.2ms)
Rendered posts/index.html.erb within layouts/application (46.6ms)
Completed 200 OK in 64ms (Views: 59.9ms | ActiveRecord: 2.0ms)
প্রথম অনুরোধে, আমরা ইতিমধ্যে ভিউ লেয়ারে ব্যয় করা সময়ের একটি বড় উন্নতি দেখতে পাচ্ছি। এর কারণ হল রেলগুলি এখন আগে থেকেই প্রস্তুত করে, আংশিকটি সম্পূর্ণ সংগ্রহের জন্য ব্যবহার করা হচ্ছে, প্রতিটি পোস্টের জন্য আলাদাভাবে ব্যবহার করার পরিবর্তে৷
Started GET "/posts"
Processing by PostsController#index as HTML
Rendering posts/index.html.erb within layouts/application
Post Load (1.3ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT ? [["LIMIT", 100]]
↳ app/views/posts/index.html.erb:4
Rendered collection of posts/_post.html.erb [100 / 100 cache hits] (19.2ms)
Rendered posts/index.html.erb within layouts/application (26.5ms)
Completed 200 OK in 37ms (Views: 35.7ms | ActiveRecord: 1.3ms)
পরবর্তী অনুরোধগুলিতে, আমরা আরও উন্নতি দেখতে পাচ্ছি - 64 মিলিসেকেন্ড থেকে প্রায় 35 মিলিসেকেন্ডে। সংগ্রহের জন্য রেল অপ্টিমাইজেশনের মাধ্যমে সমগ্র সংগ্রহের জন্য একটি বড় গতির উন্নতি এখানে করা হয়েছে। প্রতিটি আংশিক জন্য একটি ক্যাশের প্রাপ্যতা পরীক্ষা করার পরিবর্তে, রেল একই সময়ে সংগ্রহের সমস্ত ক্যাশে কীগুলি পরীক্ষা করে, ক্যাশে স্টোরের অনুসন্ধান করার সময় বাঁচায়৷
এই ক্যাশিং সাহায্যকারীর একটি অতিরিক্ত সুবিধা হল সংগ্রহের সংক্ষিপ্ত লগিং। প্রথম অনুরোধে, ক্যাশে কীগুলির একটিও পাওয়া যায়নি [0 / 100 cache hits]
, কিন্তু দ্বিতীয় অনুরোধে, তারা সব পাওয়া গেছে [100 / 100 cache hits]
.
ডাটাবেসের কিছু অবজেক্ট আপডেট করার পরে, আমরা দেখতেও পারি কতগুলি কী বাসি ছিল৷
Rendered collection of posts/_post.html.erb [88 / 100 cache hits] (13.4ms)
এই অপ্টিমাইজ করা সংগ্রহ রেন্ডারিং এবং ক্যাশিংয়ের সাথে লাভ করার জন্য অনেক গতির উন্নতি রয়েছে। বৃহত্তর সংগ্রহ রেন্ডার করার সময় আরও বড় পার্থক্য তৈরি করা হবে। আপনার সংগ্রহের জন্য কাস্টমাইজড দৃশ্যের প্রয়োজন না হলে, এই অপ্টিমাইজ করা কৌশলটি হল আপনার রেল অ্যাপগুলির জন্য যাওয়ার উপায়। AppSignal-এ, আমরা আমাদের প্রশাসক দৃষ্টিভঙ্গির মধ্যে উল্লেখযোগ্যভাবে গতি বাড়াতে পেরেছি যা এইভাবে হাজার হাজার রেকর্ড রেন্ডার করছিল৷
রেলে ক্যাশিং সংগ্রহ সম্পর্কে কোন প্রশ্ন আছে? অনুগ্রহ করে আমাদের @AppSignal এ জানাতে দ্বিধা করবেন না! নিবন্ধটি সম্পর্কে আপনার যদি কোনো মন্তব্য থাকে বা আপনার যদি কোনো বিষয় থাকে যা আপনি আমাদের কভার করতে চান, তাহলে অনুগ্রহ করে আমাদের সাথে যোগাযোগ করুন।