কম্পিউটার

রেলগুলি দ্রুত:আপনার ভিউ কর্মক্ষমতা অপ্টিমাইজ করুন৷

এই পোস্টে, আমরা রেল ভিউ পারফরম্যান্স উন্নত করার চেষ্টা করা এবং সত্য পদ্ধতিগুলি দেখব। বিশেষ করে, আমি ডাটাবেসের দক্ষতা, ভিউ ম্যানিপুলেশন এবং ক্যাশিং এর উপর ফোকাস করব।

আমি মনে করি "অকাল অপ্টিমাইজেশন হল সমস্ত মন্দের মূল" বাক্যাংশটি প্রসঙ্গ থেকে একটু বাইরে নেওয়া হয়েছে। আমি প্রায়ই শুনেছি বিকাশকারীরা কোড পর্যালোচনার সময় এটি ব্যবহার করে যখন সাধারণ অপ্টিমাইজেশান কৌশলগুলি নির্দেশ করা হয়। আপনি বিখ্যাত জানেন, "আমি এটিকে কাজ করব এবং তারপরে এটি অপ্টিমাইজ করব" - তারপরে এটি পরীক্ষা করুন - তারপর এটি ডিবাগ করুন - তারপরে এটি আবার পরীক্ষা করুন এবং আরও অনেক কিছু!

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

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

পুরো পোস্ট জুড়ে, আমরা একটি বেসিক রেল অ্যাপে লেগে থাকব, এতে উন্নতি করব এবং ফলাফলের তুলনা করব।

বেসিক রেল অ্যাপে নিম্নলিখিত মডেল রয়েছে:

  • ব্যক্তি (অনেক ঠিকানা আছে)

    • নাম:স্ট্রিং
    • votes_count:integer
  • প্রোফাইল (ব্যক্তির অন্তর্গত)

    • address:string

আমাদের ব্যক্তি মডেল দেখতে এইরকম:

# == Schema Information
#
# Table name: people
#
#  id          :integer          not null, primary key
#  name        :string
#  votes_count :integer
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#
 
class Person < ApplicationRecord
  # Relationships
  has_many :profiles
 
  # Validations
  validates_presence_of :name
  validates_uniqueness_of :name
 
  def vote!
    update votes_count: votes_count + 1
  end
end

এটি আমাদের প্রোফাইল মডেলের কোড:

# == Schema Information
#
# Table name: profiles
#
#  id         :integer          not null, primary key
#  address    :text
#  person_id  :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
 
class Profile < ApplicationRecord
  # Relationships
  belongs_to :person
 
  # Validations
  validates_presence_of :address
end
 

1000 জনকে বসানোর জন্য একটি বীজ ফাইলও রয়েছে। আমরা Faker রত্ন ব্যবহার করে সহজেই এটি করতে পারি।

আমরা এখন অ্যাপ্লিকেশন কন্ট্রোলারে "হোম" নামে একটি অ্যাকশন তৈরি করতে যাচ্ছি৷

def home
  @people = Person.all
end

আমাদের home.html.erb এর কোডটি নিম্নরূপ:

<ul>
  <% @people.each do |person| %>
    <li id="<%= person.id %>"><%= render person %></li>
  <% end %>
</ul>

আসুন একটি ড্রাই রান করি এবং এর বিরুদ্ধে আমাদের পেজের পারফরম্যান্স পরিমাপ করি।

সেই পৃষ্ঠাটি লোড হতে 1066.7ms সময় নিয়েছে। ভাল না! এটিই আমরা কমাতে চাই।

ডাটাবেস কোয়েরি

একটি কার্যকরী অ্যাপ্লিকেশন তৈরির প্রথম ধাপ হল সম্পদের সর্বোচ্চ ব্যবহার। বেশিরভাগ রেল অ্যাপস ডাটাবেস থেকে ভিউতে কিছু রেন্ডার করে, তাই আসুন প্রথমে ডাটাবেস কল অপ্টিমাইজ করার চেষ্টা করি!

এই প্রদর্শনের উদ্দেশ্যে, আমি একটি MySQL ডাটাবেস ব্যবহার করতে যাচ্ছি।

আসুন দেখি কিভাবে 1066ms এর প্রাথমিক লোড ভেঙ্গে যায়।

414.7 'controllers/application_controller#home' চালাতে

...
(0.1ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 996]]
Rendered people/_person.html.erb (1.5ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 997]]
Rendered people/_person.html.erb (2.3ms)
(0.1ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 998]]
Rendered people/_person.html.erb (2.1ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 999]]
Rendered people/_person.html.erb (2.3ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 1000]]
Rendered people/_person.html.erb (2.0ms)
Rendered application/home.html.erb within layouts/application (890.5ms)

Completed 200 OK in 1066ms (Views: 890.5ms | ActiveRecord: 175.4ms)

519.2 এবং 132.8 "application/home.html.erb" এবং "people/_person.html.erb" আংশিক রেন্ডার করতে।

আপনি কি অদ্ভুত কিছু লক্ষ্য করেছেন?

আমরা কন্ট্রোলারে একটি ডাটাবেস কল করেছি, কিন্তু প্রতিটি আংশিক তার নিজস্ব ডাটাবেস কলও করে! উপস্থাপন করছি, N+1 ক্যোয়ারী সমস্যা।

1. N+1 ক্যোয়ারী

এটি একটি খুব জনপ্রিয় এবং সহজ অপ্টিমাইজেশান কৌশল—কিন্তু এটি প্রথম উল্লেখের দাবি রাখে যেহেতু এই ভুলটি খুব প্রচলিত৷

আসুন দেখি "people/_person.html.erb" কি করে:

<ul>
  <li>
    Name: <%= person.name %>
  </li>
  <li>
    Addresses:
      <ul>
        <% person.profiles.each do |profile| %>
          <li><%= profile.address %></li>
        <% end %>
      </ul>
  </li>
</ul>
 
<%= button_to "Vote #{person.votes_count}", vote_person_path(person) %>

মূলত, এটি সেই ব্যক্তির প্রোফাইলের জন্য ডাটাবেস অনুসন্ধান করে এবং প্রতিটিকে রেন্ডার করে। তাই এটি N ক্যোয়ারী করে (যেখানে N হল মানুষের সংখ্যা) এবং 1টি ক্যোয়ারী আমরা কন্ট্রোলারে করেছি—এভাবে, N+1।

এটি অপ্টিমাইজ করতে, MySQL ডাটাবেস যোগদান ব্যবহার করুন এবং Rails ActiveRecord ফাংশন অন্তর্ভুক্ত করে।

নিচের সাথে মেলে কন্ট্রোলার পরিবর্তন করা যাক:

def home
  @people = Person.all.includes(:profiles)
end

সমস্ত লোক 1টি MySQL ক্যোয়ারী দ্বারা লোড হয়, এবং তাদের নিজ নিজ ক্যোয়ারী অন্য একটিতে লোড হয়। N+1 নিয়ে আসা হচ্ছে মাত্র 2টি প্রশ্নের জন্য।

চলুন দেখা যাক কিভাবে এটি কর্মক্ষমতা বাড়ায়!

পৃষ্ঠাটি লোড করতে আমাদের সময় লেগেছে মাত্র 936ms। আপনি নীচে দেখতে পাচ্ছেন যে "application_controller#home" অ্যাকশনটি 2টি MySQL প্রশ্ন করে।

Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.2ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.2ms)

Rendered application/home.html.erb within layouts/application (936.0ms)
Completed 200 OK in 936ms (Views: 927.1ms | ActiveRecord: 9.3ms)

2. আপনি যা ব্যবহার করবেন শুধুমাত্র তা লোড করুন

এইভাবে হোমপেজ দেখায়৷

আপনি দেখতে পাচ্ছেন আমাদের কেবল ঠিকানা দরকার, অন্য কিছু নয়। কিন্তু "_person.html.erb" অংশে আমরা প্রোফাইল অবজেক্ট লোড করি। আসুন দেখি কিভাবে আমরা সেই পরিবর্তন করতে পারি।

<li>
  Addresses:
  <ul>
    <% person.profiles.pluck(:address).each do |address| %>
      <li><%= address %></li>
    <% end %>
  </ul>
</li>

N+1 প্রশ্নগুলির আরও গভীরভাবে দেখার জন্য, ActiveRecord কর্মক্ষমতা পড়ুন:N+1 কোয়েরি অ্যান্টিপ্যাটার্ন৷

প্রোটিপ:আপনি এটির জন্য একটি সুযোগ তৈরি করতে পারেন এবং এটি "models/profile.rb" ফাইলে যোগ করতে পারেন। আপনার ভিউ ফাইলে কাঁচা ডাটাবেস কোয়েরি খুব বেশি কাজে লাগে না।

3. সমস্ত ডাটাবেস কল কন্ট্রোলারে সরান

ধরা যাক, এই মেক-বিলিভ অ্যাপ্লিকেশনটির ভবিষ্যতে, আপনি হোম পেজে মোট ব্যবহারকারীর সংখ্যা প্রদর্শন করতে চান৷

সরল ! চলুন এই ভিউতে একটি কল করি যা এইরকম দেখাচ্ছে:

# of People: <%= @people.count %>

ঠিক আছে, এটা যথেষ্ট সহজ।

আরেকটি প্রয়োজন আছে—আপনাকে একটি UI উপাদান তৈরি করতে হবে যা পৃষ্ঠার অগ্রগতি প্রদর্শন করে। আসুন এখন পৃষ্ঠায় লোকের সংখ্যাকে মোট গণনা দিয়ে ভাগ করি।

Progress: <%= index / @people.count %>

দুর্ভাগ্যবশত, আপনার সহকর্মী জানেন না যে আপনি ইতিমধ্যেই এই ক্যোয়ারীটি করেছেন এবং তারা এটিকে বার বার ভিউতে তৈরি করে চলেছে৷

আপনার নিয়ন্ত্রক এই মত দেখতে ছিল:

def home
  @people = Person.all.includes(:profiles)
  @people_count = @people.count
end

ইতিমধ্যে গণনা করা ভেরিয়েবলগুলি পুনরায় ব্যবহার করা সহজ হত৷

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

4. আপনি যেখানেই পারেন পেজিনেট করুন!

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

একটি বিরক্তিকর কারণ এটি হল যে ব্যবহারকারীদের "পরবর্তী পৃষ্ঠা" এ ক্লিক করতে হবে। এর জন্য, আপনি আপনার ব্যবহারকারীদের আরও ভাল অভিজ্ঞতা দিতে "অসীম স্ক্রোলিং" দেখতে পারেন৷

HTML পুনরায় লোড এড়ানো

একটি ঐতিহ্যবাহী রেল অ্যাপে, HTML ভিউ রেন্ডারিং অনেক সময় নেয়। সৌভাগ্যবশত, এটি কমাতে আপনি নিতে পারেন এমন কিছু ব্যবস্থা আছে।

1. টার্বোলিঙ্কস

এটি আপনার স্ট্যান্ডার্ড রেল অ্যাপে মোড়ানো আসে। Turbolinks হল একটি জাভাস্ক্রিপ্ট লাইব্রেরি যা সর্বত্র কাজ করে (এমনকি স্থির পৃষ্ঠাগুলিতে যেমন রেল ছাড়াই) এবং অসমর্থিত ব্রাউজারগুলিতে সুন্দরভাবে অবনমিত হয়৷

এটি প্রতিটি লিঙ্ককে একটি AJAX অনুরোধে রূপান্তর করে এবং JS এর ​​মাধ্যমে পৃষ্ঠার সম্পূর্ণ অংশ প্রতিস্থাপন করে। এটি কার্যক্ষমতাকে ব্যাপকভাবে উন্নত করে কারণ এটিকে CSS, JS এবং চিত্রগুলি পুনরায় লোড করতে হবে না৷

যাইহোক, কাস্টম JS লেখার সময় আপনাকে "Turbolinks safe JS" লিখতে অতিরিক্ত সতর্কতা অবলম্বন করতে হবে। এখানে এই সম্পর্কে আরো পড়ুন.

2. AJAX অনুরোধগুলি ব্যবহার করুন

Turbolinks এর মতো একই শিরায়, আপনি আপনার কিছু লিঙ্ক এবং বোতামকে AJAX অনুরোধে রূপান্তর করতে পারেন। এখানে পার্থক্য হল যে Turbolinks এর মত পুরো বডি প্রতিস্থাপন করার পরিবর্তে HTML কি প্রতিস্থাপন করা হবে তা আপনি নিয়ন্ত্রণ করতে পারেন।

চলুন AJAX-এর কাজ দেখি!

নমুনা অ্যাপে, প্রতিটি ব্যবহারকারীর জন্য একটি "ভোট" বোতাম রয়েছে৷ চলুন পরিমাপ করা যাক সেই ক্রিয়াটি করতে কতক্ষণ লাগে৷

Started POST "/people/1/vote" for 127.0.0.1 at 2020-01-21 14:50:49 +0530
Processing by PeopleController#vote as HTML
  Person Load (0.3ms)  SELECT  "people".* FROM "people" WHERE "people"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  Person Exists (4.5ms)  SELECT  1 AS one FROM "people" WHERE "people"."name" = ? AND ("people"."id" != ?) LIMIT ?  [["name", "Deon Waelchi"], ["id", 1], ["LIMIT", 1]]
  SQL (1.0ms)  UPDATE "people" SET "votes_count" = ?, "updated_at" = ? WHERE "people"."id" = ?  [["votes_count", 1], ["updated_at", "2020-01-21 09:20:49.941928"], ["id", 1]]

Redirected to https://localhost:3000/
Completed 302 Found in 24ms (ActiveRecord: 7.5ms)


Started GET "/" for 127.0.0.1 at 2020-01-21 14:50:49 +0530
Processing by ApplicationController#home as HTML
  Rendering application/home.html.erb within layouts/application

  Rendered people/_person.html.erb (2.4ms)
   (0.3ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 30]]
  Rendered people/_person.html.erb (2.2ms)
  ...

  Rendered application/home.html.erb within layouts/application (159.8ms)
Completed 200 OK in 190ms (Views: 179.0ms | ActiveRecord: 6.8ms)

এটি পৃষ্ঠাটি পুনরায় লোড করতে একই পরিমাণ সময় নেয় এবং প্রকৃত ভোটিং অংশের জন্য একটু অতিরিক্ত সময় নেয়৷

এর একটি AJAX অনুরোধ করা যাক. এখন, আমাদের "people/_person.html.erb" এর মত দেখাচ্ছে:

<%= button_to "Vote #{person.votes_count}", vote_person_path(person), remote: true %>

আমাদের কন্ট্রোলার অ্যাকশন একটি JS প্রতিক্রিয়া প্রদান করে, যা এইরকম দেখায়:

$("#<%= @person.id %>").html("<%= j render(partial: 'person', locals: {person: @person}) %>");

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

ফলাফল?

Started POST "/people/1/vote" for 127.0.0.1 at 2020-01-21 14:52:56 +0530
Processing by PeopleController#vote as JS

  Person Load (0.2ms)  SELECT  "people".* FROM "people" WHERE "people"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  Person Exists (0.3ms)  SELECT  1 AS one FROM "people" WHERE "people"."name" = ? AND ("people"."id" != ?) LIMIT ?  [["name", "Deon Waelchi"], ["id", 1], ["LIMIT", 1]]
  SQL (0.4ms)  UPDATE "people" SET "votes_count" = ?, "updated_at" = ? WHERE "people"."id" = ?  [["votes_count", 2], ["updated_at", "2020-01-21 09:22:56.532281"], ["id", 1]]
   (1.6ms)  commit transaction
  Rendering people/vote.js.erb
   (0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 1]]

  Rendered people/_person.html.erb (3.2ms)
  Rendered people/vote.js.erb (6.3ms)
Completed 200 OK in 31ms (Views: 14.6ms | ActiveRecord: 2.9ms)

30ms! এটাই! এটা কতটা মহান?

প্রোটিপ:কখন/কী প্রতিস্থাপন করতে হবে তা নির্ধারণ করতে আপনি যদি একগুচ্ছ HTML আইডি এবং ক্লাস নিয়ে গোলমাল করতে না চান, তাহলে render_async রত্ন ব্যবহার করার কথা বিবেচনা করুন। এটি বাক্সের বাইরে অনেক ভারী জিনিস তুলে নেয়৷

3. ওয়েবসকেট ব্যবহার করুন

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

WebSockets প্রযুক্তির একটি দুর্দান্ত অংশ যা ক্লায়েন্ট নতুন তথ্যের জন্য অনুরোধ করার পরিবর্তে আপনার সার্ভারকে ক্লায়েন্টের কাছে আপডেটগুলি পুশ করতে দেয়৷

আপনি যখন গতিশীল ওয়েবপেজ তৈরি করতে চান তখন এটি কার্যকর হতে পারে। কল্পনা করুন যে আপনাকে আপনার ওয়েবসাইটে একটি গেমের স্কোর প্রদর্শন করতে হবে। নতুন কন্টেন্ট আনতে আপনি পারেন,

  • আপনার ব্যবহারকারীদের পুরো পৃষ্ঠা পুনরায় লোড করতে বলুন
  • একটি পুনরায় লোড বোতাম প্রদান করুন যা শুধুমাত্র স্কোর রিফ্রেশ করে
  • প্রতি সেকেন্ডে ব্যাকএন্ড পোলিং করতে JavaScript ব্যবহার করুন
    • এটি সার্ভারে পিং করতে থাকবে এমনকি ডেটাতে কোনো পরিবর্তন না থাকলেও
    • প্রতিটি ক্লায়েন্ট প্রতি সেকেন্ডে কল করবে - সহজেই সার্ভারকে অভিভূত করবে
  • ওয়েবসকেট ব্যবহার করুন!

WebSockets-এর সাহায্যে, সার্ভারের নিয়ন্ত্রণ থাকে কখন সমস্ত ক্লায়েন্টের কাছে ডেটা পুশ করতে হবে (বা এমনকি একটি উপসেট)। যেহেতু সার্ভার জানে কখন ডেটা পরিবর্তিত হয়, এটি শুধুমাত্র যখন পরিবর্তন হয় তখনই ডেটা পুশ করতে পারে!

Rails 5 ActionCable প্রকাশ করেছে, যা আপনাকে ওয়েবসকেটের সমস্ত জিনিস পরিচালনা করতে দেয়। এটি সার্ভারে সাবস্ক্রাইব করার জন্য ক্লায়েন্টের জন্য একটি JS ফ্রেমওয়ার্ক এবং সার্ভারের পরিবর্তনগুলি প্রকাশ করার জন্য একটি ব্যাকএন্ড ফ্রেমওয়ার্ক প্রদান করে। অ্যাকশন ক্যাবলের সাহায্যে আপনার পছন্দের যেকোনো ওয়েবসকেট পরিষেবা বেছে নেওয়ার ক্ষমতা রয়েছে। এটি হতে পারে Faye, একটি স্ব-পরিচালিত ওয়েব সকেট পরিষেবা, অথবা Pusher একটি সাবস্ক্রিপশন পরিষেবা৷

ব্যক্তিগতভাবে, আমি এটির জন্য একটি সাবস্ক্রিপশন বেছে নেব, কারণ এটি আপনার পরিচালনার জন্য প্রয়োজনীয় জিনিসগুলির সংখ্যা হ্রাস করে৷

ঠিক আছে, WebSockets-এ ফিরে যান। একবার আপনি ActionCable সেট আপ করা হয়ে গেলে, আপনার ভিউ সার্ভার থেকে JSON ইনপুট শুনতে সক্ষম হবে না। একবার এটি পেয়ে গেলে, আপনার লেখা হুক অ্যাকশনগুলি সংশ্লিষ্ট HTML সামগ্রীকে প্রতিস্থাপন করবে৷

Rails docs এবং Pusher-এর কাছে WebSockets দিয়ে কীভাবে তৈরি করা যায় সে সম্পর্কে দারুণ টিউটোরিয়াল রয়েছে। সেগুলি অবশ্যই পড়া উচিত!

ক্যাশিং

লোড টাইমের বেশিরভাগ সময় রেন্ডারিং ভিউতে ব্যবহৃত হয়। এর মধ্যে রয়েছে সমস্ত CSS, JS এবং ছবি লোড করা, ERB ফাইল থেকে HTML রেন্ডার করা এবং আরও অনেক কিছু।

লোড সময়ের একটি অংশ কমানোর একটি উপায় হল আপনার অ্যাপ্লিকেশনের এমন অংশগুলি সনাক্ত করা যা আপনি জানেন যে কিছু সময়ের জন্য বা একটি ইভেন্ট না হওয়া পর্যন্ত স্থির থাকবে৷

আমাদের উদাহরণে, এটা স্পষ্ট যে কেউ ভোট না দেওয়া পর্যন্ত, হোম পেজটি মূলত সবার জন্য একই রকম দেখাবে (বর্তমানে ব্যবহারকারীদের তাদের ঠিকানা সম্পাদনা করার কোনো বিকল্প নেই)। আসুন একটি ইভেন্ট (ভোট) না হওয়া পর্যন্ত পুরো "home.html.erb" পৃষ্ঠাটি ক্যাশে করার চেষ্টা করি৷

আসুন ডালি মণি ব্যবহার করি। এটি তথ্যের টুকরোগুলি দ্রুত সংরক্ষণ এবং পুনরুদ্ধার করতে মেমক্যাশেড ব্যবহার করে। মেমক্যাশেডের কাছে স্টোরেজের জন্য কোনো ডেটাটাইপ নেই, যা আপনাকে আপনার পছন্দ মতো সঞ্চয় করার জন্য ছেড়ে দেয়।

1. ক্যাশিং ভিউ

ক্যাশিং ছাড়াই 2000 রেকর্ডের লোড টাইম হল 3500ms!

আসুন "home.html.erb" এ সবকিছু ক্যাশে করি। এটা সহজ,

<% cache do %>
  <ul>
    <% @people.each do |person| %>
      <li id="<%= person.id %>"><%= render person %></li>
    <% end %>
  </ul>
<% end %>

এরপরে, ডালি রত্নটি ইনস্টল করুন এবং "development.rb"-এ ক্যাশে স্টোরটি এতে পরিবর্তন করুন:

config.cache_store = :dalli_store

তারপর, আপনি যদি ম্যাক বা লিনাক্সে থাকেন, তাহলে এইভাবে মেমক্যাচেড পরিষেবা শুরু করুন:

memcached -vv

এখন আবার লোড করা যাক!!

এটা প্রায় 537ms লেগেছে! এটি গতিতে 7x উন্নতি!

আপনি আরও দেখতে পাবেন যে সেখানে অনেক কম MySQL কোয়েরি রয়েছে কারণ সম্পূর্ণ HTML মেমক্যাশে সংরক্ষিত ছিল এবং আপনার ডাটাবেসকে কখনো পিং না করেই সেখান থেকে আবার পড়া হয়।

আপনি যদি আপনার অ্যাপ্লিকেশন লগগুলিতে পপ অন করেন, তাহলে আপনি দেখতে পাবেন যে এই পুরো পৃষ্ঠাটি ক্যাশে থেকে পড়া হয়েছে৷

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

2. ক্যাশিং ডেটাবেস কোয়েরি

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

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

গণনা বারবার পুনরাবৃত্তি করার পরিবর্তে, আপনি এটি ক্যাশে করতে পারেন!

def team_size
  Rails.cache.fetch(:team_size, expires_in: 8.hour) do
    analytics_client = AnalyticsClient.query!(self)
    analytics_client.team_size
  end
end

এই ক্যাশে 8 ঘন্টা পরে স্বয়ংক্রিয়ভাবে মেয়াদ শেষ হবে। একবার এটি হয়ে গেলে, গণনাটি আবার করা হবে এবং সর্বশেষ মানটি পরবর্তী 8 ঘন্টার জন্য ক্যাশে করা হবে৷

3. ডাটাবেস ইনডেক্স

এছাড়াও আপনি সূচী ব্যবহার করে ক্যোয়ারী ত্বরান্বিত করতে পারেন। একজন ব্যক্তির সমস্ত ঠিকানা আনার জন্য একটি সহজ প্রশ্ন,

person.addresses

এই ক্যোয়ারী ঠিকানা সারণীকে সেই সমস্ত ঠিকানা ফেরত দিতে বলে যেখানে person_id আছে কলাম হল person.id . সূচী ব্যতীত, ডাটাবেসকে প্রতিটি সারিটি person.id এর সাথে মেলে কিনা তা পরীক্ষা করতে পৃথকভাবে পরীক্ষা করতে হবে . যাইহোক, সূচীগুলির সাথে, ডাটাবেসে ঠিকানাগুলির একটি তালিকা রয়েছে যা একটি নির্দিষ্ট person.id এর সাথে মেলে .

ডাটাবেস সূচী সম্পর্কে আরও জানতে এখানে একটি দুর্দান্ত সংস্থান রয়েছে!

সারাংশ

এই পোস্টে, আমরা ডেটাবেস ব্যবহারে উন্নতি করে, তৃতীয় পক্ষের সরঞ্জাম এবং পরিষেবাগুলি ব্যবহার করে এবং ব্যবহারকারীরা যা দেখেন তা সীমিত করে কীভাবে আপনার Rails অ্যাপের ভিউ পারফরম্যান্স উন্নত করতে হয় তা অনুসন্ধান করেছি৷

আপনি যদি আপনার অ্যাপের পারফরম্যান্স উন্নত করতে চান, তাহলে সহজভাবে শুরু করুন এবং সাথে সাথে পরিমাপ করতে থাকুন! আপনার ডাটাবেস প্রশ্নগুলি পরিষ্কার করুন, তারপরে আপনি যেখানেই পারেন AJAX অনুরোধ তৈরি করুন এবং অবশেষে যতটা সম্ভব ভিউ ক্যাশে করুন। আপনি এর পরে WebSockets এবং ডাটাবেস ক্যাশে যেতে পারেন৷

যাইহোক, সতর্ক থাকুন-অপ্টিমাইজেশন একটি পিচ্ছিল ঢাল। আপনি নিজেকে আমার মতই আসক্ত মনে করতে পারেন!

পি.এস. উৎপাদনে আপনার Rails অ্যাপের কর্মক্ষমতা নিরীক্ষণের জন্য, AppSignal-এর APM দেখুন - Ruby devs-এর জন্য Ruby devs দ্বারা নির্মিত৷ 🚀


  1. আপনার রেল অ্যাপ পরীক্ষা করার জন্য একটি ডকার কন্টেইনার সেট আপ করুন

  2. আপনার রেল অ্যাপের কর্মক্ষমতা বোঝার একটি নতুন উপায়

  3. আরো ভালো পারফরম্যান্সের জন্য কীভাবে আপনার ম্যাক অপ্টিমাইজ করবেন?

  4. YouTube অ্যানালিটিক্স:মেট্রিক্স বুঝুন এবং আপনার ভিডিও পারফরম্যান্স অপ্টিমাইজ করুন