Az eRum konferencia a második legnagyobb esemény az R programozás világában. Idén Budapest adott otthont a rendezvénynek, így nekem is nyílt lehetőségem előadni. Előadásom megtekinthető a youtubeon.

Miért?

Az R egy szálon futó (single threaded) nyelv, ezért ugyanarra az instance-ra érkező feladatok blokkolják egymást. Ez alap esetben nem okoz gondot, mert rövid feladatoknál csak millimásodperceket kell várni, ezért fel sem tűnik a felhasználónak.

Hosszabb feladatok futtatásánál viszont előfordulhat, hogy az egyik felhasználó (akár rövid, millimásodperces kérése) beragad egy hosszabb folyamat mögé. A rövid feladat futása csak akkor fog elkezdődni, amikor a sorban előtte lévő már befejeződött. Ez azt jelenti, hogy ha egy 0.1 mp alatt lefutó feladat a sorban egy 15 másodperces feladat mögé szorul (pl.: egy nagyobb csv fájl beolvasása miatt), akkor 15 másodpercig sorba áll, majd 0.1 mp alatt lefut, ez idő alatt a felhasználó pedig egyáltalán semmit nem tud csinálni.

Megfelelően loadbalance-olt alkalmazások esetén ez a blokkoló viselkedés ritkábban fordulhat elő, de az RStudio promises csomagja végleg megoldja a problémát. Az aszinkron futtatáshoz három csomag szükséges: a shiny aszinkron verziója, a future package és a promises package. Ezeket a csomagokat az alábbi utasításokkal installálhatjuk:

devtools::install_github("rstudio/promises")
devtools::install_github("rstudio/shiny")
install.packages("future")

Hogyan?

Egy standard (szinkron) hívást az alábbi módon írnánk meg: (csv fájl beolvasása, szűrés, majd oszlopkiválasztás)

library(dplyr)
read.csv("eRum.csv") %>%
  filter(talk_type == "shiny") %>%
  select(speaker_name)

 

Ugyanez a kód aszinkron hívás esetén így módosul:

future(read.csv("eRum.csv")) %...>%
  filter(talk_type == "shiny") %...>%
  select(speaker_name)

 

Az alapértelmezett (szinkron) hívást úgy tudjuk aszinkronná konvertálni, ha a lassan futó függvényt ‘future’ hívásba ágyazzuk, illetve  további függvényhívásokat intéző pipe operátort lecseréljük promise pipe operátorra (‘%…>%’).

Miért?

Ilyenkor a Shiny szerver egy teljesen új folyamatot indít a future package segítségével, majd amikor ez a folyamat végzett, akkor visszatér, és a szerver kiértékeli. Mivel külön szálon fut, így nem blokkolja más felhasználók folyamatait.

Ez a funkcionalitás csak különböző felhasználó session-ök között működnek (egyelőre). A felhasználónak, aki aszinkron módon hív meg egy függvényt, ugyanúgy meg kell várnia, amíg ez a folyamat lefut, mint szinkron mód esetén.

Demó

Összegzés

Összességében az aszinkron hívási mód kiváló lehetőséget biztosít a lassan futó függvényhívások loadbalance-olására, viszont nem használható a JavaScript-hez hasonló módon, egyazon felhasználó folyamatainak aszinkron menedzselésére.

További információk:

Ha tetszett a cikk, iratkozz fel hírlevelünkre (a jobb felső sarokban az „értesítésre” kattintva), vagy kövess minket LinkedIn és Facebook csatornákon!

Dávid Gyurkó

Author Dávid Gyurkó

More posts by Dávid Gyurkó

Join the discussion One Comment

Leave a Reply