Nepaisant daugybės privalumų, Ruby on Rails vis dar laikoma palyginti lėta žiniatinklio sistema. Visi žinome, kad "Twitter" paliko "Rails" ir pasirinko "Scala". Tačiau atlikę keletą gudrių patobulinimų galite paleisti savo programėlę gerokai greičiau!
Rubinas pirmas
Ruby yra daug objektų orientuota kalba. Tiesą sakant, (beveik) viskas Ruby yra objektas. Nereikalingų objektų kūrimas gali kainuoti programai daug papildomos atminties, todėl reikia to vengti.
Norint išmatuoti skirtumą, naudosime memory_profiler perlas ir integruotas lyginamosios analizės modulis, skirtas laiko našumui matuoti.
Naudokite "bang!" metodus eilutėms
reikalauti "memory_profiler"
report = MemoryProfiler.report do
duomenys = "X" * 1024 * 1024 * 100
data = data.downcase
pabaiga
report.pretty_print
Toliau pateiktame sąraše sukūrėme 100 MB eilutę ir sumažinome kiekvieną joje esantį simbolį. Mūsų lyginamasis rodiklis rodo, kad mus šią ataskaitą:
Iš viso skirta: 210765044 baitų (6 objektai)
Tačiau jei 6 eilutę pakeisime:
data.downcase!
Failų skaitymas eilutė po eilutės
Tariamai mums reikia iš csv failo gauti didžiulį 2 milijonų įrašų duomenų rinkinį. Paprastai tai atrodytų taip:
reikalauti 'benchmark'
Benchmark.bm do |x|
x.report do
File.readlines("2mrecords.csv").map! {|line| line.split(",")}
end
pabaiga
naudotojas sistema iš viso realus
12.797000 2.437000 15.234000 (106.319865)
Visiškai atsisiųsti failą prireikė daugiau nei 106 sekundžių. Gana daug! Tačiau šį procesą galime pagreitinti pakeisdami žemėlapis! metodą su paprastu o kilpa:
reikalauti 'benchmark'
Benchmark.bm do |x|
x.report do
file = File.open("2mrecords.csv", "r")
while line = file.gets
line.split(",")
end
end
end
naudotojas sistema iš viso realus
6.078000 0.250000 6.328000 ( 6.649422)
Nuo tada, kai buvo įdiegta žemėlapis! metodas priklauso konkrečiai klasei, pvz. Hash#map arba Array#map, kur Ruby atmintyje išsaugos kiekvieną parsiųstos rinkmenos eilutę, kol ji bus vykdoma. "Ruby" šiukšlių surinkėjas neatlaisvins atminties, kol šie iteratoriai nebus visiškai įvykdyti. Tačiau skaitant eilutę po eilutės, GC perskirstys atmintį iš ankstesnių eilučių, kai tai nėra būtina.
Venkite metodų iteratorių didesnėse kolekcijose
Šis punktas yra ankstesnio punkto tęsinys, kuriame pateikiamas dažniau pasitaikantis pavyzdys. Kaip jau minėjau, Ruby iteratoriai yra objektų metodai, todėl jie neatlaisvina atminties, kol yra atliekami. Nedideliu mastu šis skirtumas yra beprasmis (o metodai, pvz. žemėlapis atrodo lengviau skaitomas). Tačiau, kai kalbama apie didesnius duomenų rinkinius, visada verta apsvarstyti galimybę pakeisti jį paprastesnėmis kilpomis. Kaip toliau pateiktame pavyzdyje:
elementų skaičius = 10000000
randoms = Array.new(numberofelements) { rand(10) }
randoms.each do |line|
#do something
pabaiga
ir po refaktorizavimo:
elementų skaičius = 10000000
randoms = Array.new(numberofelements) { rand(10) }
while randoms.count > 0
line = randoms.shift
1TP69Darykite ką nors
pabaiga
"`
Naudokite String::<< metodą
Tai greitas, tačiau itin naudingas patarimas. Jei vieną eilutę pridedate prie kitos naudodami += operatorių už kadro. Ruby bus sukurtas papildomas objektas. Taigi, tai:
a = "X"
b = "Y"
a += b
Iš tikrųjų tai reiškia štai ką:
a = "X"
b = "Y"
c = a + b
a = c
Operatorius to išvengtų ir sutaupytų šiek tiek atminties:
a = "X"
b = "Y"
a << b
Pakalbėkime apie "Rails
Svetainė "Rails" sistema turi daug "Gothas", kuri leistų optimizuoti jūsų kodas greitai ir be didelių papildomų pastangų.
Itin skubus krovimas AKA n+1 užklausos problema
Tarkime, kad turime du susietus modelius: "Post" ir "Author":
klasė Author < ApplicationRecord
has_many :posts
end
klasė Post < ApplicationRecord
belong_to :author
end
Norime gauti visus įrašus iš mūsų valdiklio ir pateikti juos rodinyje su jų autoriais:
valdiklis
def index
@posts = Post.all.limit(20)
end
peržiūrėti
Valdiklyje, ActiveRecord sukursime tik vieną užklausą, kad rastume savo pranešimus. Tačiau vėliau ji taip pat sukurs dar 20 užklausų, kad surastų kiekvieną autorių - tai užims papildomai laiko! Laimei, "Rails" turi greitą sprendimą, kaip sujungti šias užklausas į vieną. Naudodami apima metodą, galime taip perrašyti savo valdiklį:
def index
@posts = Post.all.includes(:author).limit(20)
end
Kol kas į vieną užklausą bus paimti tik reikalingi duomenys.
Taip pat galite naudoti kitus brangakmenius, pvz. kulka pritaikyti visą procesą.
Skambinkite tik tam, ko reikia
Kitas naudingas metodas, padedantis padidinti "ActiveRecord" greitį, yra skambinti tik tiems atributams, kurie reikalingi dabartiniams tikslams. Tai ypač naudinga, kai jūsų programa pradeda augti ir didėja lentelės stulpelių skaičius.
Kaip pavyzdį paimkime ankstesnį kodą ir tarkime, kad mums reikia iš autorių išrinkti tik vardus. Taigi galime perrašyti savo valdiklį:
def index
@posts = Post.all.includes(:author).select("name").limit(20)
end
Dabar nurodome valdikliui praleisti visus atributus, išskyrus tą, kurio mums reikia.
Tinkamai atvaizduokite dalinius elementus
Tarkime, kad norime sukurti atskirą dalinį įrašams iš ankstesnių pavyzdžių:
Iš pirmo žvilgsnio šis kodas atrodo teisingas. Tačiau, kai reikia atvaizduoti daugiau pranešimų, visas procesas bus gerokai lėtesnis. Taip yra todėl, kad Bėgiai dar kartą iškviečia mūsų dalinį su nauja iteracija. Tai galime ištaisyti naudodami kolekcijos funkcija:
Dabar, Bėgiai automatiškai nustatys, kuris šablonas turėtų būti naudojamas, ir inicializuos jį tik vieną kartą.
Naudokite foninį apdorojimą
Kiekvienas procesas, kuris užima daugiau laiko ir nėra labai svarbus jūsų dabartiniam srautui, gali būti laikomas tinkamu kandidatu į foninį apdorojimą, pvz., el. laiškų siuntimas, statistinių duomenų rinkimas ar periodinių ataskaitų teikimas.
Sidekiq yra dažniausiai fono apdorojimui naudojamas brangakmenis. Jis naudoja Redis užduotims saugoti. Taip pat galite valdyti foninių procesų srautą, suskirstyti juos į atskiras eiles ir valdyti kiekvieno iš jų atminties naudojimą.
Rašykite mažiau kodo, naudokite daugiau brangakmenių
Bėgiai sugalvojo daugybę brangakmenių, kurie ne tik palengvina jūsų gyvenimą ir pagreitina kūrimo procesas, bet taip pat padidinsite savo programos našumo greitį. Tokie brangakmeniai kaip "Devise" ar "Pundit" paprastai yra gerai išbandyti dėl savo greičio ir veikia greičiau bei saugiau nei tam pačiam tikslui pagal užsakymą parašytas kodas.
Jei kiltų klausimų, kaip pagerinti "Rails" našumas, pasiekti The Codest inžinieriai pasitarti dėl savo abejonių.