इस पोस्ट में, हम रेल के प्रदर्शन को बेहतर बनाने के आजमाए हुए और सही तरीकों पर गौर करेंगे। विशेष रूप से, मैं डेटाबेस दक्षता, दृश्य हेरफेर और कैशिंग पर ध्यान केंद्रित करूंगा।
मुझे लगता है कि वाक्यांश "समयपूर्व अनुकूलन सभी बुराइयों की जड़ है" को संदर्भ से थोड़ा सा लिया गया है। मैंने अक्सर सुना है कि डेवलपर्स कोड समीक्षाओं के दौरान इसका उपयोग करते हैं जब सरल अनुकूलन तकनीकों की ओर इशारा किया जाता है। आप प्रसिद्ध को जानते हैं, "मैं इसे काम कर लूंगा और फिर इसे अनुकूलित करूंगा" - फिर इसका परीक्षण करें - फिर इसे डीबग करें - फिर इसका परीक्षण करें, और इसी तरह!
खैर, शुक्र है कि कुछ सरल और प्रभावी प्रदर्शन और अनुकूलन तकनीकें हैं जिनका उपयोग आप उस समय से कर सकते हैं जब आप कोड लिखना शुरू करते हैं।
<ब्लॉकक्वॉट>यदि आप इस लेख को पसंद करते हैं, तो हमारी रूबी प्रदर्शन निगरानी चेकलिस्ट में अन्य रूबी (ऑन रेल्स) प्रदर्शन लेखों पर एक नज़र डालें।
पूरी पोस्ट के दौरान, हम एक बुनियादी रेल ऐप से चिपके रहेंगे, उसमें सुधार करेंगे और परिणामों की तुलना करेंगे।
मूल रेल ऐप में निम्नलिखित मॉडल हैं:
-
व्यक्ति (कई पते हैं)
- नाम:स्ट्रिंग
- वोट_गणना:पूर्णांक
-
प्रोफ़ाइल (व्यक्ति से संबंधित)
- पता:स्ट्रिंग
हमारा व्यक्ति मॉडल ऐसा दिखता है:
# == 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 लोगों को आबाद करने के लिए एक बीज फ़ाइल भी है। फ़ेकर रत्न का उपयोग करके हम इसे आसानी से कर सकते हैं।
अब हम ApplicationController में "होम" नामक एक क्रिया बनाने जा रहे हैं।
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 'नियंत्रक/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 क्वेरी समस्या।
<एच3>1. एन+1 प्रश्नयह एक बहुत ही लोकप्रिय और सरल अनुकूलन तकनीक है—लेकिन यह पहले उल्लेख के योग्य है क्योंकि यह गलती इतनी प्रचलित है।
आइए देखें कि "लोग/_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)
<एच3>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 क्वेरीज़ एंटीपैटर्न।
ProTip:आप इसके लिए एक स्कोप बना सकते हैं और इसे "models/profile.rb" फाइल में जोड़ सकते हैं। आपकी दृश्य फ़ाइलों में अपरिष्कृत डेटाबेस क्वेरी अधिक काम की नहीं हैं।
<एच3>3. सभी डेटाबेस कॉल्स को कंट्रोलर के पास ले जाएँमान लें, भविष्य में इस काल्पनिक अनुप्रयोग के भविष्य में, आप होम पेज पर उपयोगकर्ताओं की कुल संख्या प्रदर्शित करना चाहेंगे।
सरल! आइए इस तरह दिखने वाले दृश्य में कॉल करें:
# of People: <%= @people.count %>
ठीक है, यह काफी आसान है।
एक और आवश्यकता है—आपको एक UI तत्व बनाने की आवश्यकता है जो पृष्ठ प्रगति को प्रदर्शित करता है। आइए अब पृष्ठ पर लोगों की संख्या को कुल संख्या से विभाजित करें।
Progress: <%= index / @people.count %>
दुर्भाग्य से, आपके सहयोगी को यह नहीं पता है कि आप पहले ही यह प्रश्न कर चुके हैं और वे इसे बार-बार विचारों में बनाने के लिए आगे बढ़ते हैं।
अगर आपका नियंत्रक इस तरह दिखता:
def home
@people = Person.all.includes(:profiles)
@people_count = @people.count
end
पहले से परिकलित चरों का पुन:उपयोग करना आसान होता।
हालांकि यह पृष्ठ लोड गति में प्रत्यक्ष सुधार में योगदान नहीं देता है, यह विभिन्न दृश्य पृष्ठों से डेटाबेस में कई कॉल को रोकता है और आपको अनुकूलन के लिए तैयार करने में मदद करता है जिसे आप बाद में कर सकते हैं, जैसे कैशिंग।
<एच3>4. जहाँ भी आप कर सकते हैं पेजिनेट करें!जैसे केवल आपको जो चाहिए उसे लोड करना, यह केवल वही दिखाने में मदद करता है जो आपको चाहिए! पेजिनेशन के साथ, विचार जानकारी के एक हिस्से को प्रस्तुत करते हैं और बाकी को मांग पर लोड करने के लिए रखते हैं। यह बहुत सारे मिलीसेकंड को शेव करता है! will_paginate और kaminari रत्न आपके लिए मिनटों में ऐसा कर देते हैं।
इसका एक कारण यह है कि उपयोगकर्ताओं को "अगला पृष्ठ" पर क्लिक करते रहना पड़ता है। उसके लिए, आप अपने उपयोगकर्ताओं को बेहतर अनुभव देने के लिए "अनंत स्क्रॉलिंग" भी देख सकते हैं।
HTML रीलोड से बचना
एक पारंपरिक रेल ऐप में, HTML व्यू रेंडरिंग में बहुत समय लगता है। सौभाग्य से, आप इसे कम करने के लिए कुछ उपाय कर सकते हैं।
<एच3>1. टर्बोलिंक्सयह आपके मानक रेल ऐप में लिपटा हुआ आता है। Turbolinks एक JavaScript लाइब्रेरी है जो हर जगह काम करती है (यहां तक कि रेल के बिना भी, जैसे कि स्थिर पृष्ठों पर) और असमर्थित ब्राउज़र पर इनायत से खराब हो जाती है।
यह प्रत्येक लिंक को AJAX अनुरोध में परिवर्तित करता है और पृष्ठ के पूरे भाग को JS के माध्यम से बदल देता है। यह प्रदर्शन में बहुत सुधार करता है क्योंकि इसमें CSS, JS और छवियों को पुनः लोड करने की आवश्यकता नहीं होती है।
हालांकि, कस्टम जेएस लिखते समय आपको "टर्बोलिंक्स सुरक्षित जेएस" लिखने के लिए अतिरिक्त सावधानी बरतनी होगी। इसके बारे में यहाँ और पढ़ें।
<एच3>2. AJAX अनुरोधों का उपयोग करेंTurbolinks की तरह ही, आप अपने कुछ लिंक और बटन को AJAX अनुरोधों में भी बदल सकते हैं। यहां अंतर यह है कि आप टर्बोलिंक्स की तरह पूरे शरीर को बदलने के बजाय एचटीएमएल को क्या बदल सकते हैं, इसे नियंत्रित करने के लिए मिलता है।
आइए 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}) %>");
जैसा कि आप देख सकते हैं, हम केवल वही सामग्री बदल रहे हैं जिसकी हमें आवश्यकता है। हम एक div पर हुक करने और उसे बदलने के लिए एक HTML आईडी प्रदान करते हैं। बेशक, हम केवल बटन सामग्री को बदलकर इसे और अधिक अनुकूलित कर सकते हैं, लेकिन इस पोस्ट के प्रयोजनों के लिए, आइए पूरे आंशिक को बदल दें।
परिणाम?
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! इतना ही! वह कितना अच्छा है?
ProTip:यदि आप HTML आईडी और कक्षाओं के एक समूह के साथ खिलवाड़ नहीं करना चाहते हैं, तो यह पता लगाने के लिए कि कब/क्या बदलना है, render_async रत्न का उपयोग करने पर विचार करें। यह बॉक्स के बाहर भारी भारोत्तोलन करता है।
<एच3>3. वेबसोकेट का उपयोग करेंHTML रीलोड के बारे में सबसे अच्छी चीजों में से एक यह है कि यह आपको हर बार सर्वर से ताजा सामग्री प्राप्त करता है। AJAX अनुरोध के साथ, आप केवल छोटे स्निपेट के लिए नवीनतम सामग्री देखते हैं।
WebSockets एक बेहतरीन तकनीक है जो आपके सर्वर को क्लाइंट को नई जानकारी के लिए अनुरोध करने के बजाय क्लाइंट को अपडेट पुश करने देती है।
यह तब उपयोगी हो सकता है जब आपको गतिशील वेबपेज बनाने की आवश्यकता हो। कल्पना कीजिए कि आपको अपनी वेबसाइट पर किसी गेम का स्कोर प्रदर्शित करने की आवश्यकता है। नई सामग्री लाने के लिए आप कर सकते हैं,
- अपने उपयोगकर्ताओं को पूरे पृष्ठ को पुनः लोड करने के लिए कहें
- एक पुनः लोड बटन प्रदान करें जो केवल स्कोर को ताज़ा करता है
- बैकएंड पर हर सेकेंड पोलिंग जारी रखने के लिए जावास्क्रिप्ट का उपयोग करें
- डेटा में कोई बदलाव न होने पर भी यह सर्वर को पिंग करता रहेगा
- हर क्लाइंट हर सेकेंड कॉल करेगा - सर्वर पर आसानी से हावी हो जाएगा
- वेबसॉकेट का उपयोग करें!
वेबसाकेट के साथ, सर्वर का नियंत्रण होता है कि सभी क्लाइंट (या यहां तक कि एक सबसेट) को डेटा कब पुश करना है। चूंकि सर्वर जानता है कि डेटा कब बदलता है, यह परिवर्तन होने पर ही डेटा को पुश कर सकता है!
रेल 5 ने एक्शनकेबल जारी किया, जो आपको वेबसाकेट की सभी चीजों को प्रबंधित करने देता है। यह क्लाइंट को सर्वर की सदस्यता के लिए एक JS फ्रेमवर्क प्रदान करता है और सर्वर के लिए परिवर्तनों को प्रकाशित करने के लिए एक बैकएंड फ्रेमवर्क प्रदान करता है। एक्शन केबल के साथ, आप अपनी पसंद की किसी भी वेबसॉकेट सेवा को चुनने की क्षमता रखते हैं। यह Faye, एक स्व-प्रबंधित वेब सॉकेट सेवा, या Pusher एक सदस्यता सेवा हो सकती है।
व्यक्तिगत रूप से, मैं इसके लिए एक सदस्यता चुनूंगा, क्योंकि यह उन चीजों की संख्या को कम कर देता है जिन्हें आपको प्रबंधित करने की आवश्यकता होती है।
ठीक है, वेबसाकेट पर वापस। एक बार जब आप एक्शनकेबल सेट कर लेते हैं, तो आपका दृश्य सर्वर से JSON इनपुट को सुनने में सक्षम नहीं होगा। इसे प्राप्त करने के बाद, आपके द्वारा लिखी गई हुक क्रियाएं संबंधित HTML सामग्री को प्रतिस्थापित कर देंगी।
रेल डॉक्स और पुशर के पास वेबसाकेट के साथ निर्माण करने के तरीके पर बहुत अच्छे ट्यूटोरियल हैं। उन्हें अवश्य पढ़ना चाहिए!
कैशिंग
दृश्य प्रस्तुत करने में अधिकांश लोड समय का उपयोग किया जाता है। इसमें सभी सीएसएस, जेएस और छवियों को लोड करना, ईआरबी फाइलों से एचटीएमएल प्रस्तुत करना और बहुत कुछ शामिल है।
लोड समय के एक हिस्से को कम करने का एक तरीका यह है कि आप अपने एप्लिकेशन के उन हिस्सों की पहचान करें जिन्हें आप जानते हैं कि कुछ समय के लिए या कोई घटना होने तक स्थिर रहेंगे।
हमारे उदाहरण में, यह स्पष्ट है कि जब तक कोई वोट नहीं देता, तब तक होम पेज अनिवार्य रूप से सभी के लिए समान दिखाई देगा (वर्तमान में उपयोगकर्ताओं के पास अपने पते संपादित करने का कोई विकल्प नहीं है)। आइए एक ईवेंट (वोट) होने तक संपूर्ण "home.html.erb" पृष्ठ को कैश करने का प्रयास करें।
आइए दल्ली रत्न का प्रयोग करें। यह जानकारी के टुकड़ों को जल्दी से संग्रहीत और पुनर्प्राप्त करने के लिए मेम्केड का उपयोग करता है। Memcached में संग्रहण के लिए कोई डेटा प्रकार नहीं होता है, जिससे आप जो कुछ भी पसंद करते हैं उसे अनिवार्य रूप से संग्रहीत कर सकते हैं।
<एच3>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
फिर, यदि आप Mac या Linux पर हैं, तो बस इस तरह Memcached सेवा प्रारंभ करें:
memcached -vv
अब पुनः लोड करते हैं !!
इसमें लगभग 537ms लगे! यह गति में 7x का सुधार है!
आप यह भी देखेंगे कि बहुत कम MySQL क्वेरीज़ हैं क्योंकि संपूर्ण HTML मेम्केड में संग्रहीत किया गया था और आपके डेटाबेस को कभी भी पिंग किए बिना, वहां से फिर से पढ़ा गया था।
यदि आप अपने एप्लिकेशन लॉग पर पॉप अप करते हैं, तो आप यह भी देखेंगे कि यह पूरा पृष्ठ कैशे से पढ़ा गया था।
निश्चित रूप से यह उदाहरण कैशिंग देखने की सतह को खरोंच कर रहा है। आप आंशिक रेंडरिंग को कैश कर सकते हैं और इसे प्रत्येक व्यक्ति ऑब्जेक्ट तक सीमित कर सकते हैं (इसे फ़्रैगमेंट कैशिंग कहा जाता है) या आप पूरे संग्रह को स्वयं कैश कर सकते हैं (इसे संग्रह कैशिंग कहा जाता है)। इसके अलावा अधिक नेस्टेड व्यू रेंडरिंग के लिए, आप रूसी गुड़िया कैशिंग कर सकते हैं।
<एच3>2. डेटाबेस क्वेरी को कैशिंग करनादृश्य गति को बेहतर बनाने के लिए आप एक और अनुकूलन कर सकते हैं जो जटिल डेटाबेस प्रश्नों को कैश करना है। यदि आपका एप्लिकेशन आंकड़े और विश्लेषण दिखाता है, तो संभावना है कि आप प्रत्येक मीट्रिक की गणना करने के लिए एक जटिल डेटाबेस क्वेरी कर रहे हैं। आप उस के आउटपुट को Memcached में स्टोर कर सकते हैं और फिर उसे टाइमआउट असाइन कर सकते हैं। इसका मतलब है कि समय समाप्त होने के बाद, गणना फिर से की जाएगी और फिर कैश में संग्रहीत की जाएगी।
उदाहरण के लिए, मान लें कि एप्लिकेशन को उपयोगकर्ता टीम के आकार को प्रदर्शित करने की आवश्यकता है। यह एक जटिल गणना हो सकती है जिसमें प्रत्यक्ष रिपोर्टी, आउटसोर्स सलाहकार और बहुत कुछ शामिल हैं।
गणना को बार-बार दोहराने के बजाय, आप इसे कैश कर सकते हैं!
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>3. डेटाबेस इंडेक्सआप अनुक्रमणिका का उपयोग करके प्रश्नों को गति भी दे सकते हैं। किसी व्यक्ति के सभी पते प्राप्त करने के लिए एक सरल क्वेरी,
person.addresses
यह क्वेरी पता तालिका को उन सभी पतों को वापस करने के लिए कहती है जहां person_id
कॉलम है person.id
. अनुक्रमणिका के बिना, डेटाबेस को प्रत्येक पंक्ति का व्यक्तिगत रूप से निरीक्षण करना होता है ताकि यह जांचा जा सके कि यह person.id
. से मेल खाता है या नहीं . हालांकि, इंडेक्स के साथ, डेटाबेस में पतों की एक सूची होती है जो एक निश्चित person.id
. से मेल खाती है ।
डेटाबेस अनुक्रमणिका के बारे में अधिक जानने के लिए यहां एक बढ़िया संसाधन है!
सारांश
इस पोस्ट में, हमने यह पता लगाया कि डेटाबेस उपयोग में सुधार करके, तृतीय-पक्ष टूल और सेवाओं का उपयोग करके और उपयोगकर्ताओं को जो दिखाई देता है उसे प्रतिबंधित करके अपने रेल ऐप के दृश्य प्रदर्शन को कैसे बेहतर बनाया जाए।
यदि आप अपने ऐप के प्रदर्शन में सुधार करना चाहते हैं, तो सरल शुरुआत करें और जैसे-जैसे आगे बढ़ें, मापते रहें! अपने डेटाबेस प्रश्नों को साफ करें, फिर जहां भी आप कर सकते हैं AJAX अनुरोध बनाएं, और अंत में जितना संभव हो उतने विचारों को कैश करें। उसके बाद आप WebSockets और डेटाबेस कैशिंग पर जा सकते हैं।
हालांकि, सावधान रहें- अनुकूलन एक फिसलन ढलान है। हो सकता है कि आप खुद को मेरी तरह आदी पाएं!
पी.एस. उत्पादन में अपने रेल ऐप के प्रदर्शन की निगरानी के लिए, ऐपसिग्नल का एपीएम देखें - रूबी देवों द्वारा रूबी देवों के लिए बनाया गया।