window.pipedriveLeadboosterConfig = { base: pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on jo olemassa') } 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 }) }, } } })() HAARAUTUMINEN JA SÄIKEISTÄMINEN RUBIINISSA - The Codest
Codest
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Toimialat
    • Fintech & pankkitoiminta
    • E-commerce
    • Adtech
    • Terveysteknologia
    • Valmistus
    • Logistiikka
    • Autoteollisuus
    • IOT
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
Takaisin nuoli PALAA TAAKSE
2016-10-06
Ohjelmistokehitys

HAARAUTUMINEN JA SÄIKEISTÄMINEN RUBYSSÄ

Marek Gierlach

Kuten luultavasti tiedät, Rubylla on useita toteutuksia, kuten MRI, JRuby, Rubinius, Opal, RubyMotion jne., ja kukin niistä voi käyttää erilaista koodin suoritusmallia. Tässä artikkelissa keskitytään kolmeen ensimmäiseen niistä ja vertaillaan MRI:tä ja

Kuten luultavasti tiedät, Rubylla on muutamia toteutuksia, kuten MRI, JRuby, Rubinius, Opal, RubyMotion jne., ja kukin niistä voi käyttää erilaista mallia ohjeiden koodi teloitus. Tässä artikkelissa keskitytään kolmeen ensimmäiseen ja vertaillaan MRI:tä (tällä hetkellä suosituin toteutus) JRubyyn ja Rubiniukseen ajamalla muutamia esimerkkiskriptejä, joiden tarkoituksena on arvioida haarautumisen ja säikeistyksen soveltuvuutta erilaisissa tilanteissa, kuten prosessori-intensiivisten algoritmien käsittelyssä, tiedostojen kopioinnissa jne.Ennen kuin aloitat "tekemällä oppimisen", sinun on kerrattava muutama perustermi.

Haarukka

  • on uusi lapsiprosessi (emoprosessin kopio).
  • on uusi prosessin tunniste (PID).
  • on erillinen muisti*
  • kommunikoi muiden kanssa prosessien välisten IPC-kanavien (inter-process communication), kuten viestijonojen, tiedostojen, pistorasioiden jne. välityksellä.
  • on olemassa, vaikka emoprosessi päättyy
  • on POSIX-kutsu - toimii pääasiassa Unix-alustoilla.

Lanka

  • on "vain" suorituskonteksti, joka toimii prosessin sisällä.
  • jakaa kaiken muistin muiden kanssa (oletusarvoisesti se käyttää vähemmän muistia kuin haarautuminen).
  • kommunikoi muiden kanssa jaettujen muistiobjektien avulla
  • kuolee prosessin myötä
  • aiheuttaa tyypillisiä monisäikeisyysongelmia, kuten nääntymistä, lukkiutumista jne.

On olemassa runsaasti haaroja ja säikeitä käyttäviä työkaluja, joita käytetään päivittäin, esimerkiksi Unicorn (haaroja) ja Puma (säikeitä) sovelluspalvelimien tasolla, Resque (haaroja) ja Sidekiq (säikeitä) taustatehtävien tasolla jne.

Seuraavassa taulukossa esitellään haarautumisen ja säikeistyksen tuki tärkeimmissä Ruby-toteutuksissa.

Ruby-toteutusHaarukkaKierteitys
MRIKylläKyllä (GIL:n rajoittamana**)
JRuby–Kyllä
RubiniusKylläKyllä

Kaksi muuta taikasanaa palaa kuin bumerangi tässä aiheessa - rinnakkaisuus ja samanaikaisuus - meidän on selitettävä niitä hieman. Ensinnäkin näitä termejä ei voi käyttää keskenään vaihdellen. Pähkinänkuoressa - voimme puhua rinnakkaisuudesta, kun kahta tai useampaa tehtävää käsitellään täsmälleen samaan aikaan. Rinnakkaisuus tapahtuu, kun kahta tai useampaa tehtävää käsitellään päällekkäisinä ajanjaksoina (ei välttämättä samanaikaisesti). Kyllä, tämä on laaja selitys, mutta riittävän hyvä, jotta huomaat eron ja ymmärrät tämän artikkelin loput.

Fronented-raportti vuodeksi 2020

Seuraavassa taulukossa esitetään rinnakkaisuuden ja samanaikaisuuden tuki.

Ruby-toteutusRinnakkaisuus (haarojen kautta)Rinnakkaisuus (säikeiden avulla)Samanaikaisuus
MRIKylläEiKyllä
JRuby–KylläKyllä
RubiniusKylläKyllä (versiosta 2.X lähtien)Kyllä

Teoria loppuu tähän - katsotaanpa sitä käytännössä!

  • Erillisen muistin käyttö ei välttämättä aiheuta sitä, että se kuluttaa saman verran muistia kuin emoprosessi. On olemassa joitakin muistin optimointitekniikoita. Yksi niistä on Copy on Write (CoW), jonka avulla emoprosessi voi jakaa varattua muistia lapsiprosessin kanssa kopioimatta sitä. CoW:n avulla lisämuistia tarvitaan vain silloin, kun lapsiprosessi muuttaa jaettua muistia. Rubyn osalta kaikki toteutukset eivät ole CoW-ystävällisiä, esimerkiksi MRI tukee sitä täysin versiosta 2.X lähtien. Ennen tätä versiota kukin haarautuminen kulutti yhtä paljon muistia kuin vanhempaprosessi.
  • Yksi magneettikuvauksen suurimmista eduista/haitoista (poista sopimaton vaihtoehto) on GIL:n (Global Interpreter Lock) käyttö. Lyhyesti sanottuna tämä mekanismi vastaa säikeiden suorituksen synkronoinnista, mikä tarkoittaa, että vain yhtä säiettä voidaan suorittaa kerrallaan. Mutta hetkinen... Tarkoittaako se, että säikeitä ei kannata käyttää MRI:ssä lainkaan? Vastaus tulee, kun ymmärtää GIL:n sisäiset asiat... tai ainakin vilkaisee tämän artikkelin koodinäytteitä.

Testitapaus

Esitelläkseni, miten haarautuminen ja säikeistäminen toimii Rubyn toteutuksissa, loin yksinkertaisen luokan nimeltä Testi ja muutama muu siitä periytyvä. Jokaisella luokalla on erilainen tehtävä. Oletusarvoisesti jokainen tehtävä suoritetaan neljä kertaa silmukassa. Jokainen tehtävä suoritetaan myös kolmea koodin suoritustapaa vastaan: peräkkäin, haarukoiden ja säikeiden kanssa. Lisäksi, Benchmark.bmbm suorittaa koodilohkon kahdesti - ensimmäisen kerran, jotta ajoympäristö saadaan käyttöön ja toimimaan, ja toisen kerran mittausta varten. Kaikki tässä artikkelissa esitetyt tulokset saatiin toisella ajokerralla. Tietenkin myös bmbm menetelmä ei takaa täydellistä eristystä, mutta useiden koodiajojen väliset erot ovat merkityksettömiä.

vaatia "benchmark"

luokka Testi
  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-metodi ei ole käytettävissä JRubyssä.
    puts e
  end

  def threading
    threads = []

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

    threads.map(&:join)
  end

  def perform
    raise "ei toteutettu"
  end
end
Kuormitustesti

Suorittaa laskutoimituksia silmukassa luodakseen suuren prosessorikuorman.

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

Käynnistetään se...

LoadTest.new.run

...ja tarkista tulokset

MRIJRubyRubinius
peräkkäiset1.8629282.0890001.918873
haarautuminen0.945018–1.178322
kierteitys1.9139821.1070001.213315

Kuten näet, peräkkäisten ajojen tulokset ovat samanlaisia. Ratkaisujen välillä on tietysti pieni ero, mutta se johtuu eri tulkkien valittujen menetelmien taustalla olevasta toteutuksesta.

Haarautuminen tuo tässä esimerkissä merkittävää suorituskykyhyötyä (koodi toimii lähes kaksi kertaa nopeammin).

Säikeistäminen antaa samanlaisia tuloksia kuin haarautuminen, mutta vain JRubylla ja Rubiniuksella. Näytteen ajaminen säikeiden kanssa MRI:ssä kuluttaa hieman enemmän aikaa kuin peräkkäinen menetelmä. Tähän on ainakin kaksi syytä. Ensinnäkin GIL pakottaa suorittamaan säikeet peräkkäin, joten täydellisessä maailmassa suoritusajan pitäisi olla sama kuin peräkkäisessä suorituksessa, mutta GIL-operaatioihin (säikeiden välillä vaihtaminen jne.) kuluu myös aikaa. Toiseksi säikeiden luomiseen kuluu myös jonkin verran aikaa.

Tämä esimerkki ei anna meille vastausta kysymykseen, mikä on käyttösäikeiden merkitys MRI:ssä. Katsotaanpa toinen esimerkki.

Torkkutesti

Suorittaa lepotilamenetelmän.

class SnoozeTest < Testi
  def perform
    sleep 1
  end
end

Tässä ovat tulokset

MRIJRubyRubinius
peräkkäiset4.0046204.0060004.003186
haarautuminen1.022066–1.028381
kierteitys1.0015481.0040001.003642

Kuten näet, kumpikin toteutus antaa samankaltaisia tuloksia paitsi peräkkäisissä ja haarautuvissa suorituksissa myös säikeistetyissä suorituksissa. Miksi MRI:llä on siis sama suorituskykyhyöty kuin JRubylla ja Rubiniuksella? Vastaus löytyy toteutuksesta nukkua.

Magneettikuvaus nukkua menetelmä on toteutettu rb_thread_wait_for C-funktio, joka käyttää toista funktiota nimeltä native_sleep. Katsotaanpa pikaisesti sen toteutusta (koodia on yksinkertaistettu, alkuperäinen toteutus löytyy osoitteesta täällä):

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

  GVL_UNLOCK_BEGIN();
  {
    // tee joitain juttuja täällä
  }
  GVL_UNLOCK_END();

  thread_debug("native_sleep donen");
 }

Tämä toiminto on tärkeä siksi, että sen lisäksi, että se käyttää tiukkaa Ruby-kontekstia, se myös vaihtaa järjestelmäkontekstiin suorittaakseen siellä joitakin toimintoja. Tällaisissa tilanteissa Ruby-prosessilla ei ole mitään tekemistä... Loistava esimerkki ajan tuhlaamisesta? Ei oikeastaan, koska on olemassa GIL:n sanonta: "Ei mitään tekemistä tässä säikeessä? Vaihdetaan toiseen ja palataan tänne hetken kuluttua". Tämä voitaisiin tehdä avaamalla ja lukitsemalla GIL:n lukitus komennolla GVL_UNLOCK_BEGIN() ja GVL_UNLOCK_END() toiminnot.

Tilanne tulee selväksi, mutta nukkua menetelmä on harvoin hyödyllinen. Tarvitsemme enemmän esimerkkejä todellisesta elämästä.

Tiedoston lataustesti

Käynnistää prosessin, joka lataa ja tallentaa tiedoston.

vaativat "net/http"

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

Seuraavia tuloksia ei tarvitse kommentoida. Ne ovat melko samanlaisia kuin edellä olevassa esimerkissä.

1.003642JRubyRubinius
peräkkäiset0.3279800.3340000.329353
haarautuminen0.104766–0.121054
kierteitys0.0857890.0940000.088490

Toinen hyvä esimerkki voisi olla tiedoston kopiointiprosessi tai jokin muu I/O-operaatio.

Päätelmät

  • Rubinius tukee täysin sekä haarautumista että säikeistämistä (versiosta 2.X lähtien, jolloin GIL poistettiin). Koodisi voi olla rinnakkaista ja toimia rinnakkain.
  • JRuby tekee hyvää työtä säikeiden kanssa, mutta ei tue haarautumista lainkaan. Rinnakkaisuus ja samanaikaisuus voitaisiin saavuttaa säikeillä.
  • MRI tukee haarautumista, mutta säikeistämistä rajoittaa GIL:n läsnäolo. Rinnakkaisuus voitaisiin saavuttaa säikeiden avulla, mutta vain silloin, kun suoritettava koodi menee Ruby-tulkin kontekstin ulkopuolelle (esim. IO-operaatiot, ytimen toiminnot). Rinnakkaisuutta ei ole mahdollista saavuttaa.

Aiheeseen liittyvät artikkelit

Ohjelmistokehitys

Tulevaisuuden web-sovellusten rakentaminen: The Codest:n asiantuntijatiimin näkemyksiä

Tutustu siihen, miten The Codest loistaa skaalautuvien, interaktiivisten verkkosovellusten luomisessa huipputeknologian avulla ja tarjoaa saumattomia käyttäjäkokemuksia kaikilla alustoilla. Lue, miten asiantuntemuksemme edistää digitaalista muutosta ja liiketoimintaa...

THECODEST
Ohjelmistokehitys

Top 10 Latviassa toimivaa ohjelmistokehitysyritystä

Tutustu Latvian parhaisiin ohjelmistokehitysyrityksiin ja niiden innovatiivisiin ratkaisuihin uusimmassa artikkelissamme. Tutustu siihen, miten nämä teknologiajohtajat voivat auttaa nostamaan liiketoimintaasi.

thecodest
Yritys- ja skaalausratkaisut

Java-ohjelmistokehityksen perusteet: A Guide to Outsourcing Successfully

Tutustu tähän keskeiseen oppaaseen Java-ohjelmistokehityksen onnistuneesta ulkoistamisesta tehokkuuden parantamiseksi, asiantuntemuksen saamiseksi ja projektin onnistumiseksi The Codestin avulla.

thecodest
Ohjelmistokehitys

Perimmäinen opas ulkoistamiseen Puolassa

Ulkoistamisen lisääntyminen Puolassa johtuu taloudellisesta, koulutuksellisesta ja teknologisesta kehityksestä, joka edistää tietotekniikan kasvua ja yritysystävällistä ilmapiiriä.

TheCodest
Yritys- ja skaalausratkaisut

Täydellinen opas IT-tarkastustyökaluihin ja -tekniikoihin

Tietotekniikan tarkastuksilla varmistetaan turvalliset, tehokkaat ja vaatimustenmukaiset järjestelmät. Lue lisää niiden merkityksestä lukemalla koko artikkeli.

Codest
Jakub Jakubowicz teknologiajohtaja ja toinen perustaja

Tilaa tietopankkimme ja pysy ajan tasalla IT-alan asiantuntemuksesta.

    Tietoa meistä

    The Codest - Kansainvälinen ohjelmistokehitysyritys, jolla on teknologiakeskuksia Puolassa.

    Yhdistynyt kuningaskunta - pääkonttori

    • Toimisto 303B, 182-184 High Street North E6 2JA
      Lontoo, Englanti

    Puola - Paikalliset teknologiakeskukset

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Krakova
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsova, Puola

      Codest

    • Etusivu
    • Tietoa meistä
    • Palvelut
    • Tapaustutkimukset
    • Tiedä miten
    • Työurat
    • Sanakirja

      Palvelut

    • Se neuvoa-antava
    • Ohjelmistokehitys
    • Backend-kehitys
    • Frontend-kehitys
    • Staff Augmentation
    • Backend-kehittäjät
    • Pilvi-insinöörit
    • Tietoinsinöörit
    • Muut
    • QA insinöörit

      Resurssit

    • Faktoja ja myyttejä yhteistyöstä ulkoisen ohjelmistokehityskumppanin kanssa
    • Yhdysvalloista Eurooppaan: Miksi amerikkalaiset startup-yritykset päättävät muuttaa Eurooppaan?
    • Tech Offshore -kehityskeskusten vertailu: Tech Offshore Eurooppa (Puola), ASEAN (Filippiinit), Euraasia (Turkki).
    • Mitkä ovat teknologiajohtajien ja tietohallintojohtajien tärkeimmät haasteet?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Verkkosivuston käyttöehdot

    Tekijänoikeus © 2025 by The Codest. Kaikki oikeudet pidätetään.

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