window.pipedriveLeadboosterConfig = { base: leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on juba olemas') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() HARGNEMINE JA LÕIMIMINE RUBIINIS - The Codest
The Codest
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Tööstusharud
    • Fintech & pangandus
    • E-commerce
    • Adtech
    • Healthtech
    • Tootmine
    • Logistika
    • Autotööstus
    • IOT
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
Tagasi nool TAGASI
2016-10-06
Tarkvaraarendus

HARGNEMINE JA LÕIMIMINE RUBY'S

Marek Gierlach

Nagu te ilmselt teate, on Ruby'l mitmeid implementatsioone, näiteks MRI, JRuby, Rubinius, Opal, RubyMotion jne, ja igaüks neist võib kasutada erinevat koodi täitmise mustrit. See artikkel keskendub kolmele esimesele neist ja võrdleb MRI

Nagu te ilmselt teate, on Ruby'l mitmeid implementatsioone, näiteks MRI, JRuby, Rubinius, Opal, RubyMotion jne, ja igaüks neist võib kasutada erinevat mustrit. kood täitmine. Selles artiklis keskendutakse kolmele esimesele neist ja võrreldakse MRI (praegu kõige populaarsem implementatsioon) JRuby ja Rubiniusega, käivitades mõned näidisskriptid, mis peaksid hindama forki ja keermestamise sobivust erinevates olukordades, näiteks protsessori intensiivsete algoritmide töötlemisel, failide kopeerimisel jne.Enne kui hakkate "õppima tehes", peate üle vaatama mõned põhiterminid.

Kahvel

  • on uus lapsprotsess (vanemprotsessi koopia).
  • on uus protsessi identifikaator (PID)
  • on eraldi mälu*
  • suhtleb teistega protsessidevahelise kommunikatsiooni (IPC) kanalite, näiteks sõnumijärjekordade, failide, sokkide jne kaudu.
  • on olemas ka siis, kui vanemprotsess lõpeb
  • on POSIX-kõne - töötab peamiselt Unixi platvormidel.

Teema

  • on "ainult" täitmiskontekst, mis töötab protsessis.
  • jagab kogu mälu teistega (vaikimisi kasutab see vähem mälu kui kahvel)
  • suhtleb teistega jagatud mäluobjektide kaudu
  • sureb protsessiga
  • toob kaasa tüüpilised mitmikeeramisprobleemid, nagu nälgimine, ummikseisud jne.

On palju vahendeid, mis kasutavad forke ja niite, mida kasutatakse igapäevaselt, nt Unicorn (forks) ja Puma (niidid) rakendusserverite tasandil, Resque (forks) ja Sidekiq (niidid) taustatööde tasandil jne.

Järgnevas tabelis on esitatud hargnemise ja lõimimise tugi peamistes Ruby implementatsioonides.

Ruby rakendamineForkingKeermestamine
MRIJahJah (piiratud GILiga**)
JRuby–Jah
RubiniusJahJah

Veel kaks maagilist sõna tulevad selles teemas tagasi nagu bumerang - paralleelsus ja samaaegsus - peame neid veidi selgitama. Esiteks ei saa neid mõisteid kasutada omavahel vahetatavalt. Lühidalt - paralleelsusest saame rääkida siis, kui kahte või enamat ülesannet töödeldakse täpselt samal ajal. Samaaegsus toimub siis, kui kahte või enamat ülesannet töödeldakse üksteisega kattuvas ajavahemikus (mitte tingimata samal ajal). Jah, see on lai seletus, kuid piisavalt hea, et aidata teil erinevust märgata ja ülejäänud artiklist aru saada.

Fronented aruanne 2020. aastaks

Järgnevas tabelis on esitatud paralleelsuse ja samaaegsuse toetus.

Ruby rakendamineParalleelsus (hargnemiste kaudu)Paralleelsus (niitide kaudu)Samaaegsus
MRIJahEiJah
JRuby–JahJah
RubiniusJahJah (alates versioonist 2.X)Jah

Sellega on teooria lõppenud - vaatame seda praktikas!

  • Eraldi mälu omamine ei pruugi põhjustada sama palju mälu tarbimist kui vanemprotsess. On olemas mõned mälu optimeerimise tehnikad. Üks neist on Copy on Write (CoW), mis võimaldab vanemprotsessil jagada eraldatud mälu lapsprotsessiga ilma seda kopeerimata. CoW puhul on lisamälu vaja ainult juhul, kui lapsprotsess muudab jagatud mälu. Ruby kontekstis ei ole kõik implementatsioonid CoW-sõbralikud, näiteks MRI toetab seda täielikult alates versioonist 2.X. Enne seda versiooni tarbis iga fork sama palju mälu kui vanemprotsess.
  • MRT üks suurimaid eeliseid/ puudusi (kustutage ebasobiv alternatiiv) on GILi (Global Interpreter Lock) kasutamine. Lühidalt öeldes vastutab see mehhanism niitide täitmise sünkroniseerimise eest, mis tähendab, et korraga saab teostada ainult ühte niiti. Aga oota... Kas see tähendab, et MRI-s pole mõtet niite üldse kasutada? Vastus tuleb GIL-i sisemuse mõistmisega... või vähemalt selles artiklis olevate koodinäidete vaatamisega.

Katsejuhtum

Selleks, et tutvustada, kuidas forking ja threading Ruby implementatsioonides toimib, lõin lihtsa klassi nimega Test ja mõned teised sellest pärinevamad. Igal klassil on erinev ülesanne, mida töödelda. Vaikimisi töötab iga ülesanne neli korda tsüklis. Samuti töötab iga ülesanne kolme tüüpi koodi täitmise vastu: järjestikune, hargnemisega ja niidiga. Lisaks, Benchmark.bmbm käivitab koodiploki kaks korda - esimest korda, et käivitada ja käivitada töökeskkond, teist korda, et mõõta. Kõik käesolevas artiklis esitatud tulemused saadi teise käivituse käigus. Loomulikult on isegi bmbm meetod ei garanteeri täiuslikku isolatsiooni, kuid erinevused mitme koodijooksu vahel on tähtsusetud.

nõuda "võrdlusalus"

klass Test
  AMOUNT = 4

  def run
    Benchmark.bmbm do |b|
      b.report("sequential") { sequential }
      b.report("forking") { forking }
      b.report("threading") { threading }
    end
  end

  private

  def sequential
    AMOUNT.times { perform }
  end

  def forking
    AMOUNT.times do
      fork do
        perform
      end
    end

    Process.waitall
  rescue NotImplementedError => e
    # fork meetod ei ole JRuby's saadaval
    puts e
  end

  def threading
    threads = []

    AMOUNT.times do
      threads << Thread.new do
        perform
      end
    end

    threads.map(&:join)
  end

  def perform
    raise "not implemented"
  end
end
Koormuse test

Käivitab arvutusi tsüklis, et tekitada suurt protsessorikoormust.

class LoadTest < Test
  def perform
    1000.times { 1000.times { 2**3**4 } }
  end
end

Käivitame selle...

LoadTest.new.run

...ja kontrollige tulemusi

MRIJRubyRubinius
järjestikune1.8629282.0890001.918873
kahvel0.945018–1.178322
keermestamine1.9139821.1070001.213315

Nagu näete, on järjestikuste sõitude tulemused sarnased. Loomulikult on lahenduste vahel väike erinevus, kuid see on tingitud valitud meetodite aluseks olevast rakendusest erinevates interpretaatorites.

Forking on antud näite puhul märkimisväärne jõudluse kasv (kood töötab peaaegu kaks korda kiiremini).

Keermestamine annab samasuguseid tulemusi nagu forking, kuid ainult JRuby ja Rubiniuse puhul. Proovi käivitamine niitidega MRI-l kulutab veidi rohkem aega kui järjestikune meetod. Sellel on vähemalt kaks põhjust. Esiteks, GIL sunnib järjestikuseid niite täitma, mistõttu täiuslikus maailmas peaks täitmisaeg olema sama, mis järjestikuse käivitamise puhul, kuid GILi operatsioonide (niitide vahel ümberlülitamine jne) puhul tekib ka ajakadu. Teiseks on vaja ka mõningaid üldkulusid niitide loomiseks.

See näide ei anna meile vastust küsimusele, milline on kasutussõnade mõte MRT-s. Vaatame teist.

Snooze test

Käivitab une meetodi.

class SnoozeTest < Test
  def perform
    sleep 1
  end
end

Siin on tulemused

MRIJRubyRubinius
järjestikune4.0046204.0060004.003186
kahvel1.022066–1.028381
keermestamine1.0015481.0040001.003642

Nagu näete, annavad mõlemad rakendused sarnaseid tulemusi mitte ainult järjestikuste ja hargnevate käivituste, vaid ka niitide puhul. Miks on siis MRI-l samasugune jõudluse kasv kui JRuby-l ja Rubiniusel? Vastus peitub implementatsioonis magada.

MRT magada meetod on rakendatud rb_thread_wait_for C-funktsioon, mis kasutab teist funktsiooni nimega native_sleep. Vaatame selle rakendamist (kood on lihtsustatud, algne rakendamine on leitav siin):

static void
native_sleep(rb_thread_t *th, struct timeval *timeout_tv)
{
  ...

  GVL_UNLOCK_BEGIN();
  {
    // tee siin mõned asjad
  }
  GVL_UNLOCK_END();

  thread_debug("native_sleep donen");
 }

Selle funktsiooni tähtsus seisneb selles, et lisaks range Ruby konteksti kasutamisele lülitub see ka süsteemi konteksti, et seal mõningaid operatsioone teha. Sellises olukorras ei ole Ruby protsessil midagi teha... Hea näide aja raiskamisest? Mitte päris, sest seal on GIL ütlus: "Selles niidis pole midagi teha? Vahetame teise ja tuleme mõne aja pärast siia tagasi". Seda võiks teha GILi lahti ja lukustades GILi koos GVL_UNLOCK_BEGIN() ja GVL_UNLOCK_END() funktsioonid.

Olukord muutub selgeks, kuid magada meetod on harva kasulik. Me vajame rohkem reaalseid näiteid.

Faili allalaadimise test

Käivitab protsessi, mis laeb alla ja salvestab faili.

nõuda "net/http"

class DownloadFileTest < Test
  def perform
    Net::HTTP.get("upload.wikimedia.org", "/wikipedia/commons/thumb/7/7/73/Ruby_logo.svg/2000px-Ruby_logo.svg.png")
  end
end

Järgmisi tulemusi ei ole vaja kommenteerida. Need on üsna sarnased eespool esitatud näite tulemustega.

1.003642JRubyRubinius
järjestikune0.3279800.3340000.329353
kahvel0.104766–0.121054
keermestamine0.0857890.0940000.088490

Teine hea näide võib olla faili kopeerimine või mõni muu I/O-operatsioon.

Järeldused

  • Rubinius toetab täielikult nii hargnemist kui ka lõimimist (alates versioonist 2.X, kui GIL eemaldati). Teie kood võib olla samaaegne ja töötada paralleelselt.
  • JRuby teeb head tööd niitidega, kuid ei toeta üldse hargnemist. Paralleelsust ja samaaegsust saaks saavutada niitidega.
  • MRI toetab hargnemist, kuid lõimimine on piiratud GILi olemasolu tõttu. Samaaegsus on võimalik saavutada niitide abil, kuid ainult siis, kui jooksev kood väljub Ruby interpretaatori kontekstist (nt IO operatsioonid, tuumafunktsioonid). Paralleelsust ei ole võimalik saavutada.

Seotud artiklid

Tarkvaraarendus

Tulevikukindlate veebirakenduste loomine: The Codest ekspertide meeskonna ülevaade

Avastage, kuidas The Codest paistab skaleeritavate, interaktiivsete veebirakenduste loomisel silma tipptehnoloogiatega, mis pakuvad sujuvat kasutajakogemust kõigil platvormidel. Saate teada, kuidas meie eksperditeadmised aitavad kaasa digitaalsele ümberkujundamisele ja äritegevusele...

THECODEST
Tarkvaraarendus

Top 10 Lätis asuvat tarkvaraarendusettevõtet

Tutvu Läti parimate tarkvaraarendusettevõtete ja nende innovaatiliste lahendustega meie viimases artiklis. Avastage, kuidas need tehnoloogiajuhid saavad aidata teie äri edendada.

thecodest
Enterprise & Scaleups lahendused

Java tarkvaraarenduse põhitõed: A Guide to Outsourcing Successfully

Tutvuge selle olulise juhendiga, kuidas edukalt outsourcing Java tarkvara arendada, et suurendada tõhusust, pääseda ligi eksperditeadmistele ja edendada projekti edu The Codest abil.

thecodest
Tarkvaraarendus

Ülim juhend Poola allhanke kohta

outsourcing kasv Poolas on tingitud majanduslikust, hariduslikust ja tehnoloogilisest arengust, mis soodustab IT kasvu ja ettevõtlussõbralikku kliimat.

TheCodest
Enterprise & Scaleups lahendused

Täielik juhend IT-auditi vahendite ja tehnikate kohta

IT-auditid tagavad turvalised, tõhusad ja nõuetele vastavad süsteemid. Lisateavet nende tähtsuse kohta leiate kogu artiklist.

The Codest
Jakub Jakubowicz CTO & kaasasutajad

Tellige meie teadmistebaas ja jääge kursis IT-sektori eksperditeadmistega.

    Meie kohta

    The Codest - rahvusvaheline tarkvaraarendusettevõte, mille tehnoloogiakeskused asuvad Poolas.

    Ühendkuningriik - peakorter

    • Büroo 303B, 182-184 High Street North E6 2JA
      London, Inglismaa

    Poola - kohalikud tehnoloogiakeskused

    • Fabryczna büroopark, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varssavi, Poola

      The Codest

    • Kodu
    • Meie kohta
    • Teenused
    • Case Studies
    • Tea kuidas
    • Karjäärivõimalused
    • Sõnastik

      Teenused

    • See nõuandev
    • Tarkvaraarendus
    • Backend arendus
    • Frontend arendus
    • Staff Augmentation
    • Backend arendajad
    • Pilveinsenerid
    • Andmeinsenerid
    • Muud
    • QA insenerid

      Ressursid

    • Faktid ja müüdid koostööst välise tarkvaraarenduspartneriga
    • USAst Euroopasse: Miks otsustavad Ameerika idufirmad Euroopasse ümber asuda?
    • Tech Offshore arenduskeskuste võrdlus: Euroopa (Poola), ASEAN (Filipiinid), Euraasia (Türgi).
    • Millised on CTO ja CIOde peamised väljakutsed?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. Kõik õigused kaitstud.

    etEstonian
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch elGreek etEstonian