Vaatamata oma arvukatele eelistele peetakse Ruby on Rails-d siiski suhteliselt aeglaseks veebiraamistikuks. Me kõik teame, et Twitter on lahkunud Railsist Scala kasuks. Kuid mõne nutika täiustusega saate oma rakendust oluliselt kiiremini käivitada!
Ruby First
Ruby on tugevalt objektorienteeritud keel. Tegelikult on (peaaegu) kõik, mis on Ruby on objekt. Ebavajalike objektide loomine võib maksta teie programmile palju lisamälu, seega peate seda vältima.
Erinevuse mõõtmiseks kasutame memory_profiler pärl ja sisseehitatud võrdlusmoodul, et mõõta aja jõudlust.
Kasuta bang! meetodeid stringide puhul
nõuda "memory_profiler"
report = MemoryProfiler.report do
data = "X" * 1024 * 1024 * 100
data = data.downcase
end
report.pretty_print
Alljärgnevas loetelus lõime 100MB suuruse stringi ja vähendasime iga selles sisalduvat märki. Meie võrdlusuuring annab meile järgmise aruande:
Kokku eraldatud: 210765044 baiti (6 objekti)
Kui me aga asendame rea 6 järgmisega:
data.downcase!
Loe faile rea kaupa
Väidetavalt on meil vaja hankida csv-failist 2 miljoni kirje suurune andmekogum. Tavaliselt näeb see välja nii:
nõuda 'benchmark'
Benchmark.bm do |x|
x.report do
File.readlines("2mrecords.csv").map! {|line| line.split(",")}
end
end
kasutaja süsteem kokku reaalne
12.797000 2.437000 15.234000 (106.319865)
Faili täielikuks allalaadimiseks kulus rohkem kui 106 sekundit. Päris palju! Kuid me saame seda protsessi kiirendada, kui asendame faili kaart! meetodi lihtsa samas kui loop:
nõuda 'benchmark'
Benchmark.bm do |x|
x.report do
file = File.open("2mrecords.csv", "r")
while line = file.gets
line.split(",")
end
end
end
kasutaja süsteem kokku reaalne
6.078000 0.250000 6.328000 ( 6.649422)
Nüüd on tööaeg drastiliselt langenud, kuna kaart! meetod kuulub konkreetsesse klassi, näiteks Hash#map või Array#map, kus Ruby salvestab iga analüüsitud faili rea mällu, niikaua kui seda täidetakse. Ruby prügikoguja ei vabasta mälu enne nende iteraatorite täielikku täitmist. Samas, lugedes seda rida-realt, GC see ümber paigutab mälu eelmistest ridadest, kui see pole vajalik.
Vältida meetodi iteraatorite kasutamist suuremate kogumite puhul
See on eelmise punkti laiendus, kus on üks tavalisem näide. Nagu ma mainisin, Ruby iteraatorid on objektimeetodid ja nad ei vabasta mälu seni, kuni neid täidetakse. Väikesel skaalal on erinevus mõttetu (ja meetodid nagu kaart tundub loetavam). Suuremate andmekogumite puhul on aga alati hea mõte kaaluda selle asendamist lihtsamate tsüklitega. Nagu alljärgnevas näites:
numberofelements = 10000000
randoms = Array.new(numberofelements) { rand(10) }
randoms.each do |line|
#teha midagi
end
ja pärast refaktoorimist:
numberofelements = 10000000
randoms = Array.new(numberofelements) { rand(10) }
while randoms.count > 0
line = randoms.shift
#egem midagi
end
"`
Kasutage String::<< meetodit
See on kiire, kuid eriti kasulik nõuanne. Kui lisate ühe stringi teisele, kasutades += operaatorit taga. Ruby loob täiendava objekti. Niisiis, see:
a = "X"
b = "Y"
a += b
Tegelikult tähendab see seda:
a = "X"
b = "Y"
c = a + b
a = c
Operaator väldiks seda, säästes teile veidi mälu:
a = "X"
b = "Y"
a << b
Räägime Railsist
The Rails raamistik omab palju "gotchas", mis võimaldaks teil optimeerida oma kood kiiresti ja ilma liigse lisapingutusteta.
Innukas laadimine AKA n+1 päringu probleem
Oletame, et meil on kaks seotud mudelit, Post ja Autor:
class Autor < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :author
end
Me tahame tuua kõik postitused meie kontrollerisse ja kuvada need vaatesse koos autoritega:
kontroller
def index
@posts = Post.all.limit(20)
end
view
Kontrollidaja, ActiveRecord loob ainult ühe päringu meie postituste leidmiseks. Kuid hiljem käivitab see ka veel 20 päringut, et leida iga autor vastavalt - see võtab täiendavalt aega! Õnneks on Railsil olemas kiire lahendus nende päringute ühendamiseks üheks päringuks. Kasutades sisaldab meetodit, võime oma kontrolleri ümber kirjutada nii:
def index
@posts = Post.all.includes(:author).limit(20)
end
Hetkel otsitakse ühte päringusse ainult vajalikud andmed.
Võite kasutada ka muid kalliskive, näiteks bullet kogu protsessi kohandamiseks.
Helistage ainult sellele, mida vajate
Teine kasulik tehnika ActiveRecordi kiiruse suurendamiseks on kutsuda ainult neid atribuute, mis on teie praeguste eesmärkide jaoks vajalikud. See on eriti kasulik, kui teie rakendus hakkab kasvama ja suureneb ka veergude arv tabeli kohta.
Võtame oma eelmise koodi näitena ja eeldame, et meil on vaja valida ainult autorite nimesid. Seega võime oma kontrolleri ümber kirjutada:
def index
@posts = Post.all.includes(:author).select("name").limit(20)
end
Nüüd anname meie kontrollerile korralduse jätta kõik atribuudid välja, välja arvatud see, mida me vajame.
Partiaalide õigesti esitamine
Oletame, et soovime luua oma postituste jaoks eraldi osa eelmistest näidetest:
Esmapilgul tundub see kood õige. Suurema arvu renderdatavate postituste puhul on kogu protsess siiski oluliselt aeglasem. Seda seetõttu, et Rööpad kutsub meie osalise uue iteratsiooniga uuesti esile. Me saame seda parandada, kasutades kollektsioonid funktsioon:
Nüüd, Rööpad leiab automaatselt välja, millist malli tuleks kasutada, ja initsialiseerib selle ainult üks kord.
Kasutage taustatöötlust
Iga protsess, mis on aeganõudvam ja mis ei ole teie praeguse töövoo jaoks oluline, võib olla hea kandidaat taustatöötluseks, nt e-kirjade saatmine, statistika kogumine või perioodiliste aruannete esitamine.
Sidekiq on kõige sagedamini kasutatav pärl taustatöötluseks. See kasutab Redis ülesannete salvestamiseks. Samuti võimaldab see teil kontrollida oma taustaprotsesside kulgu, jagada need eraldi järjekordadesse ja hallata mälukasutust igaühe kohta.
Kirjutage vähem koodi, kasutage rohkem kalliskive
Rööpad tuli välja tohutu hulk pärleid, mis mitte ainult ei tee teie elu lihtsamaks ja kiirendavad arendusprotsessi, vaid suurendavad ka teie rakenduse jõudluskiirust. Gemid nagu Devise või Pundit on tavaliselt oma kiiruse osas hästi testitud ning töötavad kiiremini ja turvalisemalt kui samaks otstarbeks spetsiaalselt kirjutatud kood.
Küsimuste korral parandada Rails jõudlus, reach The Codest insenerid välja, et konsulteerida oma kahtlustega.