কম্পিউটার টিউটোরিয়াল

ফ্র্যাগমেন্ট ক্যাশিং দিয়ে রেলস পারফরম্যান্স অপ্টিমাইজ করুন

যখন একটি রেলস অ্যাপ্লিকেশন একটি রিকোয়েস্ট এক্সেপ্ট করে, কন্ট্রোলার সাধারণত মডেল থেকে অনুরোধকৃত ডেটা চায়। মডেল তারপর ডেটাবেস থেকে সেটি ফেচ করে এবং কন্ট্রোলারের কাছে ফেরত দেয়। কন্ট্রোলার অবশেষে ভিউ রেন্ডার করে যা ডেটাকে হিউম্যান-রিডেবল ফরম্যাটে রিপ্রেজেন্ট করে।

কিছু পরিস্থিতিতে, ভিউ রেন্ডার করা একটি এক্সপেনসিভ অপারেশন, বিশেষ করে যদি ভিউতে অনেক ডেটা প্রদর্শন করতে হয়, যেমন একটি স্টোরে সব উপলব্ধ প্রোডাক্টের লিস্ট দেখানো। এমন ক্ষেত্রে, রিটার্নড ভিউয়ের অংশগুলো ক্যাশ করলে স্পিড আপ হয়, বিশেষ করে যখন ডেটা খুব কম পরিবর্তন হয়।

👋 এবং আপনি যদি এই আর্টিকেল পছন্দ করেন, তবে রুবি (অন রেইলস) পারফরম্যান্স নিয়ে আরও অনেক কিছু লিখেছি, আমাদের রুবি পারফরম্যান্স মনিটরিং চেকলিস্ট দেখুন।

লোকালি ক্যাশিং টেস্ট করা

ক্যাশিং ডেভেলপমেন্টে ডিফল্টভাবে অফ থাকে, যাতে আপনি সবসময় আপনার অ্যাপ থেকে ফ্রেশ রেসপন্স পান। লোকালি ক্যাশিং টেস্ট করতে, আপনাকে আপনার ডেভেলপমেন্ট কনফিগারেশনে সেটি অন করতে হবে।

রেলস ৫-এ, আপনি কমান্ড লাইন থেকে সাময়িকভাবে ক্যাশিং অন করতে পারেন। এটা মেমরি স্টোর ব্যবহার করবে, মানে ক্যাশড ফ্র্যাগমেন্টগুলো ওয়েব সার্ভারের রুবি প্রসেসে মেমরিতে রাখা হবে।

$ 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>

লোকালি পেজ রিকোয়েস্ট করলে, ডেভেলপমেন্ট মোডে, ডেটাবেসে ২৫টি প্রোডাক্ট থাকলে প্রায় ৩০০ মিলিসেকেন্ড লাগে। প্রায় সেটির সব সময় পার্শিয়াল রেন্ডার করার পেছনে খরচ হয়।

সামন্য raket, প্রোডাকশনে রেসপন্স দ্রুত হবে, বান্ডলড অ্যাসেট, কম লগিং এবং দ্রুত ওয়েব সার্ভারের কারণে। ডেভেলপমেন্টের সংখ্যাগুলো একুরেট নয়, কিন্তু সেগুলো দেখাবে আমাদের রিকোয়েস্টের কোন অংশ স্লোয়েস্ট, যাতে আমরা সেটি দ্রুত করতে পারি।

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/index.html.erb within layouts/application (257.5ms)
Completed 200 OK in 295ms(Views: 290.4ms | ActiveRecord: 0.4ms)

এই সব পার্শিয়াল রেন্ডার করার সময় বাঁচাতে, আমরা রেলসের বিল্ট-ইন ফ্র্যাগমেন্ট ক্যাশিং ব্যবহার করতে পারি, যা রেন্ডার্ড ভিউয়ের অংশ একটি ফ্র্যাগমেন্ট হিসেবে স্টোর করে। পরবর্তী রিকোয়েস্টের জন্য, প্রি-সেভড ফ্র্যাগমেন্ট ব্যবহার হয় আবার রেন্ডার করার বদলে।

একটি ফ্র্যাগমেন্ট ক্যাশ করতে, আপনি সেটি 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

ক্যাশ কী 몇몇 অংশ নিয়ে গঠিত:

  • "views/products" হলো ক্যাশ ক্লাস।
  • 42 হলো প্রোডাক্টের আইডি
  • 20180302103130041320 হলো প্রোডাক্টের updated_at তারিখ
  • 75dda06d36880e8b0ae6cac0a44fb56d হলো টেমপ্লেট ট্রির একটি ডাইজেস্ট

এই কী পরিবর্তন হয় যখনই প্রোডাক্ট আপডেট হয়, বা টেমপ্লেটে কিছুই পরিবর্তন হয়। যখন সেটি হয়, এটা ক্যাশে একটি মিস করায়, ফ্র্যাগমেন্ট আবার রেন্ডার হয় এবং একটি নতুন ফ্র্যাগমেন্ট সেভ হয়। এটা নিশ্চিত করে ফ্র্যাগমেন্ট ফ্রেশ থাকে, এমনকি এর কম্পোনেন্ট পরিবর্তন হলে।

ফ্র্যাগমেন্ট ক্যাশিংর বাইরে

যদিও এই উদাহরণে আলোচনা করা ক্যাশড ফ্র্যাগমেন্টগুলো একটি ছোট স্পিডআপ দেয়, ক্যাশিংয়ে আমরা আজ আলোচনা করেছি তার চেয়ে আরও অনেক কিছু আছে। রাশিয়ান ডল ক্যাশিং বা ডেটাবেস কোয়ারী রেজাল্ট ক্যাশিং-এর মতো নিম্ন-স্তরের মেথড ব্যবহার করে বড় স্পিডআপ অর্জন করা যায়।

অবশ্যই, আমরা অ্যাপসিগন্যাল একাডেমির পরবর্তী এপিসোডে এগুলোতে যাব। কোন নির্দিষ্ট বিষয় শিখতে চান? দয়া করে @AppSignal-এ আমাদের জানান। অবশ্যই, আমরা জানতে চাই আপনি এই আর্টিকেল কেমন লাগলো, বা অন্য কোন বিষয়ে জানতে চান।

  1. HTML id অ্যাট্রিবিউট: এলিমেন্টের ইউনিক আইডেন্টিফায়ার

  2. HTML Symbols

  3. HTML Paragraphs

  4. HTML Layouts