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:
- https://www.rstudio.com/resources/videos/scaling-shiny-apps-with-async-programming/
- https://medium.com/@joe.cheng/async-programming-in-r-and-shiny-ebe8c5010790
- https://rstudio.github.io/promises/articles/shiny.html
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!
Érdekes téma, jó kis előadás. Gratulálok!