Neraugoties uz daudzajām priekšrocībām, Ruby on Rails joprojām tiek uzskatīts par salīdzinoši lēnu tīmekļa sistēmu. Mēs visi zinām, ka Twitter ir atstājis Rails par labu Scala. Tomēr ar dažiem asprātīgiem uzlabojumiem jūs varat palaist savu lietotni ievērojami ātrāk!
Rubīns pirmais
Rubīns ir izteikti objektorientēta valoda. Patiesībā (gandrīz) viss Rubīns ir objekts. Nevajadzīgu objektu radīšana var radīt jūsu programmai daudz papildu atmiņas izmantošanas izmaksu, tāpēc no tā jāizvairās.
Lai izmērītu atšķirību, mēs izmantosim memory_profiler gem un iebūvētu Benchmark moduli, lai mērītu laika veiktspēju.
Sprieguma! metožu lietošana virknēm
pieprasīt "memory_profiler"
report = MemoryProfiler.report do
dati = "X" * 1024 * 1024 * 100
data = data.downcase
beigas
report.pretty_print
Tālāk sniegtajā sarakstā mēs izveidojām 100 MB lielu virkni un samazinājām katru tajā ietverto rakstzīmi. Mūsu etalons sniedz šādus rezultātus mums šādu ziņojumu:
Kopā piešķirts: 210765044 baiti (6 objekti)
Tomēr, ja 6. rindu aizstāsim ar:
data.downcase!
Failu lasīšana pa rindiņām
Domājams, mums ir nepieciešams no csv faila iegūt milzīgu datu kopumu ar 2 miljoniem ierakstu. Parasti tas izskatās šādi:
prasīt 'benchmark'
Benchmark.bm do |x|
x.report do
File.readlines("2mrecords.csv").map! {|line| line.split(",")}
beigas
beigas
lietotājs sistēma kopā real
12.797000 2.437000 15.234000 (106.319865)
Lai pilnībā lejupielādētu failu, bija nepieciešamas vairāk nekā 106 sekundes. Diezgan daudz! Bet mēs varam paātrināt šo procesu, aizstājot karte! metodi ar vienkāršu kamēr cilpa:
prasīt 'benchmark'
Benchmark.bm do |x|
x.report do
file = File.open("2mrecords.csv", "r")
while line = file.gets
line.split(",")
end
end
end
lietotājs sistēma kopā real
6.078000 0.250000 6.328000 ( 6.649422)
Darbības laiks tagad ir krasi samazinājies, jo karte! metode pieder konkrētai klasei, piemēram. Hash#map vai Array#map, kur Rubīns saglabās katru analizētā faila rindu atmiņā, kamēr vien tas tiek izpildīts. Ruby's garbage collector neatbrīvos atmiņu, pirms šie iteratori ir pilnībā izpildīti. Tomēr, lasot rindu pa rindai, GC pārvietos atmiņu no iepriekšējām rindām, ja tas nav nepieciešams.
Izvairīšanās no metožu iteratoriem lielākās kolekcijās
Šis punkts ir iepriekšējā punkta turpinājums ar biežāk sastopamu piemēru. Kā jau minēju, Rubīns iteratori ir objekta metodes, un tie neatbrīvo atmiņu, kamēr tiek izpildīti. Nelielā mērogā šī atšķirība ir bezjēdzīga (un metodes, piemēram. karte šķiet vieglāk lasāms). Tomēr, ja runa ir par lielākām datu kopām, vienmēr ir vērts apsvērt iespēju to aizstāt ar vienkāršākām cilpām. Piemēram, kā tālāk dotajā piemērā:
numberofelements = 10000000
randoms = Array.new(numberofelements) { rand(10) }
while randoms.count > 0
line = randoms.shift
#do something
beigas
"`
Izmantojiet metodi String::<<
Šis ir ātrs, bet īpaši noderīgs padoms. Ja pievienojat vienu virkni citai, izmantojot operatoru += aizkulisēs. Rubīns tiks izveidots papildu objekts. Tātad šis:
a = "X"
b = "Y"
a += b
Patiesībā tas nozīmē:
a = "X"
b = "Y"
c = a + b
a = c
Operators no tā izvairītos, ietaupot atmiņu:
a = "X"
b = "Y"
a << b
Parunāsim par Rails
Portāls Rails ietvars ir daudz "gotchas", kas ļautu optimizēt jūsu kods ātri un bez lielām papildu pūlēm.
Nepacietīga ielādēšana AKA n+1 vaicājuma problēma
Pieņemsim, ka mums ir divi saistītie modeļi - Post un Author:
klase Author < ApplicationRecord
has_many :posts
end
klase Post < ApplicationRecord
belong_to :author
end
Mēs vēlamies iegūt visus ierakstus mūsu kontrolierī un parādīt tos skatā ar to autoriem:
kontrolieris
def index
@posts = Post.all.limit(20)
end
apskatīt
Kontrolierī, ActiveRecord izveidos tikai vienu vaicājumu, lai atrastu mūsu ziņojumus. Bet vēlāk tas arī izraisīs vēl 20 vaicājumus, lai atrastu katru autoru, kas aizņems papildu laiku! Par laimi, Rails ir ātrs risinājums, kā apvienot šos pieprasījumus vienā. Izmantojot ietver metodi, mēs varam pārrakstīt mūsu kontrolieri šādi:
def index
@posts = Post.all.includes(:author).limit(20)
end
Pagaidām vienā vaicājumā tiks ielādēti tikai nepieciešamie dati.
Varat izmantot arī citus dārgakmeņus, piemēram. bullet pielāgot visu procesu.
Zvaniet tikai tam, kas jums nepieciešams
Vēl viens noderīgs paņēmiens ActiveRecord ātruma palielināšanai ir izsaukt tikai tos atribūtus, kas ir nepieciešami jūsu pašreizējiem mērķiem. Tas ir īpaši noderīgi, kad jūsu lietojumprogramma sāk augt un palielinās arī tabulu kolonnu skaits.
Kā piemēru ņemsim mūsu iepriekšējo kodu un pieņemsim, ka mums ir jāizvēlas tikai vārdi no autoriem. Tādējādi mēs varam pārrakstīt mūsu kontrolieri:
def index
@posts = Post.all.includes(:author).select("name").limit(20)
end
Tagad mēs uzdodam savam kontrolierim izlaist visus atribūtus, izņemot mums vajadzīgo.
Pareizi atveidot daļskaitļus
Pieņemsim, ka vēlamies izveidot atsevišķu daļēju sadaļu saviem ziņojumiem no iepriekšējiem piemēriem:
No pirmā acu uzmetiena šis kods izskatās pareizs. Tomēr, ja ir lielāks atveidojamo ziņojumu skaits, viss process būs ievērojami lēnāks. Tas ir tāpēc, ka Sliedes vēlreiz izsauc mūsu daļēju ar jaunu iterāciju. Mēs to varam labot, izmantojot kolekcijas funkcija:
Tagad, Sliedes automātiski noskaidros, kurš šablons jāizmanto, un inicializēs to tikai vienu reizi.
Fona apstrādes izmantošana
Katru procesu, kas aizņem vairāk laika un nav būtisks jūsu pašreizējai plūsmai, var uzskatīt par labu fona apstrādes kandidātu, piemēram, e-pasta vēstuļu sūtīšana, statistikas datu apkopošana vai periodisku pārskatu sniegšana.
Sidekiq ir visbiežāk izmantotais fona apstrādes dārgakmens. Tas izmanto Redis lai uzglabātu uzdevumus. Tā arī ļauj kontrolēt fona procesu plūsmu, sadalīt tos atsevišķās rindās un pārvaldīt atmiņas izmantošanu katram no tiem.
Rakstiet mazāk koda, izmantojiet vairāk dārgakmeņu
Sliedes nāca klajā ar milzīgu skaitu dārgakmeņiem, kas ne tikai atvieglo jūsu dzīvi un paātrina izstrādes process, bet arī palielināt lietojumprogrammas veiktspējas ātrumu. Tādi dārgakmeņi kā Devise vai Pundit parasti ir labi pārbaudīti attiecībā uz to ātrumu un darbojas ātrāk un drošāk nekā kods, kas rakstīts pēc pasūtījuma šim pašam mērķim.
Jautājumu gadījumā, lai uzlabotu Rails veiktspēja, sasniegt The Codest inženieri ārā, lai konsultētos par savām šaubām.